@cairnkeep/cli 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/AGENTS.md +45 -0
  2. package/CONTRIBUTING.md +49 -0
  3. package/LICENSE +201 -0
  4. package/README.md +149 -0
  5. package/SECURITY.md +37 -0
  6. package/bin/cairn +73 -0
  7. package/claude/agents/code-reviewer.md +174 -0
  8. package/claude/agents/security-investigator.md +112 -0
  9. package/claude/agents/security-target-selector.md +90 -0
  10. package/claude/agents/security-validator.md +97 -0
  11. package/claude/agents/wiki-ingester.md +108 -0
  12. package/claude/agents/wiki-lint-auditor.md +94 -0
  13. package/claude/agents/wiki-query-analyst.md +84 -0
  14. package/claude/commands/context-explore.md +40 -0
  15. package/claude/commands/graphify.md +150 -0
  16. package/claude/commands/memory-review.md +85 -0
  17. package/claude/commands/memory-sync.md +71 -0
  18. package/claude/commands/recall.md +32 -0
  19. package/claude/commands/remember.md +43 -0
  20. package/claude/commands/repo-review.md +191 -0
  21. package/claude/commands/security-audit.md +174 -0
  22. package/claude/commands/wiki-ingest.md +112 -0
  23. package/claude/commands/wiki-lint.md +86 -0
  24. package/claude/commands/wiki-query.md +92 -0
  25. package/claude/hooks/context-explore-pretask.sh +93 -0
  26. package/claude/hooks/memory-capture.sh +59 -0
  27. package/claude/hooks/memory-recall.sh +84 -0
  28. package/claude/hooks/memory-wakeup.sh +45 -0
  29. package/docs/building-an-overlay.md +117 -0
  30. package/docs/domain-knowledge.md +86 -0
  31. package/docs/git-providers.md +36 -0
  32. package/docs/operating.md +366 -0
  33. package/mcp-memory-server/dist/embeddings.js +122 -0
  34. package/mcp-memory-server/dist/explore-cache.js +97 -0
  35. package/mcp-memory-server/dist/index.js +1256 -0
  36. package/mcp-memory-server/package.json +36 -0
  37. package/opencode/agents/code-reviewer.md +173 -0
  38. package/opencode/agents/security-investigator.md +111 -0
  39. package/opencode/agents/security-target-selector.md +89 -0
  40. package/opencode/agents/security-validator.md +96 -0
  41. package/opencode/agents/wiki-ingester.md +107 -0
  42. package/opencode/agents/wiki-lint-auditor.md +93 -0
  43. package/opencode/agents/wiki-query-analyst.md +83 -0
  44. package/opencode/command/code-review.md +199 -0
  45. package/opencode/command/context-explore.md +42 -0
  46. package/opencode/command/graphify.md +153 -0
  47. package/opencode/command/memory-review.md +44 -0
  48. package/opencode/command/memory-sync.md +94 -0
  49. package/opencode/command/recall.md +38 -0
  50. package/opencode/command/remember.md +46 -0
  51. package/opencode/command/security-audit.md +80 -0
  52. package/opencode/command/wiki-ingest.md +55 -0
  53. package/opencode/command/wiki-lint.md +51 -0
  54. package/opencode/command/wiki-query.md +50 -0
  55. package/opencode/plugins/memory-capture.ts +188 -0
  56. package/opencode/plugins/memory-recall.ts +132 -0
  57. package/opencode/plugins/memory-wakeup.ts +102 -0
  58. package/opencode/templates/security-finding-register.yaml.template +51 -0
  59. package/opencode/templates/security-issue.md.template +43 -0
  60. package/opencode/templates/security-policy.md.template +29 -0
  61. package/opencode/templates/security-report.md.template +43 -0
  62. package/opencode/templates/wiki-contradictions.md.template +31 -0
  63. package/opencode/templates/wiki-index.md.template +40 -0
  64. package/opencode/templates/wiki-lint-report.md.template +38 -0
  65. package/opencode/templates/wiki-log.md.template +11 -0
  66. package/opencode/templates/wiki-policy.md.template +47 -0
  67. package/opencode/templates/wiki-query-answer.md.template +26 -0
  68. package/opencode/templates/wiki-source-summary.md.template +33 -0
  69. package/opencode/workflows/memory-review-workflow.md +66 -0
  70. package/opencode/workflows/security-audit-workflow.md +197 -0
  71. package/opencode/workflows/wiki-ingest-workflow.md +149 -0
  72. package/opencode/workflows/wiki-lint-workflow.md +128 -0
  73. package/opencode/workflows/wiki-query-workflow.md +122 -0
  74. package/package.json +56 -0
  75. package/scripts/bootstrap.sh +99 -0
  76. package/scripts/doctor.sh +91 -0
  77. package/scripts/install-audit-timer.sh +68 -0
  78. package/scripts/lib/assert-tool-event.mjs +50 -0
  79. package/scripts/memory-store.sh +71 -0
  80. package/scripts/memory-wiki-audit.sh +156 -0
  81. package/scripts/sync-claude-assets.sh +182 -0
  82. package/scripts/sync-opencode-explore-assets.sh +187 -0
  83. package/scripts/sync-opencode-graphify-assets.sh +152 -0
  84. package/scripts/sync-opencode-memory-assets.sh +160 -0
  85. package/scripts/sync-opencode-plugin-assets.sh +163 -0
  86. package/scripts/sync-opencode-security-assets.sh +195 -0
  87. package/scripts/sync-opencode-wiki-assets.sh +250 -0
  88. package/scripts/test-audit-timer.sh +29 -0
  89. package/scripts/test-bootstrap-untracked.sh +41 -0
  90. package/scripts/test-cli-dispatch.sh +21 -0
  91. package/scripts/test-doctor.sh +32 -0
  92. package/scripts/test-launcher-hooks.sh +66 -0
  93. package/scripts/test-memory-store.sh +44 -0
  94. package/scripts/test-remember-recall-assertions.sh +70 -0
  95. package/scripts/transcript-to-text.mjs +53 -0
  96. package/scripts/verify-docs-parity.sh +112 -0
  97. package/scripts/verify-explore-maturation.sh +288 -0
  98. package/scripts/verify-fastcontext-reliability.sh +624 -0
  99. package/scripts/verify-no-private-references.sh +145 -0
  100. package/scripts/verify-opencode-live-parity.sh +864 -0
  101. package/scripts/verify-routing-seam.sh +169 -0
  102. package/scripts/verify-token-savings-ab.sh +557 -0
  103. package/templates/PROJECT-INSTRUCTIONS.md.template +42 -0
  104. package/templates/alignment-gap-register.yaml.template +56 -0
  105. package/templates/alignment-policy.md.template +28 -0
  106. package/templates/alignment-pr-template.md.template +18 -0
  107. package/templates/alignment-report.md.template +56 -0
  108. package/templates/env.example.template +25 -0
  109. package/templates/graph-policy.md.template +37 -0
  110. package/templates/graphs-gitignore.template +3 -0
  111. package/templates/memory-wiki-audit.service.template +6 -0
  112. package/templates/memory-wiki-audit.timer.template +9 -0
  113. package/templates/memory.json.template +4 -0
  114. package/templates/planning-config.json.template +6 -0
  115. package/templates/project-brief.md.template +40 -0
  116. package/templates/security-finding-register.yaml.template +51 -0
  117. package/templates/security-issue.md.template +43 -0
  118. package/templates/security-policy.md.template +29 -0
  119. package/templates/security-report.md.template +43 -0
  120. package/templates/start-claude.sh.template +46 -0
  121. package/templates/start-opencode.sh.template +41 -0
  122. package/templates/structured-change-canvas.md.template +63 -0
  123. package/templates/wiki-contradictions.md.template +31 -0
  124. package/templates/wiki-index.md.template +40 -0
  125. package/templates/wiki-lint-report.md.template +38 -0
  126. package/templates/wiki-log.md.template +11 -0
  127. package/templates/wiki-policy.md.template +47 -0
  128. package/templates/wiki-query-answer.md.template +26 -0
  129. package/templates/wiki-source-summary.md.template +33 -0
