From 7bbd41e2f6a59273f9cab8527d8f463f4ed3977d Mon Sep 17 00:00:00 2001 From: alwkala Date: Wed, 2 Sep 2026 07:16:54 +0300 Subject: [PATCH] release(doc): v1.5.0 CDL v1.1.0, declarative decision gates & context delta resolution --- .tidyfactor | 6 +- CHANGELOG.md | 11 ++ brand.json | 2 +- dist/tidyfactor-doc.skill | Bin 64826 -> 65967 bytes dist/tidyfactor-doc/.tidyfactor | 6 +- dist/tidyfactor-doc/CHANGELOG.md | 11 ++ dist/tidyfactor-doc/brand.json | 2 +- dist/tidyfactor-doc/package.json | 3 +- .../references/workflows/collect.md | 78 ++++++++---- manifest.json | 117 +++++++++++++++--- package.json | 3 +- references/workflows/collect.md | 78 ++++++++---- 12 files changed, 241 insertions(+), 76 deletions(-) diff --git a/.tidyfactor b/.tidyfactor index 8099f8e..7b7e811 100644 --- a/.tidyfactor +++ b/.tidyfactor @@ -1,8 +1,8 @@ { "name": "tidyfactor-doc", - "version": "1.4.0", - "category": "architecture", - "description": "TidyFactor Doc - Code Documentation Builder & Dual-Engine Publishing Platform (MkDocs Material & Docsify)", + "version": "1.5.0", + "category": "development", + "description": "TidyFactor Doc — Code Documentation Builder & Dual-Engine Publishing Platform (MkDocs Material & Docsify) for AI Coding Agents", "repository": "https://github.com/TidyFactor/Doc", "npm": "@alwkala/tidyfactor-doc", "compatibility": [ diff --git a/CHANGELOG.md b/CHANGELOG.md index 70fb999..bdae747 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to `tidyfactor-doc` will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). +## [1.5.0] - 2026-09-02 + +### 🧠 Added — Contextual Decision Layer (CDL v1.1.0) & Declarative Decision Gates +- **Declarative Decision Gates (`manifest.json`)**: Added formal `decision_gates[]` declaration for the `init` command conforming to manifest schema v1.1.0, defining `doc_engine`, `target_scope`, and `audience_persona` with `track_staleness: true`. +- **Context Delta Resolution Engine (`references/workflows/collect.md`)**: Upgraded collect workflow to evaluate the mechanical Delta formula: + $$\text{Unknowns} = \text{Required Decisions} - (\text{Discovered Facts} \cup \text{Brain KIs})$$ +- **Interactive Disclosure & User Agency First**: Surfacing all genuine Unknowns interactively with structured options and recommendations. +- **Anti-Dual-Write Architecture**: Enforcing local markdown files under `docs/` as sole SSOT, with one-way outbound cloud sync via `--sync-brain`. + +--- + ## [1.4.0] - 2026-09-02 ### 🧠 Added — Sovereign Brain MCP Integration, Hygiene Auditor & Fail-Open Protocol diff --git a/brand.json b/brand.json index 6ef0b5e..b4e9b10 100644 --- a/brand.json +++ b/brand.json @@ -1,6 +1,6 @@ { "name": "TidyFactor Doc", - "version": "1.4.0", + "version": "1.5.0", "publisher": "TidyFactor Ecosystem", "partner": "Alwkala Digital Agency (https://alwkala.com)", "contact": { diff --git a/dist/tidyfactor-doc.skill b/dist/tidyfactor-doc.skill index 9d43655cd32644354e2402b0e5ea12450984b440..aa8dbcf08588d320cd43a9d11f26dd8fe1930931 100644 GIT binary patch delta 21356 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
  • ovRozt6sjfFNFrht2qt@>LqD5Vt3!$M=o$`RfThlw7N}x*dI1NcJ1<( z8>-evgz|IJdAQ4x2CYa9d7JucKkt(hHyy6v!OiqpOAF^3xL{}^)#@H|Tu<=51*BRu z4hBe#;A+u}*xV)u#j8-wOVQWq8syd&^jAKF6UG_9eL1Mneu+Am2W*scN*weNgr&|D zBnH~cZ)3dh#l})lM>Zd%$dZ|I;+HEYp2$E8B3&-vXHN}FmwiQXA>#u}7&aKS!o`ty z0?hOvgxsf$3@y_e)3)<2-<)v^bvwFm?mFo8WyhCIIU zfWQVwVRch!M)@W7lj@`1wHuEQ>dl;ih7MAfJ()RsW~t>_P@kT~-Tgsp?{N;2Ze1l7 z^BOWy3EZ#Y#+lq?8LXP;0%|5C#G^*fhOr^imhayWfU)~LcJ~`c|IyACXgUBR#efd| znhT-cZuBMSZ}U+=AiM(?gz})Ci16&~4C}Fae80Qag4h-1^}Ab~81URB&gq@b6BHKk zx_>>}vusDj-YoN&pRBp-%-HJ0RuIfWn7NLK_p6ouJ%q6#g_{=9{RoT(SMBG>$f&(w zBtI&@1Yvqt+u{9k`iya}NwAL@S^G;1nO5dNn@GqptoiSR#8n#?x%e*TY> zrV)WgJ#;|FFE~J$=4SlnII91uCdR0U2Dwa%r|XCvS0H<9h-m#~5cLEZcLt+}tWC_7 zMQ3*LywEZEL)cq#&L1jHmjjBxF_g;QrAoe2wR1>+;sfK&@Iyq-Li>)1rgi>VjPR|{ zc*k+2NoT7El=X!b@5@i7eetQs*}k6;8~m*1+R+}n)jq&9)eXTx3S+G!OIm~8In#9 zg+R=Rhok`{NDByYpWd)ef7x;K)YbcU{KV-mjUxB|J z8|v~B3Vj2AdgO7_lf5}=Iq?fNz{oFH9_?AMXk`F9kJiKwEosvc(|BSFRXvhSit>7- z*c2%{mRqQN1lMc}ca23O2bgmpANF^d`D{HNm9Po1x&Vp3coE6not?!`Ml!9Q%XLF$ zEN*r(o%ta*qo&gnlK!%s?6oU>3rgazXC_o(P*_1ead(rq=b?cJ(FqBWm$ZVgr=;A&0 zac?|4N#2;X=L${R0TJ$yj0sGjUNDH^(VX)`1rP=}d;}K0r^Ho7rC8yr8 zq_x;|`?Y1f{Puo!-rHSr_sXc+SxKH^k{FU+nj0WpCou`neGKGTM*$+a1wEa9*k3>~ zytqo6k`%cDfq67zpjfu(udAqQmB}M6xKJgKDdVnRK!mfy#793M_Fnltf9vwq7#KqI zY$C=>)xV=K~r=zkeo>f>~z}RC0?DeePXg(9;N;eiGIwD38YL+(^y2 z^tmJysX`w8@dKkdwdtozrFJD8zUY7&f_ffl^-yiAmc%m#G zJ2&oN^hxXQLaarV1E_9AIZJ*Fba?_)knQcm7S8nwQ1XOxoT6VBm4a6~Br&TePDYHI zdtuCKn*D~@r~Xi}2qA$y1+VKVSe&b3ruH-{Uo%HZ<8r(#9gYL0uk0HT9<6}8Ynx~E zfj8e_Il;y-8+qPrWj)VvOOH)p`#TI~I$Rg9-j^)18O1ykO{8CDv@{O}MEev5O_>_9 zKfhP9QUlz9F^6@spJ985^P|C+G~fyYoW`;I^<)%qqx4Xpv@liMe^pgC@`u^9Ln~18 z0`E*p81vK7B*o?|ObGU2a{*v&MI3*M6y2_u?QlmhG*7;Yh+P93Pec-P2NHBs0-?pI z7(Gbgw$y;-LW18fy1>U(zy;!f!|{lf#_&XhIHqAa8C1P6(yTtLEJ~82G1e^0HSmy# zq;yHrjr9#WBa|u%c8xfiP)!MqW9p}>XC)~Nr0^r&Uh6Llg7g+~`T_WAiJC&!^smMQ zNy}xz2uLlowA>Ehjq`YFe*D|iB zT6F_f3Ifu&{j_|A?E;wS>U}+4dnZ!tE%ffuq4d+TKhkGJ%()p!Pkv-DCmsALdBS?P z?IY6E5^p5W{TByUaqElJ&eJ~~u`%*Ge8MV9Qo`JRj1p|kle$xF z&UAOU%pJcGYx`2P$|l4v+YsLEtwJPu(C77WnhLM0XeWF$JZ#p|%O@%!nKh`mc;^xi zd8R*b0Wwh>X&1$p2*X>|CQz$oEmq-nzSUtv z7G;$XKdsm*l0Vi;nx&_fQTPY?Fi^h5mZ?t(l_sYd-gOUC6{Z%?2@;64shs?A)vJYf z&5LwIEDozq`A5c~^{YN(ZAu#^=4+)baGD=OVq}Nq?i{mbkS@Zq`Lg3bv|TUJb~dM| z^%yT69$P!R=Vn6z)kNTFbZdR%%2NTWOqdhW$mhs<%&tJ88P`6pvEsTon;N*!8XT*9 zVl1{(Qw9$VwY_7_vSc>OCu}8xf`oN=zFh?aa`S%a(u?EdqTMfdKN)INWQITt_`uXc zJ}{z}8Eow3BUl;*$l~PVv}2~7ah~yCWlK$S2QDBL+~P@~38%jLE-b4pRJzE?@hMlk z=rnj8hC256;ef4S{bP~5i%n2Hxoz`>{V zqdUYUKk7TY@J82Jvc8cMI#qAH$wkl#XZpa4Bp4Qj4Qx?`Sm-+b`vQO({a#vu-cfAnP;WvMd zC#g{a+YqstL3X1ZwJFvnuVditF=2e4)$@Y_D~iuQgG6L5`)QPpuCvaDe0Uw~A>_!) zMm2M-C%8Vq%KdPd^GMb)=sbS9xOc*sw(1nse@PIqjT{G5{Dt%P0+ucMDi+{F}q2<-h`pp)yfCO3439{E)_oC@6CWxe=YrSliDNSwG zJwMVuwmiH#d^LU2$?K-_s@EYjovcjWn}sz6C5rotP8T$oLkehg*`?prs6&vhYHaUJ zFxZG7SjPFbjU*Yz-Es@&IZ@5<998~g9dhoKsjNUwkDc??V!4TNo?Nf?-p~-OK8Fd* zDnbjfqJ^uy0LNj!R4e*z06MT|m--bi4>k5v8iYh+@`pNdLPe-6F__o#vj{Yp9so5G zAJ%t4Nanc+<}-Y%ekueb2P7^tdzFqk?9xnj@<7T$-;oQe_PMQL2)7!MYQ;&xbC0Lq zi_N?)tLJFWjQ2q24FUmbx-l{(-ir?H1j;}ScV^C{v+$ucrQGY~7ZJOY3(plPdPpV?Sc$N*gQS&!4jwHeNt=Y2J7>pc%Wv9FCnLpIlnJnWf_Tg^+%Uu#Po&teb z9B)YVZL!fxfH!4DoAt6Z)X6-kBy?6&(u@PW)1o<}owh!+W(KeRXKNjxF)hMAx( z^R9V$SyVmhjZoyR>;CjtjQi{a&c1-48GM_X@*g6O1RSkX=Qv51@5^0h5U&|O@P*i* zuW9Wm(edlz5yPv^zeRQy=WlA{fV*=+}AoQkn9a(xpV#OxpOnUV%jyN_@-Y+lu8dV>J>Y56TDY>HhhQE3Lix5hxqHoniOd+A#=_u3IQCRv z;6S^}YxU!w+`9H)7($ixiaNNdE&>&wjs_9^`_VN%6)feVo)>B@wdWH`s^q=V~gv#mK;z2#=(cWJBc)((MGKId0e@DD-!I&j@>!F%sBFuMfPR zD=^Q>$KZKbyb8;Y*?ke_E>Q{#7;8ABiGexZ81a>=l3%d76s6NO67M$K+i;7s6yK<4 zY3piYt9avHP-K61&(rX?;~@v~rtbsOxw+i#`XTo|xi^x%YTUmws2>5%q0Q$DTB3o# zvd_1tDv-#OP>xa7f(2&Sa1sIA(Hdc(bRppUHEYVD0FIF^r#ZWDkt(3}7#Uuay|(P6 z8ZmX#MDi-0oota2ai1HjGM;@CJ3>rr!nCk->|Vq5SN~ z!6dVa$C;HZZ5b=s{b`}EL^z*>l+F9Pxb;s(an2zS1f4fi42m<8{sf%}s_FZO988z@ z!6$+W@`#Ep50{>wsu>!5oE-i-y6MmjG3+wEVWM|^+YBNMFCNCITc={Z@?jzb=(YRNhwL0#dDQ+gx-$o=r+k6l7G94xm>rmT-cvf@E}Fe zgpxRH$W+M(IgG4H)Pv%~3dDOX#+ZI8qiUt-3H*eT>V7lhZ?P+cTSpjQ#!|*_v*vNV z|00X!(Bst4pbO{DpfJBV<} zd$8-0g3DPVp?En|c>EcGK!}FXj9RYTmHO2uqmvkBwn?#6{ji>9ZHe2A0Pe>W&ot~B z8Brivnv;wzBc;Gx87 ztCmu7SO%)~2nvPr=DQECa%?_+T%{c0*wI!BET))2y+NKi(S19cCqW>H%}!LmUPS?> z;MqBCpoIfWol^&hTwuHQUT}R*3Q!c;g2%s00a(lyd_aSH#kXJ&4f;uMK`B`V5Iv6t zLgltZr+IMzuSJ6bU?EK_rU!nW7lXn;wgmye+6Y`b!OwX@4+`vt{BDQ^o?Jizl4f8Y zt*=wy0v52`gc7LVwfBRxKrhm2(fNNzOnWa1=rRXgEfL_}MRwHxD_H-{EeiN*0ctK{ zQ9J9K|DFPh6&SH7wmFTYMI>N<5rl3a|Be#+0|}&TS-=y^ETHBOEHLy(+^}Z_Q)sG7 zcALIi49X8Vz|dh^ynLArJhOxaCY-lbSxYiNxy!alUBW@{fB{Qr&}^A^GngyONI=g0 zzjj(?BypJ?^{{ z$;~TB)Xw}(2t<4bc{XU9EWQdu{VV@$2iZ4dn_LmjBmU?7`1@~>zeB=5+IAdYMWQrl z&)*B<&ofWa_N(5qLm<*Sj?$a-i_8oj{|QH#(#Zc~hhVk^ZU|M)JL4Cb6MXR#3si24 z(QC56^s`?^6`(wOn^(Ffu=%a^t|0;IS2Qge6j*0R?c76yKqR*hvw0q;|Ce}mT@Dy4 z+455#g4Ko@Ol<-ohH7j+Y&9CSwL$l7SL+ia-MEu z2PS4&B_&i^V{Zz(yx{vloH=eep3vcCJ?-5Ro0R;ksyae%k7V.md` — that `generate` can turn into any doc type without re-deriving facts from the codebase itself. `` is the module, package, API surface, or component named by the request (or the whole project if none was named). -## Steps - -Run all five collection dimensions from `memory/collection-sources.md` against the target. Skip a dimension only if it genuinely doesn't apply (e.g., no Git history available for an uploaded snapshot) — note the skip and why, don't silently omit it. - -0. **Active Context Discovery & Brain MCP (Fail-Open)**: - - Silently check if project architecture KIs exist via `search_knowledge_base(query="architecture routes apis", scope="project")` when Brain MCP is active. - - If Brain MCP is absent or returns empty, proceed with 0ms delay directly to step 1. -1. **Code parsing.** Extract existing docblocks/comments, function/method/class signatures, exported types, and public surface area directly from source. Flag anything already documented inline so `generate` doesn't duplicate it. -2. **Commit history.** Read `git log` and any available PR descriptions for the target's files. Pull out *why* behind non-obvious code — rationale, past bugs fixed, deliberate tradeoffs — not just *what* changed. -3. **Runtime & environment.** Enumerate required environment variables, config files, software dependencies (with version constraints), and any stated hardware/resource limits. **MANDATORY**: Scrub and redact any actual secrets, production server IPs, database passwords, or private API tokens found in `.env` or config files—record only variable names, expected formats, and generic placeholder values. -4. **User persona tracing.** Identify who actually reads docs for this target — API consumers, internal maintainers, end-users — and note which facts matter to which persona (an internal maintainer needs the "why"; an API consumer needs the contract). -5. **Error patterns.** Collect how the code fails: thrown exceptions, error codes, logged failure messages, and how each is meant to be handled or surfaced. Scrub any sensitive runtime credentials or local workstation paths that appear inside logged messages. - -6. **Write the findings** to `docs/.collected/.md` as plain structured notes under five headings matching the dimensions above — this is source material for `generate`, not a finished doc, so skip prose polish. -7. **Update `docs/.doc-manifest.json`**: add `` to the `collected` section with a timestamp. -8. **Optional Brain Sync (`--sync-brain`)**: Persist extracted architecture facts via `extract_knowledge_item` per `20-brain-baas-integration.md`. - -## Validation checklist - -- [ ] `docs/.collected/.md` exists and has content (or an explicit "not applicable" note) under all five dimension headings -- [ ] Every fact traces to something actually found in the code, history, config, or logs — nothing inferred or assumed -- [ ] Zero sensitive data leaked: all real API keys, passwords, private IPs, and secrets are replaced with safe generic placeholders -- [ ] No local workstation drive paths (`C:\...`, `file:///...`) exist in findings; all paths are normalized to project-relative paths -- [ ] Deterministic audit passed via `python scripts/audit_docs.py docs/.collected/.md` -- [ ] `docs/.doc-manifest.json`'s `collected` section includes `` -- [ ] Findings are organized by dimension, not pre-formatted as any particular doc type +--- + +## 📋 Step 0: Context Delta Resolution & Auto-Sensing + +Before prompting the user for scope or parameters, execute the mechanical resolution formula: + +$$\text{Unknowns} = \text{Required Decisions} - (\text{Discovered Facts} \cup \text{Brain KIs})$$ + +1. **Auto-Sensing on Disk**: + - Inspect `mkdocs.yml`, `docs/index.html`, `docs/.doc-manifest.json`, and codebase structure. + - For sources marked with `track_staleness: true`, compare hash/mtime against stored snapshot. + - Any parameter resolved from disk is removed from $\text{Unknowns}$. + +2. **Fail-Open Brain MCP Acceleration**: + - Check if architecture KIs exist via `search_knowledge_base(query="architecture routes apis", scope="project")`. + - If Brain MCP is absent, offline, or returns empty, proceed with 0ms delay directly to Step 1 without warnings. + +--- + +## 🔍 Step 1: Codebase Collection Dimensions + +Run all five collection dimensions from `memory/collection-sources.md` against the target: + +1. **Code parsing**: Extract existing docblocks/comments, function/method/class signatures, exported types, and public surface area directly from source. Flag anything already documented inline. +2. **Commit history**: Read `git log` and available PR descriptions for target files. Pull out *why* behind non-obvious code (tradeoffs, rationale, bug fixes). +3. **Runtime & environment**: Enumerate required environment variables, config files, software dependencies (with version constraints), and resource limits. **MANDATORY**: Scrub and redact any actual secrets, production server IPs, database passwords, or private API tokens—record only variable names and generic placeholders. +4. **User persona tracing**: Identify who reads docs for this target (API consumers, internal maintainers, end-users) and map facts accordingly. +5. **Error patterns**: Collect how the code fails: thrown exceptions, error codes, logged failure messages, and resolution steps. Scrub local workstation paths. + +--- + +## 💾 Step 2: Persist Findings & Outbound Push + +1. Write structured notes to `docs/.collected/.md` under five headings matching the dimensions above. +2. Update `docs/.doc-manifest.json` with `` and timestamp. +3. Save local snapshot `.tidyfactor/doc-brief.snapshot.json` for deterministic drift detection. +4. **Anti-Dual-Write Outbound Push (`--sync-brain`)**: + - Local markdown files are the sole Single Source of Truth. + - When `--sync-brain` is explicitly provided, export extracted architecture facts to Brain MCP via `extract_knowledge_item`. + +--- + +## ## Validation checklist + +- [ ] Context Delta Resolution executed before prompting user. +- [ ] `docs/.collected/.md` exists and has content under all five dimension headings. +- [ ] Every fact traces to verified code, history, config, or logs — zero hallucination. +- [ ] Zero sensitive data leaked: all real API keys, passwords, private IPs, and secrets replaced with generic placeholders. +- [ ] No local workstation drive paths (`C:\...`, `file:///...`) exist; all paths are normalized to project-relative paths. +- [ ] Deterministic audit passed via `python scripts/audit_docs.py docs/.collected/.md`. +- [ ] `docs/.doc-manifest.json`'s `collected` section includes ``. +- [ ] Findings organized by dimension, not pre-formatted as any particular doc type. diff --git a/manifest.json b/manifest.json index 5927af8..88057ae 100644 --- a/manifest.json +++ b/manifest.json @@ -1,29 +1,118 @@ { - "$schema": "https://tidyfactor.com/schemas/skill-manifest.tools.schema.json", + "manifest_schema_version": "1.1.0", "skill_id": "tidyfactor-doc", - "version": "1.4.0", "skill_root_anchor": "self", "tools": [ { "name": "audit_docs", "description": "Audits documentation files under /docs for sensitive data leaks, banned absolute URLs, relative link integrity, and Docsify/MkDocs compliance.", - "runtime": "python", - "entrypoint": "scripts/audit_docs.py", - "args_schema": { - "type": "object", - "properties": { - "target": { - "type": "string", - "description": "Directory or markdown file path to audit (defaults to docs)" + "entrypoint": { + "runtime": "python3", + "script": "scripts/audit_docs.py" + }, + "invocation": { + "cli_pattern": "{runtime} {skill_root}/{script} {target_path} {flags}", + "args": [ + { + "name": "target", + "type": "path", + "required": false, + "default": "docs", + "description": "Directory or markdown file path to audit" }, - "json": { + { + "name": "json", "type": "boolean", + "required": false, + "default": false, + "flag": "--json", "description": "Output structured JSON report" } - } + ] + }, + "output": { + "format": "json", + "channel": "stdout" }, - "cli_pattern": "python {entrypoint} {target} --json", - "isolation_recommended": false + "runtime_requirements": { + "isolation_recommended": false, + "dependencies": [] + }, + "invoked_by_commands": ["generate", "site", "mkdocs", "docsify", "audit"] + } + ], + "decision_gates": [ + { + "command": "init", + "description": "Decision gate selecting documentation engine, navigation structure, and audience persona.", + "decisions": [ + { + "key": "doc_engine", + "description": "Target documentation publishing engine", + "type": "enum", + "options": ["mkdocs_material", "docsify_spa", "static_markdown"], + "default": "mkdocs_material", + "priority": 1, + "discovery": [ + { + "source": "local_file", + "path": "mkdocs.yml", + "track_staleness": true + }, + { + "source": "local_file", + "path": "docs/index.html", + "track_staleness": true + }, + { + "source": "brain_ki", + "ki_type": "project" + } + ], + "persist_to": { + "local": { "path": ".tidyfactor/doc-brief.snapshot.json" }, + "brain_ki": { + "sync_direction": "outbound_push_only", + "requires_flag": "--sync-brain" + } + } + }, + { + "key": "target_scope", + "description": "Scope of documentation generation", + "type": "enum", + "options": ["full_codebase", "api_surface_only", "developer_guide", "end_user_docs"], + "default": "full_codebase", + "priority": 2, + "discovery": [ + { + "source": "local_file", + "path": "docs/.doc-manifest.json" + } + ], + "persist_to": { + "local": { "path": ".tidyfactor/doc-brief.snapshot.json" } + } + }, + { + "key": "audience_persona", + "description": "Primary audience reading the documentation", + "type": "enum", + "options": ["api_consumer", "internal_maintainer", "end_user", "bilingual_developer"], + "default": "bilingual_developer", + "priority": 3, + "discovery": [ + { + "source": "local_file", + "path": "brand.json", + "json_path": "$.audience" + } + ], + "persist_to": { + "local": { "path": ".tidyfactor/doc-brief.snapshot.json" } + } + } + ] } ] } diff --git a/package.json b/package.json index 301d119..ab1df48 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tidyfactor/doc", - "version": "1.4.0", + "version": "1.5.0", "description": "TidyFactor Doc — Code Documentation Builder & Dual-Engine Publishing Platform (MkDocs Material & Docsify) for AI Coding Agents", "main": "SKILL.md", "bin": { @@ -50,6 +50,7 @@ "assets", "bin", "brand.json", + "manifest.json", "memory", "references", "scripts", diff --git a/references/workflows/collect.md b/references/workflows/collect.md index 35f2b7e..519c5d1 100644 --- a/references/workflows/collect.md +++ b/references/workflows/collect.md @@ -2,29 +2,55 @@ One outcome: a structured findings file — `docs/.collected/.md` — that `generate` can turn into any doc type without re-deriving facts from the codebase itself. `` is the module, package, API surface, or component named by the request (or the whole project if none was named). -## Steps - -Run all five collection dimensions from `memory/collection-sources.md` against the target. Skip a dimension only if it genuinely doesn't apply (e.g., no Git history available for an uploaded snapshot) — note the skip and why, don't silently omit it. - -0. **Active Context Discovery & Brain MCP (Fail-Open)**: - - Silently check if project architecture KIs exist via `search_knowledge_base(query="architecture routes apis", scope="project")` when Brain MCP is active. - - If Brain MCP is absent or returns empty, proceed with 0ms delay directly to step 1. -1. **Code parsing.** Extract existing docblocks/comments, function/method/class signatures, exported types, and public surface area directly from source. Flag anything already documented inline so `generate` doesn't duplicate it. -2. **Commit history.** Read `git log` and any available PR descriptions for the target's files. Pull out *why* behind non-obvious code — rationale, past bugs fixed, deliberate tradeoffs — not just *what* changed. -3. **Runtime & environment.** Enumerate required environment variables, config files, software dependencies (with version constraints), and any stated hardware/resource limits. **MANDATORY**: Scrub and redact any actual secrets, production server IPs, database passwords, or private API tokens found in `.env` or config files—record only variable names, expected formats, and generic placeholder values. -4. **User persona tracing.** Identify who actually reads docs for this target — API consumers, internal maintainers, end-users — and note which facts matter to which persona (an internal maintainer needs the "why"; an API consumer needs the contract). -5. **Error patterns.** Collect how the code fails: thrown exceptions, error codes, logged failure messages, and how each is meant to be handled or surfaced. Scrub any sensitive runtime credentials or local workstation paths that appear inside logged messages. - -6. **Write the findings** to `docs/.collected/.md` as plain structured notes under five headings matching the dimensions above — this is source material for `generate`, not a finished doc, so skip prose polish. -7. **Update `docs/.doc-manifest.json`**: add `` to the `collected` section with a timestamp. -8. **Optional Brain Sync (`--sync-brain`)**: Persist extracted architecture facts via `extract_knowledge_item` per `20-brain-baas-integration.md`. - -## Validation checklist - -- [ ] `docs/.collected/.md` exists and has content (or an explicit "not applicable" note) under all five dimension headings -- [ ] Every fact traces to something actually found in the code, history, config, or logs — nothing inferred or assumed -- [ ] Zero sensitive data leaked: all real API keys, passwords, private IPs, and secrets are replaced with safe generic placeholders -- [ ] No local workstation drive paths (`C:\...`, `file:///...`) exist in findings; all paths are normalized to project-relative paths -- [ ] Deterministic audit passed via `python scripts/audit_docs.py docs/.collected/.md` -- [ ] `docs/.doc-manifest.json`'s `collected` section includes `` -- [ ] Findings are organized by dimension, not pre-formatted as any particular doc type +--- + +## 📋 Step 0: Context Delta Resolution & Auto-Sensing + +Before prompting the user for scope or parameters, execute the mechanical resolution formula: + +$$\text{Unknowns} = \text{Required Decisions} - (\text{Discovered Facts} \cup \text{Brain KIs})$$ + +1. **Auto-Sensing on Disk**: + - Inspect `mkdocs.yml`, `docs/index.html`, `docs/.doc-manifest.json`, and codebase structure. + - For sources marked with `track_staleness: true`, compare hash/mtime against stored snapshot. + - Any parameter resolved from disk is removed from $\text{Unknowns}$. + +2. **Fail-Open Brain MCP Acceleration**: + - Check if architecture KIs exist via `search_knowledge_base(query="architecture routes apis", scope="project")`. + - If Brain MCP is absent, offline, or returns empty, proceed with 0ms delay directly to Step 1 without warnings. + +--- + +## 🔍 Step 1: Codebase Collection Dimensions + +Run all five collection dimensions from `memory/collection-sources.md` against the target: + +1. **Code parsing**: Extract existing docblocks/comments, function/method/class signatures, exported types, and public surface area directly from source. Flag anything already documented inline. +2. **Commit history**: Read `git log` and available PR descriptions for target files. Pull out *why* behind non-obvious code (tradeoffs, rationale, bug fixes). +3. **Runtime & environment**: Enumerate required environment variables, config files, software dependencies (with version constraints), and resource limits. **MANDATORY**: Scrub and redact any actual secrets, production server IPs, database passwords, or private API tokens—record only variable names and generic placeholders. +4. **User persona tracing**: Identify who reads docs for this target (API consumers, internal maintainers, end-users) and map facts accordingly. +5. **Error patterns**: Collect how the code fails: thrown exceptions, error codes, logged failure messages, and resolution steps. Scrub local workstation paths. + +--- + +## 💾 Step 2: Persist Findings & Outbound Push + +1. Write structured notes to `docs/.collected/.md` under five headings matching the dimensions above. +2. Update `docs/.doc-manifest.json` with `` and timestamp. +3. Save local snapshot `.tidyfactor/doc-brief.snapshot.json` for deterministic drift detection. +4. **Anti-Dual-Write Outbound Push (`--sync-brain`)**: + - Local markdown files are the sole Single Source of Truth. + - When `--sync-brain` is explicitly provided, export extracted architecture facts to Brain MCP via `extract_knowledge_item`. + +--- + +## ## Validation checklist + +- [ ] Context Delta Resolution executed before prompting user. +- [ ] `docs/.collected/.md` exists and has content under all five dimension headings. +- [ ] Every fact traces to verified code, history, config, or logs — zero hallucination. +- [ ] Zero sensitive data leaked: all real API keys, passwords, private IPs, and secrets replaced with generic placeholders. +- [ ] No local workstation drive paths (`C:\...`, `file:///...`) exist; all paths are normalized to project-relative paths. +- [ ] Deterministic audit passed via `python scripts/audit_docs.py docs/.collected/.md`. +- [ ] `docs/.doc-manifest.json`'s `collected` section includes ``. +- [ ] Findings organized by dimension, not pre-formatted as any particular doc type.