@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.
- package/AGENTS.md +45 -0
- package/CONTRIBUTING.md +49 -0
- package/LICENSE +201 -0
- package/README.md +149 -0
- package/SECURITY.md +37 -0
- package/bin/cairn +73 -0
- package/claude/agents/code-reviewer.md +174 -0
- package/claude/agents/security-investigator.md +112 -0
- package/claude/agents/security-target-selector.md +90 -0
- package/claude/agents/security-validator.md +97 -0
- package/claude/agents/wiki-ingester.md +108 -0
- package/claude/agents/wiki-lint-auditor.md +94 -0
- package/claude/agents/wiki-query-analyst.md +84 -0
- package/claude/commands/context-explore.md +40 -0
- package/claude/commands/graphify.md +150 -0
- package/claude/commands/memory-review.md +85 -0
- package/claude/commands/memory-sync.md +71 -0
- package/claude/commands/recall.md +32 -0
- package/claude/commands/remember.md +43 -0
- package/claude/commands/repo-review.md +191 -0
- package/claude/commands/security-audit.md +174 -0
- package/claude/commands/wiki-ingest.md +112 -0
- package/claude/commands/wiki-lint.md +86 -0
- package/claude/commands/wiki-query.md +92 -0
- package/claude/hooks/context-explore-pretask.sh +93 -0
- package/claude/hooks/memory-capture.sh +59 -0
- package/claude/hooks/memory-recall.sh +84 -0
- package/claude/hooks/memory-wakeup.sh +45 -0
- package/docs/building-an-overlay.md +117 -0
- package/docs/domain-knowledge.md +86 -0
- package/docs/git-providers.md +36 -0
- package/docs/operating.md +366 -0
- package/mcp-memory-server/dist/embeddings.js +122 -0
- package/mcp-memory-server/dist/explore-cache.js +97 -0
- package/mcp-memory-server/dist/index.js +1256 -0
- package/mcp-memory-server/package.json +36 -0
- package/opencode/agents/code-reviewer.md +173 -0
- package/opencode/agents/security-investigator.md +111 -0
- package/opencode/agents/security-target-selector.md +89 -0
- package/opencode/agents/security-validator.md +96 -0
- package/opencode/agents/wiki-ingester.md +107 -0
- package/opencode/agents/wiki-lint-auditor.md +93 -0
- package/opencode/agents/wiki-query-analyst.md +83 -0
- package/opencode/command/code-review.md +199 -0
- package/opencode/command/context-explore.md +42 -0
- package/opencode/command/graphify.md +153 -0
- package/opencode/command/memory-review.md +44 -0
- package/opencode/command/memory-sync.md +94 -0
- package/opencode/command/recall.md +38 -0
- package/opencode/command/remember.md +46 -0
- package/opencode/command/security-audit.md +80 -0
- package/opencode/command/wiki-ingest.md +55 -0
- package/opencode/command/wiki-lint.md +51 -0
- package/opencode/command/wiki-query.md +50 -0
- package/opencode/plugins/memory-capture.ts +188 -0
- package/opencode/plugins/memory-recall.ts +132 -0
- package/opencode/plugins/memory-wakeup.ts +102 -0
- package/opencode/templates/security-finding-register.yaml.template +51 -0
- package/opencode/templates/security-issue.md.template +43 -0
- package/opencode/templates/security-policy.md.template +29 -0
- package/opencode/templates/security-report.md.template +43 -0
- package/opencode/templates/wiki-contradictions.md.template +31 -0
- package/opencode/templates/wiki-index.md.template +40 -0
- package/opencode/templates/wiki-lint-report.md.template +38 -0
- package/opencode/templates/wiki-log.md.template +11 -0
- package/opencode/templates/wiki-policy.md.template +47 -0
- package/opencode/templates/wiki-query-answer.md.template +26 -0
- package/opencode/templates/wiki-source-summary.md.template +33 -0
- package/opencode/workflows/memory-review-workflow.md +66 -0
- package/opencode/workflows/security-audit-workflow.md +197 -0
- package/opencode/workflows/wiki-ingest-workflow.md +149 -0
- package/opencode/workflows/wiki-lint-workflow.md +128 -0
- package/opencode/workflows/wiki-query-workflow.md +122 -0
- package/package.json +56 -0
- package/scripts/bootstrap.sh +99 -0
- package/scripts/doctor.sh +91 -0
- package/scripts/install-audit-timer.sh +68 -0
- package/scripts/lib/assert-tool-event.mjs +50 -0
- package/scripts/memory-store.sh +71 -0
- package/scripts/memory-wiki-audit.sh +156 -0
- package/scripts/sync-claude-assets.sh +182 -0
- package/scripts/sync-opencode-explore-assets.sh +187 -0
- package/scripts/sync-opencode-graphify-assets.sh +152 -0
- package/scripts/sync-opencode-memory-assets.sh +160 -0
- package/scripts/sync-opencode-plugin-assets.sh +163 -0
- package/scripts/sync-opencode-security-assets.sh +195 -0
- package/scripts/sync-opencode-wiki-assets.sh +250 -0
- package/scripts/test-audit-timer.sh +29 -0
- package/scripts/test-bootstrap-untracked.sh +41 -0
- package/scripts/test-cli-dispatch.sh +21 -0
- package/scripts/test-doctor.sh +32 -0
- package/scripts/test-launcher-hooks.sh +66 -0
- package/scripts/test-memory-store.sh +44 -0
- package/scripts/test-remember-recall-assertions.sh +70 -0
- package/scripts/transcript-to-text.mjs +53 -0
- package/scripts/verify-docs-parity.sh +112 -0
- package/scripts/verify-explore-maturation.sh +288 -0
- package/scripts/verify-fastcontext-reliability.sh +624 -0
- package/scripts/verify-no-private-references.sh +145 -0
- package/scripts/verify-opencode-live-parity.sh +864 -0
- package/scripts/verify-routing-seam.sh +169 -0
- package/scripts/verify-token-savings-ab.sh +557 -0
- package/templates/PROJECT-INSTRUCTIONS.md.template +42 -0
- package/templates/alignment-gap-register.yaml.template +56 -0
- package/templates/alignment-policy.md.template +28 -0
- package/templates/alignment-pr-template.md.template +18 -0
- package/templates/alignment-report.md.template +56 -0
- package/templates/env.example.template +25 -0
- package/templates/graph-policy.md.template +37 -0
- package/templates/graphs-gitignore.template +3 -0
- package/templates/memory-wiki-audit.service.template +6 -0
- package/templates/memory-wiki-audit.timer.template +9 -0
- package/templates/memory.json.template +4 -0
- package/templates/planning-config.json.template +6 -0
- package/templates/project-brief.md.template +40 -0
- package/templates/security-finding-register.yaml.template +51 -0
- package/templates/security-issue.md.template +43 -0
- package/templates/security-policy.md.template +29 -0
- package/templates/security-report.md.template +43 -0
- package/templates/start-claude.sh.template +46 -0
- package/templates/start-opencode.sh.template +41 -0
- package/templates/structured-change-canvas.md.template +63 -0
- package/templates/wiki-contradictions.md.template +31 -0
- package/templates/wiki-index.md.template +40 -0
- package/templates/wiki-lint-report.md.template +38 -0
- package/templates/wiki-log.md.template +11 -0
- package/templates/wiki-policy.md.template +47 -0
- package/templates/wiki-query-answer.md.template +26 -0
- 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>
|