@@ -0,0 +1,66 @@
1
+ <purpose>
2
+ Review memory candidates staged by the SessionEnd hook (memory-capture.sh) and
3
+ accept (write to AgentFS) or discard them. This is the accept gate between
4
+ autonomous extraction and durable writes.
5
+ </purpose>
6
+
7
+ <required_reading>
8
+ @$HOME/.config/opencode/templates/wiki-policy.md.template
9
+ </required_reading>
10
+
11
+ <process>
12
+
13
+ ## 0. Initialize Repo Context
14
+
15
+ Resolve the repo root and staging dir:
16
+
17
+ ```bash
18
+ ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
19
+ cd "$ROOT"
20
+ STAGING="$ROOT/.planning/memory-staging"
21
+ ```
22
+
23
+ Parse `--all` from `$ARGUMENTS` (default: newest session only).
24
+ If `$STAGING` is missing or has no `*.json`, report "No staged memory candidates to review" and stop.
25
+
26
+ ## 1. Load Staged Candidates
27
+
28
+ - default: read the newest `*.json` only
29
+ - `--all`: read every `*.json`, oldest first
30
+
31
+ Each file is the JSON from `mcp-memory-server extract`:
32
+ `{ model, count, candidates: [{ key, value, category, importance, rationale }] }`
33
+
34
+ ## 2. Review Each Candidate (judgment gate)
35
+
36
+ For each candidate, apply acceptance rules:
37
+ - **Accept**: durable, branch-safe, short fact/decision/pitfall/convention that future sessions benefit from and is not already in AgentFS. Check duplicates with `memory_search` on the candidate's key/terms.
38
+ - **Discard**: branch-local/speculative, a restatement of canonical code/config, trivial/transient, or already in AgentFS.
39
+
40
+ Classify scope: `project` (default), `domain-engineering` (reusable patterns), `identity` (user facts only).
41
+
42
+ ## 3. Write Accepted Candidates
43
+
44
+ For each accepted candidate, call the cairn-memory MCP:
45
+ ```
46
+ memory_write(scope="<scope>", key="<key>", value="<value>", promote_to="<category if applicable>")
47
+ ```
48
+ If it supersedes an existing entry (same key, updated value), use `memory_supersede(scope, key, value, reason)`.
49
+
50
+ ## 4. Clear Staging
51
+
52
+ Delete staged files whose candidates have been fully reviewed (accepted or discarded). With `--all`, clear the entire staging dir once done.
53
+
54
+ ## 5. Report
55
+
56
+ Summary: N reviewed, N accepted (→ AgentFS), N discarded, N superseded. Accepted facts are now durable across both harnesses.
57
+
58
+ </process>
59
+
60
+ <success_criteria>
61
+ - [ ] Staging dir read; candidates parsed
62
+ - [ ] Each candidate judged (durable, branch-safe, non-duplicate)
63
+ - [ ] Accepted candidates written via memory_write / memory_supersede
64
+ - [ ] Reviewed staging files cleared
65
+ - [ ] No speculative, branch-local, or trivial claims written to AgentFS
66
+ </success_criteria>
@@ -0,0 +1,197 @@
1
+ <purpose>
2
+ Run one governed local security assessment against the current repository. Select one narrow target, investigate it, validate at most one candidate finding, and preserve the outcome under `.planning/security/`.
3
+ </purpose>
4
+
5
+ <required_reading>
6
+ @$HOME/.config/opencode/templates/security-policy.md.template
7
+ @$HOME/.config/opencode/templates/security-report.md.template
8
+ @$HOME/.config/opencode/templates/security-finding-register.yaml.template
9
+ @$HOME/.config/opencode/templates/security-issue.md.template
10
+ </required_reading>
11
+
12
+ <available_agent_types>
13
+ Valid subagent types for this workflow:
14
+ - security-target-selector
15
+ - security-investigator
16
+ - security-validator
17
+ </available_agent_types>
18
+
19
+ <process>
20
+
21
+ ## 0. Initialize Repo Context
22
+
23
+ Resolve the repo root:
24
+
25
+ ```bash
26
+ ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
27
+ if [ -z "$ROOT" ]; then
28
+ echo "Not inside a git repository. /security-audit must run from a project repo."
29
+ exit 1
30
+ fi
31
+ cd "$ROOT"
32
+ ```
33
+
34
+ Parse flags from `$ARGUMENTS`:
35
+ - `--full`
36
+ - `--focus <path>`
37
+ - `--threat-model <name>`
38
+ - `--verify-only`
39
+ - `--create-confidential-issue`
40
+ - `--issue-project <group/project>`
41
+
42
+ Rules:
43
+ - `audit_mode` is `full` when `--full` is set, otherwise `diff`
44
+ - default `threat_model` to `changed-surface` when no explicit value is supplied
45
+ - `--issue-project` is optional metadata; do not fail the run only because it is missing
46
+
47
+ Capture:
48
+ - current UTC `timestamp`
49
+ - `branch`
50
+ - repo basename as `project_name`
51
+ - `default_branch` using `origin/HEAD`, then `origin/main`, `main`, `master`, then `HEAD`
52
+ - `base_ref` as `default_branch` in diff mode, otherwise `full-repo`
53
+ - `head_ref` as `branch`
54
+
55
+ Create directories:
56
+
57
+ ```bash
58
+ mkdir -p .planning/security/REPORTS .planning/security/CANDIDATES .planning/security/VALIDATED .planning/security/ISSUES .planning/security/tmp
59
+ ```
60
+
61
+ Scaffold when missing:
62
+ - `.planning/security/FINDINGS.yaml` from `security-finding-register.yaml.template` with project name and default branch filled in
63
+ - `.planning/security/POLICY.md` from `security-policy.md.template` with default branch filled in
64
+
65
+ Paths:
66
+ - `findings_path = {ROOT}/.planning/security/FINDINGS.yaml`
67
+ - `policy_path = {ROOT}/.planning/security/POLICY.md`
68
+ - `report_path = {ROOT}/.planning/security/REPORTS/{timestamp}.md`
69
+ - `candidate_path = {ROOT}/.planning/security/CANDIDATES/{timestamp}-candidate.md`
70
+
71
+ ## 1. Build The Audit Scope
72
+
73
+ Always read:
74
+ - `AGENTS.md` if present
75
+ - `.planning/security/POLICY.md`
76
+ - `.planning/security/FINDINGS.yaml`
77
+
78
+ Build `scope_summary`:
79
+ - in diff mode, summarize the changed surface from the current branch relative to `default_branch`, plus any staged or unstaged changes
80
+ - in full mode, summarize the main attack-surface-bearing directories and entrypoints
81
+ - when `--focus <path>` is present, keep the summary anchored to that path even in full mode
82
+
83
+ Build `changed_paths` as a concise path list for the selector.
84
+
85
+ ## 2. Choose One Target
86
+
87
+ Preferred path: spawn `security-target-selector`.
88
+
89
+ ```text
90
+ ◆ Selecting one high-signal security target...
91
+ ```
92
+
93
+ Spawn with:
94
+
95
+ ```text
96
+ Task(
97
+ prompt="Read $HOME/.config/opencode/agents/security-target-selector.md for instructions. FIRST ACTION: change into {ROOT}.\n\n<audit_assignment>\nproject_root: {ROOT}\naudit_mode: {audit_mode}\nfocus_path: {focus_path or \"null\"}\nthreat_model: {threat_model}\npolicy_path: {ROOT}/.planning/security/POLICY.md\nfindings_path: {ROOT}/.planning/security/FINDINGS.yaml\nscope_summary: {scope_summary}\nchanged_paths: {changed_paths}\n</audit_assignment>",
98
+ subagent_type="security-target-selector",
99
+ description="Security audit: target selector"
100
+ )
101
+ ```
102
+
103
+ If the selector returns `NO_TARGET`:
104
+ - write `report_path` from `security-report.md.template`
105
+ - set accepted and rejected counts to `0`
106
+ - explain that no grounded target was selected for this run
107
+ - stop after reporting the result in chat
108
+
109
+ ## 3. Investigate The Target
110
+
111
+ Preferred path: spawn `security-investigator`.
112
+
113
+ ```text
114
+ ◆ Investigating selected target...
115
+ ```
116
+
117
+ Spawn with:
118
+
119
+ ```text
120
+ Task(
121
+ prompt="Read $HOME/.config/opencode/agents/security-investigator.md for instructions. FIRST ACTION: change into {ROOT}.\n\n<audit_assignment>\nproject_root: {ROOT}\naudit_mode: {audit_mode}\nthreat_model: {threat_model}\nselected_file: {selected_file}\ninvestigation_target: {investigation_target}\nlikely_entry_point: {likely_entry_point}\nrisk_class: {risk_class}\npolicy_path: {ROOT}/.planning/security/POLICY.md\nfindings_path: {ROOT}/.planning/security/FINDINGS.yaml\ncandidate_path: {ROOT}/.planning/security/CANDIDATES/{timestamp}-candidate.md\n</audit_assignment>",
122
+ subagent_type="security-investigator",
123
+ description="Security audit: investigator"
124
+ )
125
+ ```
126
+
127
+ If the investigator returns `NO_FINDING`:
128
+ - write `report_path` with `Accepted findings: 0` and `Rejected candidates: 1`
129
+ - include the rejection reason and the candidate path
130
+ - stop after reporting the result in chat
131
+
132
+ ## 4. Validate The Candidate
133
+
134
+ Compute `next_finding_id` from `.planning/security/FINDINGS.yaml` by taking the next unused `SEC-xxxx` identifier.
135
+
136
+ Preferred path: spawn `security-validator`.
137
+
138
+ ```text
139
+ ◆ Validating candidate against exploitability and duplicate bars...
140
+ ```
141
+
142
+ Spawn with:
143
+
144
+ ```text
145
+ Task(
146
+ prompt="Read $HOME/.config/opencode/agents/security-validator.md for instructions. FIRST ACTION: change into {ROOT}.\n\n<audit_assignment>\nproject_root: {ROOT}\npolicy_path: {ROOT}/.planning/security/POLICY.md\nfindings_path: {ROOT}/.planning/security/FINDINGS.yaml\ncandidate_path: {ROOT}/.planning/security/CANDIDATES/{timestamp}-candidate.md\nnext_finding_id: {next_finding_id}\nvalidated_dir: {ROOT}/.planning/security/VALIDATED\n</audit_assignment>",
147
+ subagent_type="security-validator",
148
+ description="Security audit: validator"
149
+ )
150
+ ```
151
+
152
+ ## 5. Write Durable Outcome
153
+
154
+ Always write `report_path` from `security-report.md.template` and fill:
155
+ - project name, audit scope, base ref, head ref, threat model, focus path, timestamp
156
+ - selected file and investigation target when a target existed
157
+ - accepted and rejected counts
158
+ - accepted finding details when validation accepted a finding
159
+ - rejection rationale when the run ended with a rejected candidate
160
+
161
+ If validation returned `ACCEPTED`:
162
+ - if `--verify-only` is not set, append one new entry to `.planning/security/FINDINGS.yaml`
163
+ - keep the entry concise and consistent with the existing ledger shape
164
+ - include the validated report path under `evidence.reports` and `validation.report_path`
165
+ - set `last_security_audit.at`, `last_security_audit.branch`, and `last_security_audit.report`
166
+
167
+ If validation returned `REJECTED`:
168
+ - do not mutate `.planning/security/FINDINGS.yaml`
169
+
170
+ ## 6. Optional Confidential Issue Draft
171
+
172
+ If `--create-confidential-issue` is set and validation returned `ACCEPTED`:
173
+ - write `.planning/security/ISSUES/{timestamp}-confidential-issue.md` from `security-issue.md.template`
174
+ - fill `issue-project` when provided, otherwise use `unassigned`
175
+ - preserve the validated report path and audit report path in the draft
176
+ - treat the markdown draft as the durable artifact even if no external tracker is updated in this run
177
+
178
+ ## 7. Report Results
179
+
180
+ In chat:
181
+ - state whether the run ended with `accepted`, `rejected`, or `no target`
182
+ - show the selected file and investigation target when applicable
183
+ - link the durable report path
184
+ - mention the candidate path and validated path when they exist
185
+ - mention whether `.planning/security/FINDINGS.yaml` was updated or skipped because of `--verify-only`
186
+
187
+ </process>
188
+
189
+ <success_criteria>
190
+ - [ ] Repo root resolved and `.planning/security/` scaffold exists
191
+ - [ ] Exactly one target selected or explicitly rejected as unnecessary
192
+ - [ ] Candidate report written for investigated runs
193
+ - [ ] Candidate validated against duplicate and reachability bars
194
+ - [ ] Durable report written under `.planning/security/REPORTS/`
195
+ - [ ] Findings ledger updated only for accepted findings and only when not in `--verify-only` mode
196
+ - [ ] Optional confidential issue draft written when requested and an accepted finding exists
197
+ </success_criteria>
@@ -0,0 +1,149 @@
1
+ <purpose>
2
+ Compile one canonical source into the repo-local project wiki while keeping raw sources authoritative. Produce or refresh a source summary under `.planning/wiki/sources/`, update `.planning/wiki/index.md`, and append `.planning/wiki/log.md`.
3
+ </purpose>
4
+
5
+ <required_reading>
6
+ @$HOME/.config/opencode/templates/wiki-policy.md.template
7
+ @$HOME/.config/opencode/templates/wiki-index.md.template
8
+ @$HOME/.config/opencode/templates/wiki-log.md.template
9
+ @$HOME/.config/opencode/templates/wiki-source-summary.md.template
10
+ </required_reading>
11
+
12
+ <available_agent_types>
13
+ Valid GSD subagent types (use exact names — do not fall back to 'general-purpose'):
14
+ - wiki-ingester
15
+ </available_agent_types>
16
+
17
+ <process>
18
+
19
+ ## 0. Initialize Repo Context
20
+
21
+ Resolve the repo root:
22
+
23
+ ```bash
24
+ ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
25
+ if [ -z "$ROOT" ]; then
26
+ echo "Not inside a git repository. /wiki-ingest must run from a project repo."
27
+ exit 1
28
+ fi
29
+ cd "$ROOT"
30
+ ```
31
+
32
+ Parse arguments from `$ARGUMENTS`:
33
+ - require exactly one non-flag argument as `source_input`
34
+ - reject empty input or multiple positional arguments with a clear error
35
+ - capture an optional `--refresh` flag into `refresh_mode` (default false)
36
+
37
+ Capture:
38
+ - current UTC `timestamp`
39
+ - `branch`
40
+ - repo basename as `project_name`
41
+ - `default_branch` using `origin/HEAD`, then `origin/main`, `main`, `master`, then `HEAD`
42
+
43
+ Resolve `source_input`:
44
+ 1. if it is an existing absolute path, use it as `source_abs`
45
+ 2. else if `$ROOT/$source_input` exists, use that path
46
+ 3. else stop with a clear error
47
+
48
+ Derive:
49
+ - `source_rel` when the file is inside the repo, otherwise use the absolute path
50
+ - `source_slug` from the relative path or basename, normalized to lowercase kebab case
51
+ - `source_kind` as one of `repo_doc`, `repo_code`, `repo_config`, `external_doc`, or `generated_or_binary`
52
+ - `source_page_path = {ROOT}/.planning/wiki/sources/{source_slug}.md`
53
+
54
+ Create directories:
55
+
56
+ ```bash
57
+ mkdir -p .planning/wiki/sources .planning/wiki/topics .planning/wiki/entities .planning/wiki/queries .planning/wiki/REPORTS .planning/wiki/tmp
58
+ ```
59
+
60
+ Scaffold files when missing:
61
+ - `.planning/wiki/index.md` from `wiki-index.md.template` with project name filled in
62
+ - `.planning/wiki/log.md` from `wiki-log.md.template`
63
+ - `.planning/wiki/POLICY.md` from `wiki-policy.md.template` with project name and default branch filled in
64
+
65
+ ## 1. Gather Canonical Context
66
+
67
+ Before any synthesis:
68
+ - read `AGENTS.md` if present
69
+ - read `.planning/wiki/POLICY.md`
70
+ - read `.planning/wiki/index.md`
71
+ - read the target source directly
72
+ - read nearby repo docs only when needed to disambiguate the source
73
+
74
+ Truth rules:
75
+ - the target source is canonical for its own content
76
+ - the wiki is derived and may summarize or cross-link, but must not replace the source
77
+ - when the source is code, do not paraphrase the whole file or create a fake per-file manual; extract only stable interfaces, invariants, behaviors, or references worth reusing
78
+ - if the source is generated, vendored, or mostly binary, write a minimal source note that points back to the canonical path and explains why no richer summary was created
79
+
80
+ ## 2. Write Or Refresh The Source Summary
81
+
82
+ In `refresh_mode` (the `--refresh` flag was passed):
83
+ - the source page must already exist at `source_page_path`; if it does not, fall back to a normal ingest and note this in the log
84
+ - pass `refresh_mode: true` to the `wiki-ingester` assignment so it re-reads the canonical source, updates only the stable facts that changed, preserves the existing page structure and unchanged facts, bumps `Last reviewed` to the current timestamp, re-evaluates the `Contradictions And Freshness Notes` section, and logs the action as `wiki-refresh`
85
+ - refresh is the primary maintenance loop: run it whenever the MR/PR, code, or doc behind a page changes, so the derived wiki tracks state instead of going stale
86
+
87
+ Default path (no `--refresh`): spawn `wiki-ingester`.
88
+
89
+ ```text
90
+ ◆ Compiling wiki source summary...
91
+ ```
92
+
93
+ Spawn with:
94
+
95
+ ```text
96
+ Task(
97
+ prompt="Read $HOME/.config/opencode/agents/wiki-ingester.md for instructions. FIRST ACTION: change into {ROOT}.\n\n<wiki_assignment>\nproject_root: {ROOT}\nsource_abs: {source_abs}\nsource_rel: {source_rel}\nsource_kind: {source_kind}\nsource_page_path: {ROOT}/.planning/wiki/sources/{source_slug}.md\nindex_path: {ROOT}/.planning/wiki/index.md\nlog_path: {ROOT}/.planning/wiki/log.md\npolicy_path: {ROOT}/.planning/wiki/POLICY.md\ntimestamp: {timestamp}\nbranch: {branch}\nproject_name: {project_name}\nrefresh_mode: {refresh_mode}\n</wiki_assignment>",
98
+ subagent_type="wiki-ingester",
99
+ description="Wiki: source ingester"
100
+ )
101
+ ```
102
+
103
+ If Task/subagent execution is unavailable:
104
+ - run the ingester role inline
105
+ - still write the source page and update index/log
106
+
107
+ ## 3. Conservative Topic And Entity Maintenance
108
+
109
+ After the source page exists:
110
+ - create or update a topic page under `.planning/wiki/topics/` only if the source adds a durable concept that already appears across multiple sources or repeated queries
111
+ - create or update an entity page under `.planning/wiki/entities/` only if the source identifies a stable interface, component, owner, or bounded concept that improves cross-linking
112
+ - every new topic or entity page must:
113
+ - stay shorter than the combined raw sources it points to
114
+ - include `Last reviewed`
115
+ - include canonical source references
116
+ - call out contradictions or freshness uncertainty explicitly
117
+
118
+ Do not:
119
+ - create topic or entity pages for every file
120
+ - mirror whole code modules into wiki pages
121
+ - hide uncertainty behind definitive language
122
+
123
+ ## 4. Update Index And Log
124
+
125
+ Ensure:
126
+ - the source page is linked once in the `Sources` section of `.planning/wiki/index.md`
127
+ - if `<!-- wiki:sources:start -->` and `<!-- wiki:sources:end -->` exist, update only inside that block and replace `- None yet.` when adding the first real entry
128
+ - any created topic or entity page is linked once in the correct section, using the matching marker blocks when present
129
+ - `.planning/wiki/log.md` gets one new append-only entry with timestamp, command, source path, pages touched, and whether the run stayed in conservative code-summary mode
130
+ - in `refresh_mode`, log the action as `wiki-refresh` (not `wiki-ingest`) so the maintenance loop is distinguishable from first-time ingests
131
+ - if `<!-- wiki:entries:start -->` and `<!-- wiki:entries:end -->` exist, append inside that block
132
+
133
+ ## 5. Report Results
134
+
135
+ Display:
136
+ - source page path
137
+ - any topic or entity pages updated
138
+ - a short note that raw sources remain canonical
139
+
140
+ </process>
141
+
142
+ <success_criteria>
143
+ - [ ] Repo root resolved and wiki scaffold created if missing
144
+ - [ ] Canonical source resolved from the input path
145
+ - [ ] One source summary page written or refreshed under `.planning/wiki/sources/`
146
+ - [ ] Index updated
147
+ - [ ] Log appended
148
+ - [ ] No fake duplicate code-manual page created for a raw code file
149
+ </success_criteria>
@@ -0,0 +1,128 @@
1
+ <purpose>
2
+ Run an advisory lint pass over the repo-local project wiki. Produce a durable report under `.planning/wiki/REPORTS/` and append `.planning/wiki/log.md`.
3
+ </purpose>
4
+
5
+ <required_reading>
6
+ @$HOME/.config/opencode/templates/wiki-policy.md.template
7
+ @$HOME/.config/opencode/templates/wiki-index.md.template
8
+ @$HOME/.config/opencode/templates/wiki-log.md.template
9
+ @$HOME/.config/opencode/templates/wiki-lint-report.md.template
10
+ @$HOME/.config/opencode/templates/wiki-contradictions.md.template
11
+ </required_reading>
12
+
13
+ <available_agent_types>
14
+ Valid GSD subagent types (use exact names — do not fall back to 'general-purpose'):
15
+ - wiki-lint-auditor
16
+ </available_agent_types>
17
+
18
+ <process>
19
+
20
+ ## 0. Initialize Repo Context
21
+
22
+ Resolve the repo root:
23
+
24
+ ```bash
25
+ ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
26
+ if [ -z "$ROOT" ]; then
27
+ echo "Not inside a git repository. /wiki-lint must run from a project repo."
28
+ exit 1
29
+ fi
30
+ cd "$ROOT"
31
+ ```
32
+
33
+ Parse flags from `$ARGUMENTS`:
34
+ - optional `--focus <path>` pointing to one page or subdirectory under `.planning/wiki/`
35
+
36
+ Capture:
37
+ - current UTC `timestamp`
38
+ - `branch`
39
+ - repo basename as `project_name`
40
+ - `default_branch` using `origin/HEAD`, then `origin/main`, `main`, `master`, then `HEAD`
41
+ - `report_path = {ROOT}/.planning/wiki/REPORTS/{timestamp}-lint.md`
42
+ - `register_path = {ROOT}/.planning/wiki/CONTRADICTIONS.md`
43
+
44
+ Create directories:
45
+
46
+ ```bash
47
+ mkdir -p .planning/wiki/sources .planning/wiki/topics .planning/wiki/entities .planning/wiki/queries .planning/wiki/REPORTS .planning/wiki/tmp
48
+ ```
49
+
50
+ Scaffold files when missing:
51
+ - `.planning/wiki/index.md` from `wiki-index.md.template` with project name filled in
52
+ - `.planning/wiki/log.md` from `wiki-log.md.template`
53
+ - `.planning/wiki/POLICY.md` from `wiki-policy.md.template` with project name and default branch filled in
54
+ - `.planning/wiki/CONTRADICTIONS.md` from `wiki-contradictions.md.template`
55
+
56
+ ## 1. Gather Wiki And Canonical Context
57
+
58
+ Before linting:
59
+ - read `AGENTS.md` if present
60
+ - read `.planning/wiki/POLICY.md`
61
+ - read `.planning/wiki/index.md`
62
+ - read `.planning/wiki/log.md`
63
+ - read the relevant wiki pages under `sources/`, `topics/`, `entities/`, and `queries/`
64
+ - read canonical raw docs or code when needed to verify suspected stale or contradicted claims
65
+ - do not consult memory tools for this command
66
+ - do not scan unrelated repo files; stay within the wiki plus directly cited canonical sources unless a contradiction requires one extra raw-source check
67
+
68
+ Linting truth rules:
69
+ - raw repo docs, tests, interfaces, config, and code remain canonical
70
+ - lint findings are advisory and should bias toward high-signal discrepancies
71
+ - prefer a smaller number of real issues over speculative style cleanup
72
+
73
+ ## 2. Run The Advisory Checks
74
+
75
+ Check for:
76
+ - missing citations on non-trivial claims
77
+ - orphan pages that are not discoverable from `.planning/wiki/index.md` or any other wiki page
78
+ - stale claims whose `Last reviewed` context clearly lags the cited canonical sources
79
+ - contradicted claims where the wiki no longer matches the cited raw sources
80
+ - missing obvious pages, but only when the gap is clear and recurring rather than speculative
81
+ - broken cross-references to missing wiki files or raw repo files
82
+
83
+ Contradiction severity (classify every contradiction found, mirroring the policy):
84
+ - `hard` — genuinely conflicting claims that cannot both be correct; must be resolved before downstream work relies on either page
85
+ - `scope-mismatch` — the two claims apply to different scopes/contexts and do not truly conflict
86
+ - `soft` — non-blocking, contextual difference; coexists
87
+
88
+ Run this lint pass inline in the current command.
89
+
90
+ Reliability rule:
91
+ - do not spawn another agent or task for `/wiki-lint`
92
+ - do not create todos for this command
93
+ - inspect the current wiki state, write the report directly, then append the log entry and return
94
+
95
+ Write the report directly to `report_path` using the required structure from `wiki-lint-report.md.template`.
96
+
97
+ Conservative execution rule:
98
+ - if there are zero meaningful findings, still write a report with zero counts and `- None.` in each findings section
99
+ - if there is one clear contradiction or drift issue, report that instead of searching for additional speculative findings
100
+
101
+ ## 3. Update The Contradiction Register
102
+
103
+ Mirror every contradiction finding into the persistent register at `.planning/wiki/CONTRADICTIONS.md`. This is what stops contradictions from leaking (reported once, then forgotten):
104
+
105
+ - read the existing register
106
+ - for each contradiction found this run: if an open entry for the same page-pair/claim already exists, update it (severity, evidence, last-seen timestamp); otherwise open a new entry under `<!-- wiki:contradictions:open:start -->` with severity, `Status: open`, affected pages, the conflicting claims, and the detection date
107
+ - for contradictions that previously existed but whose underlying wiki page(s) now agree with the canonical source: flip `Status: open` → `resolved`, move the entry to the `<!-- wiki:contradictions:resolved:start -->` block, and record the resolution date and the refresh/ingest that fixed it
108
+ - do not delete entries — move resolved ones to the Resolved section so the history is preserved
109
+ - a contradiction is `resolved` only after the conflicting page was actually reconciled (via `/wiki-ingest --refresh` or a manual edit), not merely acknowledged
110
+
111
+ ## 4. Report Results
112
+
113
+ Display:
114
+ - report path
115
+ - a short summary of the highest-signal findings
116
+ - a reminder that the report is advisory and raw sources remain canonical
117
+ - append the log entry inside `<!-- wiki:entries:start -->` and `<!-- wiki:entries:end -->` when those markers exist
118
+
119
+ </process>
120
+
121
+ <success_criteria>
122
+ - [ ] Repo root resolved and wiki scaffold created if missing
123
+ - [ ] Relevant wiki pages and cited canonical sources inspected
124
+ - [ ] Advisory lint report written under `.planning/wiki/REPORTS/`
125
+ - [ ] Log appended
126
+ - [ ] Missing citations, orphan pages, stale or contradicted claims, missing obvious pages, and broken links were considered conservatively
127
+ - [ ] Final user-facing summary kept raw sources as the source of truth
128
+ </success_criteria>
@@ -0,0 +1,122 @@
1
+ <purpose>
2
+ Answer repository questions by consulting the compiled wiki first and canonical raw sources second. Optionally store a reusable derived answer under `.planning/wiki/queries/`.
3
+ </purpose>
4
+
5
+ <required_reading>
6
+ @$HOME/.config/opencode/templates/wiki-policy.md.template
7
+ @$HOME/.config/opencode/templates/wiki-index.md.template
8
+ @$HOME/.config/opencode/templates/wiki-log.md.template
9
+ @$HOME/.config/opencode/templates/wiki-query-answer.md.template
10
+ </required_reading>
11
+
12
+ <available_agent_types>
13
+ Valid GSD subagent types (use exact names — do not fall back to 'general-purpose'):
14
+ - wiki-query-analyst
15
+ </available_agent_types>
16
+
17
+ <process>
18
+
19
+ ## 0. Initialize Repo Context
20
+
21
+ Resolve the repo root:
22
+
23
+ ```bash
24
+ ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
25
+ if [ -z "$ROOT" ]; then
26
+ echo "Not inside a git repository. /wiki-query must run from a project repo."
27
+ exit 1
28
+ fi
29
+ cd "$ROOT"
30
+ ```
31
+
32
+ Parse flags from `$ARGUMENTS`:
33
+ - `--writeback`
34
+ - the remaining text is the required `question`
35
+
36
+ If `question` is empty after flag parsing:
37
+ - stop with a clear error explaining that the command needs a question
38
+
39
+ Capture:
40
+ - current UTC `timestamp`
41
+ - `branch`
42
+ - repo basename as `project_name`
43
+ - `default_branch` using `origin/HEAD`, then `origin/main`, `main`, `master`, then `HEAD`
44
+ - `query_slug` from the question, normalized to lowercase kebab case
45
+
46
+ Create directories:
47
+
48
+ ```bash
49
+ mkdir -p .planning/wiki/sources .planning/wiki/topics .planning/wiki/entities .planning/wiki/queries .planning/wiki/REPORTS .planning/wiki/tmp
50
+ ```
51
+
52
+ Scaffold files when missing:
53
+ - `.planning/wiki/index.md` from `wiki-index.md.template` with project name filled in
54
+ - `.planning/wiki/log.md` from `wiki-log.md.template`
55
+ - `.planning/wiki/POLICY.md` from `wiki-policy.md.template` with project name and default branch filled in
56
+
57
+ Paths:
58
+ - `index_path = {ROOT}/.planning/wiki/index.md`
59
+ - `log_path = {ROOT}/.planning/wiki/log.md`
60
+ - `policy_path = {ROOT}/.planning/wiki/POLICY.md`
61
+ - `query_output_path = {ROOT}/.planning/wiki/queries/{timestamp}-{query_slug}.md` when `writeback` is true
62
+
63
+ ## 1. Build The Retrieval Scope
64
+
65
+ Before answering:
66
+ - read `AGENTS.md` if present
67
+ - read `.planning/wiki/POLICY.md`
68
+ - read `.planning/wiki/index.md` first
69
+ - use the index to shortlist relevant pages under `sources/`, `topics/`, `entities/`, `queries/`, and recent `REPORTS/` when needed
70
+ - read only the relevant wiki pages next
71
+ - if the wiki is missing, stale, contradictory, or insufficient, read the canonical repo docs, tests, interfaces, config, or code directly
72
+
73
+ Truth rules:
74
+ - canonical raw repo sources outrank derived wiki pages
75
+ - reusable prior query pages are helpful context, not proof by themselves
76
+ - when the wiki conflicts with raw sources, preserve the contradiction and trust the raw sources
77
+
78
+ ## 2. Answer The Question
79
+
80
+ Preferred path: spawn `wiki-query-analyst`.
81
+
82
+ ```text
83
+ ◆ Building wiki-grounded answer...
84
+ ```
85
+
86
+ Spawn with:
87
+
88
+ ```text
89
+ Task(
90
+ prompt="Read $HOME/.config/opencode/agents/wiki-query-analyst.md for instructions. FIRST ACTION: change into {ROOT}.\n\n<wiki_assignment>\nproject_root: {ROOT}\nquestion: {question}\nwriteback: {writeback}\nindex_path: {ROOT}/.planning/wiki/index.md\nlog_path: {ROOT}/.planning/wiki/log.md\npolicy_path: {ROOT}/.planning/wiki/POLICY.md\noutput_path: {query_output_path or \"null\"}\ntimestamp: {timestamp}\nbranch: {branch}\nproject_name: {project_name}\n</wiki_assignment>",
91
+ subagent_type="wiki-query-analyst",
92
+ description="Wiki: query analyst"
93
+ )
94
+ ```
95
+
96
+ If Task/subagent execution is unavailable:
97
+ - run the query-analyst role inline
98
+ - still answer in chat
99
+ - still write the reusable query page and update index/log when `writeback` is true
100
+
101
+ ## 3. Report Results
102
+
103
+ Always:
104
+ - answer in chat with preserved source references and caveats
105
+ - call out any contradictions or freshness uncertainty explicitly
106
+
107
+ If `writeback` is true:
108
+ - mention the saved query page path
109
+ - confirm that the query artifact is derived, not canonical
110
+ - update the `Queries` section of `.planning/wiki/index.md` inside `<!-- wiki:queries:start -->` and `<!-- wiki:queries:end -->` when those markers exist, replacing `- None yet.` when adding the first real entry
111
+ - append the log entry inside `<!-- wiki:entries:start -->` and `<!-- wiki:entries:end -->` when those markers exist
112
+
113
+ </process>
114
+
115
+ <success_criteria>
116
+ - [ ] Repo root resolved and wiki scaffold created if missing
117
+ - [ ] Index consulted before deeper reads
118
+ - [ ] Relevant wiki pages reviewed before canonical fallback
119
+ - [ ] Final chat answer preserved source references and caveats
120
+ - [ ] Reusable answer written under `.planning/wiki/queries/` when `--writeback` is used
121
+ - [ ] Index and log updated when `--writeback` is used
122
+ </success_criteria>