@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,191 @@
1
+ ---
2
+ description: Review code for bugs, security issues, and maintainability concerns (workflow code-review; distinct name to avoid shadowing the built-in /code-review)
3
+ argument-hint: "[--full | --staged | --branch <name> | --mr <project>!iid | --since <ref> | --focus <pattern> | --post-to-mr | --block-on <severity>]"
4
+ allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task
5
+ ---
6
+
7
+ Git provider: these steps use the git host set by `CAIRN_GIT_PROVIDER` (`github`/`gitlab`/`codeberg`/`forgejo`/`none`); resolve the operation-to-tool mapping from `docs/git-providers.md`. If it is `none` or no provider MCP is registered, skip the provider steps and continue locally.
8
+
9
+ <objective>
10
+ Review code for bugs, security issues, maintainability problems, and style violations.
11
+
12
+ Output: `REVIEW.md` in the repo root (or `.planning/reviews/` if it exists).
13
+
14
+ Flag handling:
15
+ - `--full` — review all tracked files in the repository (entire codebase)
16
+ - `--staged` — review only git-staged changes
17
+ - `--branch <name>` — review `<name>` vs default branch
18
+ - `--mr <project>!iid` — review MR diff via the git-provider MCP
19
+ - `--since <ref>` — review changes since `<ref>` (e.g. `HEAD~1`)
20
+ - `--focus <pattern>` — restrict to files matching glob pattern
21
+ - `--post-to-mr` — post findings as MR/PR diff comments (requires `--mr`)
22
+ - `--block-on <severity>` — fail if findings at or above severity exist (critical/high/medium)
23
+ - Default (no flags) — review working tree + staged changes
24
+
25
+ This is an advisory command. Findings are structured by severity and dimension.
26
+ </objective>
27
+
28
+ <context>
29
+ Arguments: $ARGUMENTS
30
+
31
+ Default behavior:
32
+ 1. Detect review scope from flags (or default to working tree + staged)
33
+ 2. Collect diff and relevant context files
34
+ 3. Spawn code-reviewer subagent with diff + project context
35
+ 4. Write structured REVIEW.md with findings
36
+ 5. Optionally post findings to the MR/PR
37
+ 6. Enforce block gate if `--block-on` is set
38
+
39
+ Important rules:
40
+ - The reviewer is READ-ONLY on source code — only creates REVIEW.md
41
+ - Findings must cite exact file paths and line numbers
42
+ - Each finding includes: severity, dimension, description, and suggested fix
43
+ - Don't flag style issues that match existing project conventions
44
+ - Review dimensions include `simplicity` — flag over-engineering (unnecessary abstractions, speculative scaffolding/YAGNI, avoidable dependencies or boilerplate); a shortcut tagged with a `ponytail:` comment is acceptable, not a finding
45
+ </context>
46
+
47
+ <process>
48
+
49
+ ## 1. Detect Review Scope
50
+
51
+ Parse arguments to determine review mode:
52
+
53
+ ### Full codebase mode (`--full`)
54
+ ```bash
55
+ REVIEW_MODE=full
56
+ FILE_LIST=$(git ls-files | grep -vE '\.(md|txt|yml|yaml|json|toml|lock|cfg|ini|env|gitignore)$' | grep -E "$FOCUS_PATTERN" 2>/dev/null || git ls-files)
57
+ ```
58
+ The reviewer receives the full file list and reads each file directly (no diff).
59
+
60
+ ### Diff-based modes
61
+
62
+ | Flag | Diff Command |
63
+ |---|---|
64
+ | `--staged` | `git diff --cached` |
65
+ | `--branch <name>` | `git diff "${DEFAULT_BRANCH}...<name>"` |
66
+ | `--mr <project>!iid` | git-provider MCP: `get_merge_request_diffs` |
67
+ | `--since <ref>` | `git diff <ref>..HEAD` |
68
+ | (none) | `git diff` + `git diff --cached` |
69
+
70
+ If `--focus <pattern>` is set, filter files to matching paths.
71
+
72
+ ## 2. Collect Context
73
+
74
+ ```bash
75
+ REPO_ROOT=$(git rev-parse --show-toplevel)
76
+ DEFAULT_BRANCH=$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's#^origin/##' || true)
77
+ if [ -z "$DEFAULT_BRANCH" ]; then
78
+ if git rev-parse --verify origin/main >/dev/null 2>&1 || git rev-parse --verify main >/dev/null 2>&1; then
79
+ DEFAULT_BRANCH=main
80
+ elif git rev-parse --verify origin/master >/dev/null 2>&1 || git rev-parse --verify master >/dev/null 2>&1; then
81
+ DEFAULT_BRANCH=master
82
+ else
83
+ DEFAULT_BRANCH=HEAD
84
+ fi
85
+ fi
86
+ ```
87
+
88
+ Collect project context for the reviewer:
89
+ - Language detection (from file extensions in diff)
90
+ - Existing conventions (read 1-2 analogous files not in diff)
91
+ - Project skills (`.claude/skills/` or `.agents/skills/` if present)
92
+ - Lint/test config (`.eslintrc`, `pyproject.toml`, `Cargo.toml`, etc.)
93
+
94
+ ## 3. Build Review Input
95
+
96
+ ### Full mode (`--full`)
97
+ Build a file list from tracked source files (excluding docs, config, lock files). The reviewer reads each file directly. For large repos, prioritize:
98
+ - Entry points and public APIs
99
+ - Auth, security, and data-access layers
100
+ - Recently changed files (last 30 days by `git log --since=30-days-ago`)
101
+
102
+ ### Diff-based modes
103
+ Combine:
104
+ - Full unified diff (from step 1)
105
+ - Project context (from step 2)
106
+ - File list with paths and languages
107
+
108
+ For MR mode, also capture:
109
+ - MR title, description, assignees, reviewers
110
+ - Existing discussion notes (to avoid duplicating findings)
111
+
112
+ ## 4. Spawn code-reviewer
113
+
114
+ Spawn the `code-reviewer` subagent via the Task tool with `subagent_type: "code-reviewer"`.
115
+
116
+ **Full mode:** Pass `<mode>full</mode>` and `<files>{tracked file list}</files>`. The reviewer reads files directly.
117
+
118
+ **Diff mode:** Pass `<mode>diff</mode>` and `<diff>{full diff}</diff>`.
119
+
120
+ Prompt structure:
121
+ ```text
122
+ Read agent instructions for code review.
123
+
124
+ <mode>{full|diff}</mode>
125
+ <diff>{full diff — only for diff mode}</diff>
126
+ <files>{file list with paths}</files>
127
+ <project_context>{language, conventions, skills, lint config}</project_context>
128
+ <config>block_on: {BLOCK_ON_SEVERITY}, focus: {FOCUS_PATTERN}</config>
129
+ <constraints>Read-only on source. Cite file:line for every finding. Skip style issues matching project conventions.</constraints>
130
+ ```
131
+
132
+ Handle return:
133
+ - `## CLEAN` — no findings, write brief REVIEW.md
134
+ - `## FINDINGS` — structured findings, write REVIEW.md with table
135
+ - `## ESCALATE` — critical issues, write REVIEW.md and block
136
+
137
+ ## 5. Write REVIEW.md
138
+
139
+ Create/update `REVIEW.md` (or `.planning/reviews/REVIEW.md` if directory exists):
140
+
141
+ ```markdown
142
+ # Code Review — {date}
143
+
144
+ **Scope:** {full | staged | branch | MR | since}
145
+ **Files:** {count}
146
+ **Findings:** {total} ({critical} critical, {high} high, {medium} medium, {low} low)
147
+
148
+ ## Findings by Severity
149
+
150
+ ### Critical
151
+ | # | File:Line | Dimension | Description | Suggested Fix |
152
+ |---|---|---|---|---|
153
+
154
+ ### High
155
+ ...
156
+
157
+ ### Medium
158
+ ...
159
+
160
+ ### Low
161
+ ...
162
+
163
+ ## Summary
164
+ {brief assessment}
165
+ ```
166
+
167
+ ## 6. Optional: Post to MR
168
+
169
+ If `--post-to-mr` and `--mr` are set:
170
+ - For each finding with file:line, create a diff discussion note
171
+ - Group findings by file
172
+ - Reference REVIEW.md in a top-level MR note
173
+
174
+ ## 7. Block Gate
175
+
176
+ If `--block-on <severity>` is set and findings at or above that severity exist:
177
+
178
+ ```
179
+ REVIEW BLOCKED: {N} findings at or above {severity}
180
+ ▶ Fix findings or remove --block-on to continue
181
+ ```
182
+
183
+ Stop here. Otherwise:
184
+
185
+ ```
186
+ REVIEW COMPLETE: {total} findings ({critical} critical, {high} high)
187
+ ▶ Review REVIEW.md for details
188
+ ▶ /repo-review --post-to-mr to comment on MR
189
+ ```
190
+
191
+ </process>
@@ -0,0 +1,174 @@
1
+ ---
2
+ description: Run a governed local security audit against one scoped attack surface and write repo-local artifacts
3
+ argument-hint: "[--full] [--focus <path>] [--threat-model <name>] [--verify-only] [--create-confidential-issue] [--issue-project <group/project>]"
4
+ allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task
5
+ ---
6
+
7
+ Git provider: these steps use the git host set by `CAIRN_GIT_PROVIDER` (`github`/`gitlab`/`codeberg`/`forgejo`/`none`); resolve the operation-to-tool mapping from `docs/git-providers.md`. If it is `none` or no provider MCP is registered, skip the provider steps and continue locally.
8
+
9
+ <objective>
10
+ 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/`.
11
+
12
+ Output artifacts:
13
+ - `.planning/security/REPORTS/<timestamp>.md`
14
+ - `.planning/security/CANDIDATES/<timestamp>-candidate.md`
15
+ - `.planning/security/VALIDATED/SEC-xxxx-<slug>.md` for accepted findings
16
+ - optional `.planning/security/ISSUES/<timestamp>-confidential-issue.md`
17
+ - optional update to `.planning/security/FINDINGS.yaml`
18
+
19
+ Flag handling:
20
+ - `--full` — inspect the broader repository instead of the changed surface only
21
+ - `--focus <path>` — bias target selection toward one file or subtree
22
+ - `--threat-model <name>` — label and bias the run; defaults to `changed-surface`
23
+ - `--verify-only` — write the audit artifacts without mutating `.planning/security/FINDINGS.yaml`
24
+ - `--create-confidential-issue` — create a repo-local confidential issue draft when an accepted finding exists
25
+ - `--issue-project <group/project>` — record the intended git-provider destination for that issue draft
26
+
27
+ This is a governed local-only workflow. It must stay inside the current repository, repo-owned local processes, local files, and localhost services launched from this repo.
28
+
29
+ Recommended `--threat-model` values: `changed-surface` (default), `authenticated-http-request`, `privilege-escalation`, `session-upgrade`, `deserialization`, `archive-extraction`, `path-traversal`, `subprocess-injection`, `config-file-injection`, `localhost-service-abuse`, `native-crash`, `memory-corruption`. Use a short concrete phrase that helps the selector and investigator reason about attacker capability or failure mode.
30
+ </objective>
31
+
32
+ <context>
33
+ Arguments: $ARGUMENTS
34
+
35
+ Scaffold templates live at `$HOME/.claude/templates/security-*.template` (installed by `scripts/sync-claude-assets.sh`). The bootstrap also seeds `.planning/security/POLICY.md` and `.planning/security/FINDINGS.yaml` into each project.
36
+
37
+ Operating model:
38
+ - one scoped target per run
39
+ - one candidate finding per run at most
40
+ - rejected outcomes stay in the run history, not in the canonical ledger
41
+ - accepted findings may update `.planning/security/FINDINGS.yaml` unless `--verify-only` is set
42
+ - repo-local drafts are preferred over speculative issue filing side effects
43
+ </context>
44
+
45
+ <process>
46
+
47
+ ## 0. Initialize repo context
48
+
49
+ ```bash
50
+ ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
51
+ if [ -z "$ROOT" ]; then
52
+ echo "Not inside a git repository. /security-audit must run from a project repo."
53
+ exit 1
54
+ fi
55
+ cd "$ROOT"
56
+ ```
57
+
58
+ Parse flags from `$ARGUMENTS` (`--full`, `--focus`, `--threat-model`, `--verify-only`, `--create-confidential-issue`, `--issue-project`).
59
+
60
+ Rules:
61
+ - `audit_mode` is `full` when `--full` is set, otherwise `diff`
62
+ - default `threat_model` to `changed-surface` when no explicit value is supplied
63
+ - `--issue-project` is optional metadata; do not fail the run only because it is missing
64
+
65
+ Capture: current UTC `timestamp`, `branch`, repo basename as `project_name`, `default_branch` (try `origin/HEAD`, then `origin/main`, `main`, `master`, then `HEAD`), `base_ref` (= `default_branch` in diff mode, else `full-repo`), `head_ref` (= `branch`).
66
+
67
+ ```bash
68
+ mkdir -p .planning/security/REPORTS .planning/security/CANDIDATES .planning/security/VALIDATED .planning/security/ISSUES .planning/security/tmp
69
+ ```
70
+
71
+ Scaffold when missing:
72
+ - `.planning/security/FINDINGS.yaml` from `$HOME/.claude/templates/security-finding-register.yaml.template` with project name and default branch filled in
73
+ - `.planning/security/POLICY.md` from `$HOME/.claude/templates/security-policy.md.template` with default branch filled in
74
+
75
+ Paths: `findings_path`, `policy_path`, `report_path = .planning/security/REPORTS/{timestamp}.md`, `candidate_path = .planning/security/CANDIDATES/{timestamp}-candidate.md`.
76
+
77
+ ## 1. Build the audit scope
78
+
79
+ Always read `AGENTS.md` (if present), `.planning/security/POLICY.md`, `.planning/security/FINDINGS.yaml`.
80
+
81
+ Build `scope_summary`:
82
+ - diff mode: summarize the changed surface from the current branch relative to `default_branch`, plus staged/unstaged changes
83
+ - full mode: summarize the main attack-surface-bearing directories and entrypoints
84
+ - when `--focus <path>` is present, keep the summary anchored to that path even in full mode
85
+
86
+ Build `changed_paths` as a concise path list for the selector.
87
+
88
+ ## 2. Choose one target
89
+
90
+ Spawn the `security-target-selector` subagent via the Task tool with `subagent_type: "security-target-selector"`. The prompt is the assignment block:
91
+
92
+ ```text
93
+ <audit_assignment>
94
+ project_root: {ROOT}
95
+ audit_mode: {audit_mode}
96
+ focus_path: {focus_path or "null"}
97
+ threat_model: {threat_model}
98
+ policy_path: {ROOT}/.planning/security/POLICY.md
99
+ findings_path: {ROOT}/.planning/security/FINDINGS.yaml
100
+ scope_summary: {scope_summary}
101
+ changed_paths: {changed_paths}
102
+ </audit_assignment>
103
+ ```
104
+
105
+ If the selector returns `NO_TARGET`: write `report_path` from `security-report.md.template` with accepted/rejected counts `0`, explain no grounded target was selected, and stop after reporting in chat.
106
+
107
+ ## 3. Investigate the target
108
+
109
+ Spawn the `security-investigator` subagent via the Task tool with `subagent_type: "security-investigator"` and prompt:
110
+
111
+ ```text
112
+ <audit_assignment>
113
+ project_root: {ROOT}
114
+ audit_mode: {audit_mode}
115
+ threat_model: {threat_model}
116
+ selected_file: {selected_file}
117
+ investigation_target: {investigation_target}
118
+ likely_entry_point: {likely_entry_point}
119
+ risk_class: {risk_class}
120
+ policy_path: {ROOT}/.planning/security/POLICY.md
121
+ findings_path: {ROOT}/.planning/security/FINDINGS.yaml
122
+ candidate_path: {ROOT}/.planning/security/CANDIDATES/{timestamp}-candidate.md
123
+ </audit_assignment>
124
+ ```
125
+
126
+ If the investigator returns `NO_FINDING`: write `report_path` with `Accepted findings: 0` and `Rejected candidates: 1`, include the rejection reason and candidate path, and stop after reporting in chat.
127
+
128
+ ## 4. Validate the candidate
129
+
130
+ Compute `next_finding_id` from `.planning/security/FINDINGS.yaml` (next unused `SEC-xxxx`).
131
+
132
+ Spawn the `security-validator` subagent via the Task tool with `subagent_type: "security-validator"` and prompt:
133
+
134
+ ```text
135
+ <audit_assignment>
136
+ project_root: {ROOT}
137
+ policy_path: {ROOT}/.planning/security/POLICY.md
138
+ findings_path: {ROOT}/.planning/security/FINDINGS.yaml
139
+ candidate_path: {ROOT}/.planning/security/CANDIDATES/{timestamp}-candidate.md
140
+ next_finding_id: {next_finding_id}
141
+ validated_dir: {ROOT}/.planning/security/VALIDATED
142
+ </audit_assignment>
143
+ ```
144
+
145
+ ## 5. Write durable outcome
146
+
147
+ Always write `report_path` from `security-report.md.template` and fill: project name, audit scope, base ref, head ref, threat model, focus path, timestamp, selected file and investigation target (when a target existed), accepted/rejected counts, accepted finding details (when accepted), rejection rationale (when rejected).
148
+
149
+ If validation returned `ACCEPTED`:
150
+ - if `--verify-only` is not set, append one new entry to `.planning/security/FINDINGS.yaml`, concise and consistent with the existing ledger shape
151
+ - include the validated report path under `evidence.reports` and `validation.report_path`
152
+ - set `last_security_audit.at`, `.branch`, and `.report`
153
+
154
+ If validation returned `REJECTED`: do not mutate `.planning/security/FINDINGS.yaml`.
155
+
156
+ ## 6. Optional confidential issue draft
157
+
158
+ If `--create-confidential-issue` is set and validation returned `ACCEPTED`: write `.planning/security/ISSUES/{timestamp}-confidential-issue.md` from `security-issue.md.template`, fill `issue-project` (or `unassigned`), and preserve the validated + audit report paths.
159
+
160
+ ## 7. Report results
161
+
162
+ In chat: state `accepted` / `rejected` / `no target`; show the selected file and investigation target when applicable; link the durable report path; mention candidate and validated paths when they exist; mention whether `.planning/security/FINDINGS.yaml` was updated or skipped because of `--verify-only`.
163
+
164
+ </process>
165
+
166
+ <success_criteria>
167
+ - [ ] Repo root resolved and `.planning/security/` scaffold exists
168
+ - [ ] Exactly one target selected or explicitly rejected as unnecessary
169
+ - [ ] Candidate report written for investigated runs
170
+ - [ ] Candidate validated against duplicate and reachability bars
171
+ - [ ] Durable report written under `.planning/security/REPORTS/`
172
+ - [ ] Findings ledger updated only for accepted findings and only when not in `--verify-only` mode
173
+ - [ ] Optional confidential issue draft written when requested and an accepted finding exists
174
+ </success_criteria>
@@ -0,0 +1,112 @@
1
+ ---
2
+ description: Compile one canonical source into a sparse, citation-heavy project wiki page, or re-sync an existing page to the current source with --refresh
3
+ argument-hint: "<source-path> [--refresh]"
4
+ allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task
5
+ ---
6
+
7
+ <objective>
8
+ Compile one canonical source into the repo-local project wiki under `.planning/wiki/`, or re-sync an existing summary to the current canonical source.
9
+
10
+ Output artifacts:
11
+ - `.planning/wiki/sources/<slug>.md`
12
+ - updated `.planning/wiki/index.md`
13
+ - updated `.planning/wiki/log.md`
14
+ - optional conservative updates under `.planning/wiki/topics/` or `.planning/wiki/entities/`
15
+
16
+ This is a derived-knowledge command. Raw repository docs, ADRs, tests, interfaces, and code remain canonical. The wiki must stay sparse, citation-heavy, and conservative.
17
+
18
+ Argument handling:
19
+ - accepts exactly one non-flag argument: an absolute source path or a repo-relative path inside the current repository
20
+ - optional `--refresh` flag: re-sync an existing source summary to the current canonical source instead of writing it from scratch. In refresh mode: re-read the canonical source, update only the stable facts that changed, bump `Last reviewed`, keep the page's existing structure, and append a `wiki-refresh` log entry. Use this whenever the MR/PR, code, or doc behind a page has changed.
21
+ - the source may be a repo doc, ADR, runbook, config surface, or a code file that defines a stable interface or behavior
22
+ - do not restate an entire code file into a fake duplicate wiki page; summarize only stable, reusable facts with citations
23
+
24
+ Scaffold templates live at `$HOME/.claude/templates/wiki-*.template` (installed by `scripts/sync-claude-assets.sh`).
25
+ </objective>
26
+
27
+ <context>
28
+ Arguments: $ARGUMENTS
29
+ </context>
30
+
31
+ <process>
32
+
33
+ ## 0. Initialize repo context
34
+
35
+ ```bash
36
+ ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
37
+ if [ -z "$ROOT" ]; then
38
+ echo "Not inside a git repository. /wiki-ingest must run from a project repo."
39
+ exit 1
40
+ fi
41
+ cd "$ROOT"
42
+ ```
43
+
44
+ Parse `$ARGUMENTS`: require exactly one non-flag argument as `source_input`; reject empty input or multiple positional arguments with a clear error; capture an optional `--refresh` flag into `refresh_mode` (default false).
45
+
46
+ Capture: current UTC `timestamp`, `branch`, repo basename as `project_name`, `default_branch` (try `origin/HEAD`, then `origin/main`, `main`, `master`, then `HEAD`).
47
+
48
+ Resolve `source_input`: (1) if an existing absolute path, use as `source_abs`; (2) else if `$ROOT/$source_input` exists, use it; (3) else stop with a clear error.
49
+
50
+ Derive: `source_rel` (when inside the repo, else absolute), `source_slug` (lowercase kebab), `source_kind` (one of `repo_doc`, `repo_code`, `repo_config`, `external_doc`, `generated_or_binary`), `source_page_path = {ROOT}/.planning/wiki/sources/{source_slug}.md`.
51
+
52
+ ```bash
53
+ mkdir -p .planning/wiki/sources .planning/wiki/topics .planning/wiki/entities .planning/wiki/queries .planning/wiki/REPORTS .planning/wiki/tmp
54
+ ```
55
+
56
+ Scaffold when missing from `$HOME/.claude/templates/wiki-*.template`:
57
+ - `.planning/wiki/index.md` (project name filled in)
58
+ - `.planning/wiki/log.md`
59
+ - `.planning/wiki/POLICY.md` (project name + default branch filled in)
60
+
61
+ ## 1. Gather canonical context
62
+
63
+ Read `AGENTS.md` (if present), `.planning/wiki/POLICY.md`, `.planning/wiki/index.md`, the target source directly, and nearby repo docs only when needed to disambiguate.
64
+
65
+ Truth rules: the target source is canonical for its own content; the wiki is derived and must not replace the source; for code, extract only stable interfaces/invariants/behaviors (no whole-file paraphrase); for generated/vendored/binary sources, write a minimal note pointing back to the canonical path.
66
+
67
+ ## 2. Write or refresh the source summary
68
+
69
+ In `refresh_mode` (the `--refresh` flag was passed): the source page should already exist at `source_page_path`; if it does not, fall back to a normal ingest and note this in the log. Pass `refresh_mode: true` in the assignment so the ingester re-reads the canonical source, updates only the stable facts that changed, preserves the existing page structure and unchanged facts, bumps `Last reviewed`, re-evaluates the `Contradictions And Freshness Notes` section, and logs the action as `wiki-refresh`. Refresh is the primary maintenance loop: run it whenever the MR/PR, code, or doc behind a page changes.
70
+
71
+ Default path (no `--refresh`): spawn the `wiki-ingester` subagent via the Task tool with `subagent_type: "wiki-ingester"` and prompt:
72
+
73
+ ```text
74
+ <wiki_assignment>
75
+ project_root: {ROOT}
76
+ source_abs: {source_abs}
77
+ source_rel: {source_rel}
78
+ source_kind: {source_kind}
79
+ source_page_path: {ROOT}/.planning/wiki/sources/{source_slug}.md
80
+ index_path: {ROOT}/.planning/wiki/index.md
81
+ log_path: {ROOT}/.planning/wiki/log.md
82
+ policy_path: {ROOT}/.planning/wiki/POLICY.md
83
+ timestamp: {timestamp}
84
+ branch: {branch}
85
+ project_name: {project_name}
86
+ refresh_mode: {refresh_mode}
87
+ </wiki_assignment>
88
+ ```
89
+
90
+ If Task/subagent execution is unavailable, run the ingester role inline and still write the source page and update index/log.
91
+
92
+ ## 3. Conservative topic and entity maintenance
93
+
94
+ After the source page exists, create/update a topic page under `.planning/wiki/topics/` only if the source adds a durable concept appearing across multiple sources or repeated queries; create/update an entity page under `.planning/wiki/entities/` only if it identifies a stable interface, component, owner, or bounded concept that improves cross-linking. Every new topic/entity page must stay shorter than its combined raw sources, include `Last reviewed`, include canonical references, and call out contradictions or freshness uncertainty. Do not create a page for every file or hide uncertainty behind definitive language.
95
+
96
+ ## 4. Update index and log
97
+
98
+ Ensure the source page is linked once in the `Sources` section of `.planning/wiki/index.md` (update only inside `<!-- wiki:sources:start -->`/`<!-- wiki:sources:end -->` when present, replacing `- None yet.` for the first real entry). Link any created topic/entity page once in the correct section. Append one entry to `.planning/wiki/log.md` (timestamp, action — `wiki-ingest` or `wiki-refresh` in refresh mode — source path, pages touched, conservative-mode/refresh-delta note), inside `<!-- wiki:entries:start -->`/`<!-- wiki:entries:end -->` when present.
99
+
100
+ ## 5. Report results
101
+
102
+ Display the source page path, any topic/entity pages updated, and a short note that raw sources remain canonical.
103
+
104
+ </process>
105
+
106
+ <success_criteria>
107
+ - [ ] Repo root resolved and wiki scaffold created if missing
108
+ - [ ] Canonical source resolved from the input path
109
+ - [ ] One source summary page written or refreshed under `.planning/wiki/sources/`
110
+ - [ ] Index updated and log appended
111
+ - [ ] No fake duplicate code-manual page created for a raw code file
112
+ </success_criteria>
@@ -0,0 +1,86 @@
1
+ ---
2
+ description: Audit the project wiki for citation gaps, orphan pages, stale claims, contradictions, and broken cross-references; mirror contradictions into the persistent register
3
+ argument-hint: "[--focus <path>]"
4
+ allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
+ ---
6
+
7
+ <objective>
8
+ Run an advisory lint pass over `.planning/wiki/`.
9
+
10
+ Output artifacts:
11
+ - `.planning/wiki/REPORTS/<timestamp>-lint.md` (advisory snapshot)
12
+ - `.planning/wiki/CONTRADICTIONS.md` (persistent register, updated in place)
13
+ - updated `.planning/wiki/log.md`
14
+
15
+ Flag handling:
16
+ - `--focus <path>` — restrict advisory checks to one wiki page or subdirectory under `.planning/wiki/`
17
+
18
+ This is an advisory governance command. Raw repository docs, ADRs, tests, interfaces, and code remain canonical even when the wiki disagrees or is stale. Scaffold templates live at `$HOME/.claude/templates/wiki-*.template`.
19
+
20
+ Contradictions are classified by severity (`soft` / `scope-mismatch` / `hard`) and written to the persistent `CONTRADICTIONS.md` register. Unlike the per-run REPORTS snapshot, the register is durable: lint opens, updates, and resolves entries in place so contradictions do not leak (get reported and forgotten). An entry is `resolved` only after the conflicting wiki page has actually been reconciled to the canonical source.
21
+
22
+ Reliability rule: run the lint inline in this command. Do not spawn a subagent and do not create todos for `/wiki-lint`.
23
+ </objective>
24
+
25
+ <context>
26
+ Arguments: $ARGUMENTS
27
+ </context>
28
+
29
+ <process>
30
+
31
+ ## 0. Initialize repo context
32
+
33
+ ```bash
34
+ ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
35
+ if [ -z "$ROOT" ]; then
36
+ echo "Not inside a git repository. /wiki-lint must run from a project repo."
37
+ exit 1
38
+ fi
39
+ cd "$ROOT"
40
+ ```
41
+
42
+ Parse flags from `$ARGUMENTS`: optional `--focus <path>` pointing to one page or subdirectory under `.planning/wiki/`.
43
+
44
+ Capture: current UTC `timestamp`, `branch`, repo basename as `project_name`, `default_branch` (try `origin/HEAD`, then `origin/main`, `main`, `master`, then `HEAD`), `report_path = {ROOT}/.planning/wiki/REPORTS/{timestamp}-lint.md`, `register_path = {ROOT}/.planning/wiki/CONTRADICTIONS.md`.
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 when missing from `$HOME/.claude/templates/wiki-*.template`: `.planning/wiki/index.md`, `.planning/wiki/log.md`, `.planning/wiki/POLICY.md`, `.planning/wiki/CONTRADICTIONS.md`.
51
+
52
+ ## 1. Gather wiki and canonical context
53
+
54
+ Read `AGENTS.md` (if present), `.planning/wiki/POLICY.md`, `.planning/wiki/index.md`, `.planning/wiki/log.md`, and the relevant wiki pages under `sources/`, `topics/`, `entities/`, `queries/`. Read canonical raw docs or code only when needed to verify a suspected stale or contradicted claim. Do not consult memory tools and do not scan unrelated repo files; stay within the wiki plus directly cited canonical sources unless a contradiction requires one extra raw-source check.
55
+
56
+ Truth rules: raw repo docs/tests/interfaces/config/code remain canonical; lint findings are advisory and should bias toward high-signal discrepancies; prefer a smaller number of real issues over speculative style cleanup.
57
+
58
+ ## 2. Run the advisory checks (inline)
59
+
60
+ Check for: missing citations on non-trivial claims; orphan pages not discoverable from the index or any other wiki page; stale claims whose `Last reviewed` clearly lags the cited canonical sources; contradicted claims where the wiki no longer matches cited raw sources; missing obvious pages (only when the gap is clear and recurring); broken cross-references to missing wiki files or raw repo files.
61
+
62
+ Finding-signal severity: `high` for contradicted claims or broken links on heavily used pages; `medium` for missing citations, stale, or orphan pages; `low` for optional missing pages or minor hygiene gaps.
63
+
64
+ Contradiction severity (separate axis — classify every contradiction): `hard` (genuinely conflicting, must resolve), `scope-mismatch` (different scopes, coexists), `soft` (contextual, coexists).
65
+
66
+ Write the report directly to `report_path` using the structure from `wiki-lint-report.md.template`:
67
+ - `# Wiki Lint Report`; bullets for `Project`, `Generated at`, `Scope`, `Advisory status`
68
+ - `## Summary` (counts per finding class, with contradiction severity breakdown); `## Contradictions (severity-tagged)`; `## High Signal Findings`; `## Medium Signal Findings`; `## Low Signal Findings`; `## Suggested Next Steps`
69
+
70
+ Conservative rule: if there are zero meaningful findings, still write a report with zero counts and `- None.` in each findings section. If there is one clear contradiction or drift issue, report that instead of hunting for speculative findings.
71
+
72
+ Then update the persistent contradiction register at `register_path` (`.planning/wiki/CONTRADICTIONS.md`): for each contradiction found, open or refresh an entry under `<!-- wiki:contradictions:open:start -->` with severity, `Status: open`, affected pages, conflicting claims, detection date; for contradictions whose page(s) now agree with the canonical source, flip `Status: open` → `resolved` and move the entry to `<!-- wiki:contradictions:resolved:start -->` with a resolution date. Do not delete entries — move resolved ones. An entry is `resolved` only after the page was actually reconciled, not merely acknowledged.
73
+
74
+ ## 3. Report results
75
+
76
+ Display the report path, a short summary of the highest-signal findings, the number of register changes, and a reminder that the report is advisory and raw sources remain canonical. Append one `wiki-lint` entry to `.planning/wiki/log.md` (timestamp, focus scope, report path, register change count, short summary), inside `<!-- wiki:entries:start -->`/`<!-- wiki:entries:end -->` when present.
77
+
78
+ </process>
79
+
80
+ <success_criteria>
81
+ - [ ] Repo root resolved and wiki scaffold created if missing
82
+ - [ ] Relevant wiki pages and cited canonical sources inspected
83
+ - [ ] Advisory lint report written under `.planning/wiki/REPORTS/`
84
+ - [ ] Log appended
85
+ - [ ] Final user-facing summary kept raw sources as the source of truth
86
+ </success_criteria>
@@ -0,0 +1,92 @@
1
+ ---
2
+ description: Answer from the project wiki first, then fall back to canonical repo sources, optionally writing back a reusable answer
3
+ argument-hint: "[--writeback] <question>"
4
+ allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task
5
+ ---
6
+
7
+ <objective>
8
+ Answer a repository question using the compiled wiki as a first-pass map, without letting the wiki outrank raw sources.
9
+
10
+ Outputs:
11
+ - chat answer
12
+ - optional `.planning/wiki/queries/<timestamp>-<slug>.md`
13
+ - updated `.planning/wiki/index.md` and `.planning/wiki/log.md` when `--writeback` is used
14
+
15
+ Flag handling:
16
+ - `--writeback` — store a reusable answer artifact under `.planning/wiki/queries/` and refresh index/log
17
+
18
+ This is a retrieval-and-synthesis command. Raw repository docs, ADRs, tests, interfaces, and code remain canonical. Scaffold templates live at `$HOME/.claude/templates/wiki-*.template`.
19
+ </objective>
20
+
21
+ <context>
22
+ Arguments: $ARGUMENTS
23
+ </context>
24
+
25
+ <process>
26
+
27
+ ## 0. Initialize repo context
28
+
29
+ ```bash
30
+ ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
31
+ if [ -z "$ROOT" ]; then
32
+ echo "Not inside a git repository. /wiki-query must run from a project repo."
33
+ exit 1
34
+ fi
35
+ cd "$ROOT"
36
+ ```
37
+
38
+ Parse flags from `$ARGUMENTS`: `--writeback`; the remaining text is the required `question`. If `question` is empty after flag parsing, stop with a clear error.
39
+
40
+ Capture: current UTC `timestamp`, `branch`, repo basename as `project_name`, `default_branch` (try `origin/HEAD`, then `origin/main`, `main`, `master`, then `HEAD`), `query_slug` (lowercase kebab from the question).
41
+
42
+ ```bash
43
+ mkdir -p .planning/wiki/sources .planning/wiki/topics .planning/wiki/entities .planning/wiki/queries .planning/wiki/REPORTS .planning/wiki/tmp
44
+ ```
45
+
46
+ Scaffold when missing from `$HOME/.claude/templates/wiki-*.template`: `.planning/wiki/index.md`, `.planning/wiki/log.md`, `.planning/wiki/POLICY.md`.
47
+
48
+ Paths: `index_path`, `log_path`, `policy_path`, `query_output_path = {ROOT}/.planning/wiki/queries/{timestamp}-{query_slug}.md` when `writeback` is true.
49
+
50
+ ## 1. Build the retrieval scope
51
+
52
+ Read `AGENTS.md` (if present), `.planning/wiki/POLICY.md`, `.planning/wiki/index.md` first; use the index to shortlist relevant pages under `sources/`, `topics/`, `entities/`, `queries/`, and recent `REPORTS/`; read only the relevant wiki pages next; if the wiki is missing, stale, contradictory, or insufficient, read canonical repo docs/tests/interfaces/config/code directly.
53
+
54
+ Truth rules: canonical raw sources outrank derived wiki pages; prior query pages are hints, not proof; when the wiki conflicts with raw sources, preserve the contradiction and trust the raw sources.
55
+
56
+ ## 2. Answer the question
57
+
58
+ Spawn the `wiki-query-analyst` subagent via the Task tool with `subagent_type: "wiki-query-analyst"` and prompt:
59
+
60
+ ```text
61
+ <wiki_assignment>
62
+ project_root: {ROOT}
63
+ question: {question}
64
+ writeback: {writeback}
65
+ index_path: {ROOT}/.planning/wiki/index.md
66
+ log_path: {ROOT}/.planning/wiki/log.md
67
+ policy_path: {ROOT}/.planning/wiki/POLICY.md
68
+ output_path: {query_output_path or "null"}
69
+ timestamp: {timestamp}
70
+ branch: {branch}
71
+ project_name: {project_name}
72
+ </wiki_assignment>
73
+ ```
74
+
75
+ If Task/subagent execution is unavailable, run the query-analyst role inline; still answer in chat and still write the reusable query page + update index/log when `writeback` is true.
76
+
77
+ ## 3. Report results
78
+
79
+ Always answer in chat with preserved source references and caveats, calling out any contradictions or freshness uncertainty.
80
+
81
+ If `writeback` is true: mention the saved query page path; confirm the artifact is derived, not canonical; update the `Queries` section of `.planning/wiki/index.md` inside `<!-- wiki:queries:start -->`/`<!-- wiki:queries:end -->` when present (replace `- None yet.` for the first real entry); append the log entry inside `<!-- wiki:entries:start -->`/`<!-- wiki:entries:end -->` when present.
82
+
83
+ </process>
84
+
85
+ <success_criteria>
86
+ - [ ] Repo root resolved and wiki scaffold created if missing
87
+ - [ ] Index consulted before deeper reads
88
+ - [ ] Relevant wiki pages reviewed before canonical fallback
89
+ - [ ] Final chat answer preserved source references and caveats
90
+ - [ ] Reusable answer written under `.planning/wiki/queries/` when `--writeback` is used
91
+ - [ ] Index and log updated when `--writeback` is used
92
+ </success_criteria>