@kiwidata/grimoire 0.1.4 → 0.1.6
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/.claude-plugin/plugin.json +2 -2
- package/AGENTS.md +21 -25
- package/LICENSE +36 -0
- package/README.md +86 -61
- package/dist/cli/index.js +2 -43
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/program.d.ts +4 -0
- package/dist/cli/program.d.ts.map +1 -0
- package/dist/cli/program.js +45 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/commands/configure.d.ts.map +1 -1
- package/dist/commands/configure.js +2 -1
- package/dist/commands/configure.js.map +1 -1
- package/dist/core/check.d.ts.map +1 -1
- package/dist/core/check.js +47 -11
- package/dist/core/check.js.map +1 -1
- package/dist/core/ci.d.ts.map +1 -1
- package/dist/core/ci.js +2 -2
- package/dist/core/ci.js.map +1 -1
- package/dist/core/doc-style.d.ts.map +1 -1
- package/dist/core/doc-style.js +76 -0
- package/dist/core/doc-style.js.map +1 -1
- package/dist/core/docs.d.ts.map +1 -1
- package/dist/core/docs.js +93 -74
- package/dist/core/docs.js.map +1 -1
- package/dist/core/health.d.ts +6 -0
- package/dist/core/health.d.ts.map +1 -1
- package/dist/core/health.js +78 -21
- package/dist/core/health.js.map +1 -1
- package/dist/core/hooks.d.ts.map +1 -1
- package/dist/core/hooks.js +17 -19
- package/dist/core/hooks.js.map +1 -1
- package/dist/core/list.d.ts.map +1 -1
- package/dist/core/list.js +4 -7
- package/dist/core/list.js.map +1 -1
- package/dist/core/pr.d.ts.map +1 -1
- package/dist/core/pr.js +0 -8
- package/dist/core/pr.js.map +1 -1
- package/dist/core/risk-register.d.ts +17 -0
- package/dist/core/risk-register.d.ts.map +1 -0
- package/dist/core/risk-register.js +73 -0
- package/dist/core/risk-register.js.map +1 -0
- package/dist/core/shared-setup.d.ts.map +1 -1
- package/dist/core/shared-setup.js +5 -4
- package/dist/core/shared-setup.js.map +1 -1
- package/dist/core/status.d.ts.map +1 -1
- package/dist/core/status.js +3 -3
- package/dist/core/status.js.map +1 -1
- package/dist/core/trace.d.ts.map +1 -1
- package/dist/core/trace.js +37 -35
- package/dist/core/trace.js.map +1 -1
- package/dist/core/update.d.ts.map +1 -1
- package/dist/core/update.js +1 -10
- package/dist/core/update.js.map +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -3
- package/dist/index.js.map +1 -1
- package/package.json +19 -2
- package/skills/grimoire-apply/SKILL.md +40 -37
- package/skills/grimoire-audit/SKILL.md +4 -1
- package/skills/grimoire-bug/SKILL.md +7 -3
- package/skills/grimoire-commit/SKILL.md +1 -1
- package/skills/grimoire-design/SKILL.md +3 -3
- package/skills/grimoire-discover/SKILL.md +77 -110
- package/skills/grimoire-draft/SKILL.md +55 -18
- package/skills/grimoire-plan/SKILL.md +58 -52
- package/skills/grimoire-pr/SKILL.md +7 -8
- package/skills/grimoire-pr-review/SKILL.md +2 -1
- package/skills/grimoire-refactor/SKILL.md +3 -3
- package/skills/grimoire-review/SKILL.md +13 -1
- package/skills/grimoire-verify/SKILL.md +19 -7
- package/skills/grimoire-vuln-remediate/SKILL.md +107 -0
- package/skills/grimoire-vuln-triage/SKILL.md +109 -0
- package/skills/references/artifact-map.md +44 -0
- package/skills/references/code-quality.md +41 -9
- package/skills/references/container-scan-triage.md +102 -0
- package/skills/references/dependency-vuln-triage.md +236 -0
- package/skills/references/principles.md +82 -0
- package/skills/references/refactor-scan-categories.md +2 -2
- package/skills/references/review-personas.md +13 -6
- package/skills/references/test-baseline.md +55 -0
- package/skills/references/testing-contracts.md +1 -1
- package/templates/accepted-risks.yml +47 -0
- package/templates/constraints.md +25 -0
- package/dist/commands/archive.d.ts +0 -3
- package/dist/commands/archive.d.ts.map +0 -1
- package/dist/commands/archive.js +0 -22
- package/dist/commands/archive.js.map +0 -1
- package/dist/commands/log.d.ts +0 -3
- package/dist/commands/log.d.ts.map +0 -1
- package/dist/commands/log.js +0 -15
- package/dist/commands/log.js.map +0 -1
- package/dist/commands/map.d.ts +0 -3
- package/dist/commands/map.d.ts.map +0 -1
- package/dist/commands/map.js +0 -16
- package/dist/commands/map.js.map +0 -1
- package/dist/core/archive.d.ts +0 -9
- package/dist/core/archive.d.ts.map +0 -1
- package/dist/core/archive.js +0 -81
- package/dist/core/archive.js.map +0 -1
- package/dist/core/log.d.ts +0 -8
- package/dist/core/log.d.ts.map +0 -1
- package/dist/core/log.js +0 -140
- package/dist/core/log.js.map +0 -1
- package/dist/core/map.d.ts +0 -22
- package/dist/core/map.d.ts.map +0 -1
- package/dist/core/map.js +0 -365
- package/dist/core/map.js.map +0 -1
- package/templates/dupignore +0 -93
- package/templates/mapignore +0 -58
- package/templates/mapkeys +0 -65
|
@@ -38,7 +38,7 @@ Derive implementation tasks from approved Gherkin features and MADR decisions. T
|
|
|
38
38
|
- "See if there's an existing utility for Z"
|
|
39
39
|
- "TODO: check if this conflicts with…"
|
|
40
40
|
|
|
41
|
-
Resolve each one yourself before writing the task. Tools: codebase-memory-mcp (`search_graph`, `trace_path`, `get_code_snippet`), `.grimoire/docs/<area>.md`
|
|
41
|
+
Resolve each one yourself before writing the task. Tools: codebase-memory-mcp (`search_graph`, `trace_path`, `get_code_snippet`) for symbols and reusable code, `.grimoire/docs/<area>.md` for conventions/boundaries, `Grep`, neighbor files. The task should state the *answer* ("Reuse `parse_invoice` in `src/billing/parsing.py:42`" or "No existing utility — write new"), never the *question*.
|
|
42
42
|
|
|
43
43
|
**2. Clarify or propose, never assume.** When the spec is ambiguous or silent on something you need to plan:
|
|
44
44
|
|
|
@@ -48,6 +48,14 @@ Resolve each one yourself before writing the task. Tools: codebase-memory-mcp (`
|
|
|
48
48
|
|
|
49
49
|
The plan implements what's approved. It does not expand scope to hit a checklist.
|
|
50
50
|
|
|
51
|
+
**3. Plan to the principles.** Every task is gated by the four principles in `../references/principles.md` — **one right way, DRY, don't reinvent the wheel, keep it simple.** Concretely, before writing each task:
|
|
52
|
+
- **One right way:** name the single sanctioned approach. If the spec leaves two ways open, pick one (record why in the task) — never plan both.
|
|
53
|
+
- **DRY:** reuse before write (search the graph); don't plan a task that stores a fact already derivable from code/mcp or already homed elsewhere.
|
|
54
|
+
- **Don't reinvent:** prefer an existing tool/library/proven pattern over a bespoke mechanism. git for change process, standard libs for crypto/auth/parsing.
|
|
55
|
+
- **Keep it simple:** choose the least-code option inside the non-goals. Flag any task that adds an abstraction, a dependency, or a second mechanism — it needs an explicit reason.
|
|
56
|
+
|
|
57
|
+
These are gates, not aspirations — a task that adds a duplicate home or a reinvented wheel is rejected, not refined.
|
|
58
|
+
|
|
51
59
|
### 1. Select Change
|
|
52
60
|
- List active changes in `.grimoire/changes/`
|
|
53
61
|
- If multiple, ask user which one to plan
|
|
@@ -55,13 +63,11 @@ The plan implements what's approved. It does not expand scope to hit a checklist
|
|
|
55
63
|
|
|
56
64
|
### 2. Read All Artifacts
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
Read the change's artifacts following `../references/artifact-map.md` — it defines what each file is, the grimoire-docs-first / graph-for-structure discipline, and the staleness gate. Plan-specific reading on top of that:
|
|
59
67
|
|
|
60
|
-
|
|
61
|
-
- `
|
|
62
|
-
-
|
|
63
|
-
- All proposed decision records, **including Cost of Ownership sections**
|
|
64
|
-
- The current baseline (`features/`, `.grimoire/decisions/`) for context on what's changing
|
|
68
|
+
- `.grimoire/docs/constraints.md` — any constraints (security/NFR/observability) this change touches. These produce `unit-invariant` tasks, not scenarios.
|
|
69
|
+
- The current baseline (`features/`, `.grimoire/decisions/`) via `git diff main` — exactly what this change adds vs. what already existed.
|
|
70
|
+
- Existing duplication in areas you're touching — `search_graph` for similar functions, or `grimoire health` (its `duplicates` metric) — so tasks consolidate rather than clone.
|
|
65
71
|
|
|
66
72
|
**Validate the build-vs-buy decision:**
|
|
67
73
|
- Check that `manifest.md` has a **Prior Art** section documenting what existing solutions were researched. If it's missing or empty, **stop and tell the user** — planning without a build-vs-buy analysis produces plans that ignore cheaper alternatives.
|
|
@@ -69,27 +75,6 @@ The plan implements what's approved. It does not expand scope to hit a checklist
|
|
|
69
75
|
- If the decision was to **build custom**, verify the manifest documents (1) what existing tools were considered, (2) the specific requirements they don't meet, and (3) what design patterns are being borrowed from prior art.
|
|
70
76
|
- If the decision was **hybrid** (adopt for part, build for part), ensure the boundary between adopted and custom code is clear in the tasks.
|
|
71
77
|
|
|
72
|
-
**Read from grimoire docs (these replace codebase exploration):**
|
|
73
|
-
- **`.grimoire/docs/<area>.md`** for each area the change touches — these contain: key files with responsibilities, reusable utilities (exact function names, file paths, line numbers), naming conventions, structural patterns, and "Where New Code Goes" guidance. This is the information that lets you write tasks with exact file paths without reading every source file.
|
|
74
|
-
- **`.grimoire/docs/data/schema.yml`** — the full data model: every table/collection, field types, relationships, indexes, and external API contracts with `source:` pointers to ORM code. Read this instead of reading individual model files.
|
|
75
|
-
- **`.grimoire/docs/context.yml`** — the project's deployment environment, related services, infrastructure dependencies, CI/CD pipelines, and observability setup. Read this to understand deployment constraints (e.g., Lambda means no long-running processes, Kubernetes means you may need health check endpoints), cross-service boundaries (e.g., auth is handled by a sibling service, not this project), and infrastructure available at runtime (e.g., Redis is available for caching, RabbitMQ for async tasks).
|
|
76
|
-
- **`.grimoire/docs/.snapshot.json`** `duplicates` section if present — existing clones in areas you're touching, so tasks consolidate rather than add more.
|
|
77
|
-
|
|
78
|
-
**Read proposed data changes:**
|
|
79
|
-
- **`data.yml`** if present — proposed schema changes need migration and model tasks
|
|
80
|
-
|
|
81
|
-
**Staleness gate:** For each area doc loaded, check its `last_updated` date against `git log -1 --format=%ci <directory>`. If any doc is older than the most recent commit to its directory, it's stale — the file paths, utility names, and patterns it describes may no longer be accurate.
|
|
82
|
-
|
|
83
|
-
- **Level 1-2:** Warn ("Area doc for `<area>` is behind recent commits — reusable utilities and file paths may be wrong") and proceed. Note inferred paths with `<!-- inferred: area doc may be stale -->`.
|
|
84
|
-
- **Level 3-4:** Treat as a blocker. Do not generate tasks until the user refreshes stale docs via `grimoire-discover` targeted refresh. Planning with stale docs at this complexity produces wrong file paths and misses recent utilities — the cost of re-planning outweighs the cost of refreshing first.
|
|
85
|
-
|
|
86
|
-
**Read specific source files only when:**
|
|
87
|
-
- Area docs don't exist yet (tell the user to run `grimoire map` + `/grimoire:discover` first — planning without area docs produces worse tasks)
|
|
88
|
-
- Area docs exist but you need to verify a specific implementation detail (e.g., exact function signature, exact import path)
|
|
89
|
-
- You need to read existing step definitions to understand the test setup
|
|
90
|
-
|
|
91
|
-
**Do NOT read the entire codebase** for "context." The plan skill's job is to produce tasks with specific file paths and specific assertions. Area docs + data schema give you this. Reading dozens of source files wastes context window and doesn't produce better plans.
|
|
92
|
-
|
|
93
78
|
### 3. Check Specification Completeness
|
|
94
79
|
|
|
95
80
|
Before generating tasks, evaluate whether the specifications are detailed enough to plan against. Underspecified requirements produce vague tasks, which produce wrong code.
|
|
@@ -133,11 +118,22 @@ Level 1-2 changes with minor gaps may proceed; level 3-4 with multiple gaps shou
|
|
|
133
118
|
**If no real gaps**, proceed directly to task generation.
|
|
134
119
|
|
|
135
120
|
### 4. Generate Tasks
|
|
136
|
-
Create `.grimoire/changes/<change-id>/tasks.md`. **Every
|
|
121
|
+
Create `.grimoire/changes/<change-id>/tasks.md`. **Every task produces both production code AND a test — but the test level matches the artifact the task derives from.** Tasks are structured as pairs: the failing test first, then the production code.
|
|
122
|
+
|
|
123
|
+
**Tag every implementation task with a `verify:` level** — this tells `grimoire-apply` which test vehicle to use. Match the artifact:
|
|
124
|
+
|
|
125
|
+
| Task derives from | `verify:` | Test vehicle |
|
|
126
|
+
|-------------------|-----------|--------------|
|
|
127
|
+
| a `.feature` scenario (actor-observable behavior) | `scenario` | step definitions + Gherkin |
|
|
128
|
+
| a constraint in `constraints.md` (security/NFR/observability) | `unit-invariant` | unit/integration test asserting the invariant |
|
|
129
|
+
| an ADR consequence, refactor, or internal change with no spec | `characterization` | unit / characterization test |
|
|
130
|
+
|
|
131
|
+
**Do not plan a `.feature` scenario task for a constraint or an internal change.** Constraints get `unit-invariant` unit tests; internal changes get `characterization` tests. Forcing Gherkin onto a non-behavioral concern is the antipattern that fills feature files with slop (one right way: behavior → scenario, everything else → unit test).
|
|
137
132
|
|
|
138
133
|
**THE PLAN'S SCOPE IS WHAT WAS APPROVED.** Tasks may only derive from:
|
|
139
|
-
-
|
|
140
|
-
-
|
|
134
|
+
- `.feature` scenarios in this change → `verify: scenario`
|
|
135
|
+
- Constraints added/touched in `.grimoire/docs/constraints.md` → `verify: unit-invariant`
|
|
136
|
+
- ADRs in this change (and their Confirmation sections) → `verify: unit-invariant` or `characterization`
|
|
141
137
|
- `data.yml` entries in this change
|
|
142
138
|
- The manifest's Assumptions, Pre-Mortem mitigations, and Prior Art borrowings
|
|
143
139
|
- Verification tasks (run feature suite, run project suite, validate ADR confirmation)
|
|
@@ -259,8 +255,8 @@ Follow the rules in `../references/testing-contracts.md`. Key points: mock at HT
|
|
|
259
255
|
- If a library was rejected for a specific reason (e.g., doesn't support X), add a comment to the relevant task noting this so future developers don't re-evaluate the same option
|
|
260
256
|
|
|
261
257
|
**Existing code to reuse:**
|
|
262
|
-
-
|
|
263
|
-
- If
|
|
258
|
+
- Query the graph (`search_graph` by concept/name) for existing utilities that apply to this change; area docs give conventions, the graph gives the reusable symbols
|
|
259
|
+
- If `grimoire health`/mcp shows existing clones in the area you're touching, tasks should consolidate rather than add more
|
|
264
260
|
- Add a "Reuse" section at the top of tasks.md listing specific functions/classes to import instead of rewriting
|
|
265
261
|
|
|
266
262
|
**Verification (always last):**
|
|
@@ -282,12 +278,12 @@ The tasks file starts with a context block so any LLM can orient without re-read
|
|
|
282
278
|
|
|
283
279
|
## 1. <Capability/Area>
|
|
284
280
|
<!-- context:
|
|
285
|
-
-
|
|
281
|
+
- features/<name>.feature
|
|
286
282
|
- .grimoire/docs/<area>.md
|
|
287
283
|
- src/<area>/<file-to-edit>.ts
|
|
288
284
|
- tests/<area>/<test-file>.ts
|
|
289
285
|
-->
|
|
290
|
-
- [ ] 1.1 Write step defs in `<exact path>` for scenario: "<scenario name>" in
|
|
286
|
+
- [ ] 1.1 (verify: scenario) Write step defs in `<exact path>` for scenario: "<scenario name>" in `features/<file>`
|
|
291
287
|
- Given: <what the step does, what it calls>
|
|
292
288
|
- When: <what the step does, what it calls>
|
|
293
289
|
- Then: <what to assert — specific expected values/states>
|
|
@@ -295,32 +291,40 @@ The tasks file starts with a context block so any LLM can orient without re-read
|
|
|
295
291
|
- <specific function/class/view to create or modify>
|
|
296
292
|
- <specific behavior to implement>
|
|
297
293
|
- <edge cases to handle>
|
|
298
|
-
- [ ] 1.3 Write step defs in `<exact path>` for scenario: "<next scenario>"
|
|
299
|
-
...
|
|
300
|
-
- [ ] 1.4 Implement in `<exact path>`:
|
|
301
|
-
...
|
|
302
294
|
|
|
303
|
-
## 2.
|
|
295
|
+
## 2. Constraints
|
|
296
|
+
<!-- context:
|
|
297
|
+
- .grimoire/docs/constraints.md
|
|
298
|
+
- src/<area>/<file-to-edit>.ts
|
|
299
|
+
- tests/<area>/<unit-test-file>.ts
|
|
300
|
+
-->
|
|
301
|
+
- [ ] 2.1 (verify: unit-invariant) Write unit test in `<exact path>` asserting constraint: "<assertion from constraints.md>"
|
|
302
|
+
- Arrange: <setup>
|
|
303
|
+
- Assert: <the invariant — exact expected behavior, no Gherkin>
|
|
304
|
+
- [ ] 2.2 Implement in `<exact path>`:
|
|
305
|
+
- <specific change that satisfies the invariant>
|
|
306
|
+
|
|
307
|
+
## 3. Shared Steps
|
|
304
308
|
<!-- context:
|
|
305
309
|
- tests/step_defs/common.py
|
|
306
|
-
-
|
|
310
|
+
- features/<all relevant .feature files>
|
|
307
311
|
-->
|
|
308
|
-
- [ ]
|
|
312
|
+
- [ ] 3.1 Add to `<exact path>`:
|
|
309
313
|
- Given "<step text>": <what it does>
|
|
310
314
|
- Given "<step text>": <what it does>
|
|
311
315
|
|
|
312
|
-
##
|
|
316
|
+
## 4. Architecture
|
|
313
317
|
<!-- context:
|
|
314
|
-
- .grimoire/
|
|
318
|
+
- .grimoire/decisions/<nnnn-title>.md
|
|
315
319
|
- src/<files affected by decision>
|
|
316
320
|
-->
|
|
317
|
-
- [ ]
|
|
318
|
-
- [ ]
|
|
321
|
+
- [ ] 4.1 (verify: characterization) In `<exact path>`: <specific change from ADR>
|
|
322
|
+
- [ ] 4.2 Add test in `<exact path>`: <ADR confirmation check — what to assert>
|
|
319
323
|
|
|
320
|
-
##
|
|
321
|
-
- [ ]
|
|
322
|
-
- [ ]
|
|
323
|
-
- [ ]
|
|
324
|
+
## 5. Verification
|
|
325
|
+
- [ ] 5.1 Run `<exact test command>` — all new scenarios green
|
|
326
|
+
- [ ] 5.2 Run `<exact test command>` — no regressions
|
|
327
|
+
- [ ] 5.3 Run `<exact test command>` — full project suite
|
|
324
328
|
```
|
|
325
329
|
|
|
326
330
|
**Context blocks are mandatory.** Every task section (except Verification) must have a `<!-- context: ... -->` listing the files needed. This serves two purposes:
|
|
@@ -330,11 +334,13 @@ The tasks file starts with a context block so any LLM can orient without re-read
|
|
|
330
334
|
### 6. Quality Check
|
|
331
335
|
Before presenting to the user, verify the plan:
|
|
332
336
|
- [ ] Every task references a specific file path (no "implement the feature")
|
|
333
|
-
- [ ] Every
|
|
337
|
+
- [ ] Every implementation task carries a `verify:` tag matching its source artifact — `scenario` only for `.feature` behavior; `unit-invariant` for constraints; `characterization` for internal/refactor. No `.feature` scenario task for a constraint or internal change.
|
|
338
|
+
- [ ] Every test task describes what to assert (no "write a test")
|
|
334
339
|
- [ ] Every implementation task describes what to create/modify (no "add the code")
|
|
335
340
|
- [ ] The verification section has the exact commands to run
|
|
336
|
-
- [ ] Tasks are ordered: shared steps →
|
|
341
|
+
- [ ] Tasks are ordered: shared steps → test → production code → verification
|
|
337
342
|
- [ ] No task requires the LLM to make architectural decisions — those should already be in the ADR
|
|
343
|
+
- [ ] **Principles gate** (`../references/principles.md`): no task introduces a duplicate home for an existing fact (DRY), a second way to do an existing thing (one right way), a reinvented wheel where a tool/library/proven pattern exists (don't reinvent), or an abstraction/dependency justified only by a hypothetical (KISS). Any that does has a stated reason.
|
|
338
344
|
|
|
339
345
|
If any task is too vague, make it more specific before presenting. Read more codebase if needed.
|
|
340
346
|
|
|
@@ -17,14 +17,14 @@ Generate a pull request description from grimoire change artifacts and optionall
|
|
|
17
17
|
- Loose match: "PR", "pull request", "ready to merge", "create PR"
|
|
18
18
|
|
|
19
19
|
## Routing
|
|
20
|
-
- Tasks incomplete or finalize not done → `grimoire-apply` first. Do not create a PR before the change is finalized — PR
|
|
20
|
+
- Tasks incomplete or finalize not done → `grimoire-apply` first. Do not create a PR before the change is finalized — the PR reflects the finished branch state (decisions accepted, change folder removed).
|
|
21
21
|
- Haven't committed yet → `grimoire-commit` first
|
|
22
22
|
- Want a pre-merge design review → this skill includes optional post-implementation review
|
|
23
23
|
|
|
24
24
|
## Prerequisites
|
|
25
|
-
- Change has been finalized: `.grimoire/changes/<change-id>/` is removed
|
|
26
|
-
-
|
|
27
|
-
- The change is on a feature branch (created during apply)
|
|
25
|
+
- Change has been finalized: `.grimoire/changes/<change-id>/` is removed (manifest/tasks were ephemeral scaffolding)
|
|
26
|
+
- Decision records are live in `.grimoire/decisions/` with status `accepted`
|
|
27
|
+
- The change is on a feature branch (created during draft/apply); its diff vs. `main` is the change
|
|
28
28
|
|
|
29
29
|
## Workflow
|
|
30
30
|
|
|
@@ -117,9 +117,8 @@ Check that the branch is pushed to the remote before creating. If not, offer to
|
|
|
117
117
|
|
|
118
118
|
### 6. Link Back
|
|
119
119
|
After PR creation:
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
- Suggest running `grimoire archive <change-id>` to complete the lifecycle
|
|
120
|
+
- The `Change: <change-id>` trailer on the commits links them to the change; the PR body + git log are the durable record (the change folder was already removed at finalize).
|
|
121
|
+
- Suggest merging the PR to complete the change. There is no archive step — git history is the history.
|
|
123
122
|
|
|
124
123
|
## Important
|
|
125
124
|
- The PR description must trace back to grimoire artifacts — this is what makes the audit trail work.
|
|
@@ -129,4 +128,4 @@ After PR creation:
|
|
|
129
128
|
- If tasks are incomplete, warn the user but don't block PR creation — they may want a draft PR.
|
|
130
129
|
|
|
131
130
|
## Done
|
|
132
|
-
When the PR is created (or description is presented for manual creation), the workflow is complete. Suggest
|
|
131
|
+
When the PR is created (or description is presented for manual creation), the workflow is complete. Suggest merging the PR to complete the change — git history + the `Change:` trailer are the record; there is no separate archive step.
|
|
@@ -64,13 +64,14 @@ git log <base>..<head> --format="%B" | grep -E "^Change:"
|
|
|
64
64
|
|
|
65
65
|
If present:
|
|
66
66
|
- Change ID = trailer value
|
|
67
|
-
- Load artifacts:
|
|
67
|
+
- Load artifacts: check `.grimoire/changes/<change-id>/` for an active change. If the change is already finalized/merged the change folder is gone — read the artifacts from the PR's head branch (`git diff main` shows the live `features/`, `.grimoire/decisions/`, `.grimoire/docs/constraints.md`) and use the `Change:` trailer to correlate commits.
|
|
68
68
|
- Read `manifest.md`, all `.feature` files in the change, decision records, `tasks.md`, `data.yml`
|
|
69
69
|
- Also grep for `Scenarios:` and `Decisions:` trailers to scope review to the named items
|
|
70
70
|
|
|
71
71
|
If no `Change:` trailer exists, that's itself a finding for a grimoire-managed repo: flag as **suggestion** ("commits missing audit trailer — `grimoire trace` won't find this PR") unless the project clearly doesn't use grimoire.
|
|
72
72
|
|
|
73
73
|
### 4. Gather Project Context
|
|
74
|
+
See `../references/artifact-map.md` for what each artifact is and the grimoire-docs-first / staleness discipline.
|
|
74
75
|
- `.grimoire/config.yaml` — language, tools, `commit_style`, `comment_style`, `project.compliance`, `dep_audit`
|
|
75
76
|
- `.grimoire/docs/context.yml` — deployment environment, related services
|
|
76
77
|
- `.grimoire/docs/data/schema.yml` — current data baseline
|
|
@@ -26,7 +26,7 @@ Systematically find, prioritize, and plan tech debt reduction. Combines automate
|
|
|
26
26
|
## Prerequisites
|
|
27
27
|
- A grimoire-initialized project (`.grimoire/` exists)
|
|
28
28
|
- Git history available (hotspot analysis needs `git log`)
|
|
29
|
-
- Ideally:
|
|
29
|
+
- Ideally: codebase-memory-mcp indexed (live structure/duplication intelligence) + `/grimoire:discover` run (area intent docs help contextualize findings)
|
|
30
30
|
|
|
31
31
|
## Debt Item Format
|
|
32
32
|
|
|
@@ -113,7 +113,7 @@ Run applicable scans from the categories in `../references/refactor-scan-categor
|
|
|
113
113
|
- **Circular dependencies** — tight coupling between modules
|
|
114
114
|
- **Dependency staleness** — uses `config.tools.dep_audit` or package manager outdated commands
|
|
115
115
|
- **Broken promises** — aged TODO/FIXME/HACK comments via `grep` + `git blame`
|
|
116
|
-
- **Duplication** — textual clones via
|
|
116
|
+
- **Duplication** — textual clones via `config.tools.duplicates` or `grimoire health` (config-driven duplicates metric); plus semantic duplicate detection via `search_graph(semantic_query=[...])` to find re-implementations under different names (requires `codebase-memory-mcp`)
|
|
117
117
|
- **Dead code** — uses `config.tools.dead_code` or `codebase-memory-mcp` graph queries
|
|
118
118
|
- **Test debt** — high complexity + low coverage
|
|
119
119
|
- **Pattern divergence** — code that contradicts established codebase patterns; uses `codebase-memory-mcp` peer group analysis + hallucinated reference detection (skip if graph not indexed)
|
|
@@ -209,7 +209,7 @@ For each item the user approves to fix:
|
|
|
209
209
|
4. Hand off to `/grimoire:plan` for task generation, then `/grimoire:apply` for implementation
|
|
210
210
|
|
|
211
211
|
**Refactoring-specific guidance for the plan/apply stages:**
|
|
212
|
-
- **
|
|
212
|
+
- **Capture a baseline first, then keep it.** Apply records which tests were already failing at change start (`baseline.md`, see `../references/test-baseline.md`). For a refactor this is the whole safety net: "passing" means *no new failures vs the baseline*, not "zero failures." A test red before you started is pre-existing and accepted; a test you turn red is the refactor breaking behavior — and that means it's not a refactoring. Diff against the baseline after each incremental move.
|
|
213
213
|
- **Prefer incremental moves over big-bang rewrites.** Move one function at a time, run tests after each move.
|
|
214
214
|
- **Add tests before refactoring if test debt is part of the item.** You need a safety net before restructuring.
|
|
215
215
|
- **Update imports incrementally.** When moving code to a new module, re-export from the old location first, then update consumers, then remove the re-export.
|
|
@@ -42,7 +42,7 @@ This step is optional. The user can skip it by saying "skip review" or "go strai
|
|
|
42
42
|
- If only one, confirm it
|
|
43
43
|
|
|
44
44
|
### 2. Gather Context
|
|
45
|
-
Read all artifacts for the change:
|
|
45
|
+
Read all artifacts for the change — see `../references/artifact-map.md` for what each is and the grimoire-docs-first / staleness discipline:
|
|
46
46
|
- `manifest.md` — change summary, scope, **and Prior Art section** (build-vs-buy rationale)
|
|
47
47
|
- All `.feature` files — behavioral specifications
|
|
48
48
|
- All decision records — architectural choices
|
|
@@ -95,6 +95,12 @@ Persona scope for design review:
|
|
|
95
95
|
- 4.6 Code Style Reviewer — **skip** (no code yet; runs only on diff reviews)
|
|
96
96
|
- 4.7 Adversarial User — engage per matrix; criteria in `../references/adversarial-personas.md`
|
|
97
97
|
- 4.8 Contrarian — runs last when any persona produced a blocker; calibrates other personas' findings post-hoc
|
|
98
|
+
- 4.9 Principles Auditor — **runs on every review (complexity ≥ 2), always.** Audits the design against the four principles in `../references/principles.md` and raises a finding for each violation lacking a stated reason:
|
|
99
|
+
- **One right way** — does any artifact introduce a second way to do something the codebase already does? Does a spec leave two approaches open ("X or Y")? → blocker until one is chosen.
|
|
100
|
+
- **DRY** — is any fact given a second home (a capability in feature + MADR + constraint; a constant/rule duplicated)? Does any task store something derivable from code/mcp? → blocker.
|
|
101
|
+
- **Don't reinvent the wheel** — does any task build a mechanism that an existing tool/library/proven pattern already provides (custom crypto/auth, a bespoke change-tracking/diff/staging process where git suffices)? → blocker.
|
|
102
|
+
- **Keep it simple** — any abstraction, indirection, new dependency, or new file justified only by a hypothetical, or scope reaching past a non-goal? → suggestion (blocker if it adds a maintained surface).
|
|
103
|
+
- Also enforce the **artifact-jurisdiction** rule: any `.feature` scenario that is really a constraint (security/NFR/observability), an internal technical detail, or a non-functional concern is a blocker — it belongs in `constraints.md` or a MADR, not Gherkin.
|
|
98
104
|
|
|
99
105
|
### 5.5 Visual Fidelity (cheap tier)
|
|
100
106
|
|
|
@@ -144,6 +150,12 @@ Compile into the standard report layout (§5 of the personas reference):
|
|
|
144
150
|
- **[suggestion]** [axe-color-contrast] `designs/preview.html` — Element has insufficient color contrast 3.8. Impact: serious.
|
|
145
151
|
(or: "axe-core: no violations." / "axe-core not installed — install `@axe-core/cli` for accessibility checks.")
|
|
146
152
|
|
|
153
|
+
## Principles Auditor
|
|
154
|
+
- **[blocker]** [DRY] PII-scrubbing behavior is specified in both `features/pii-log-scrubbing.feature` and ADR-0008 — one authoritative home. Move to `constraints.md`, link the MADR.
|
|
155
|
+
- **[blocker]** [jurisdiction] `features/logging-observability.feature` describes internal log structure (no external actor) — belongs in `constraints.md`, not a `.feature`.
|
|
156
|
+
- **[suggestion]** [KISS] Task 3.2 adds a `BaseExtractor` for a single caller — inline until a second extractor exists.
|
|
157
|
+
(or: "No principle violations found.")
|
|
158
|
+
|
|
147
159
|
## Contrarian <!-- omit when zero findings from all personas -->
|
|
148
160
|
- **[blocker upheld]** ...
|
|
149
161
|
- **[blocker → suggestion]** ...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: grimoire-verify
|
|
3
|
-
description: Verify that implementation matches feature specs and decision records. Use after apply is complete, before
|
|
3
|
+
description: Verify that implementation matches feature specs and decision records. Use after apply is complete, before committing and opening a PR.
|
|
4
4
|
compatibility: Designed for Claude Code (or similar products)
|
|
5
5
|
metadata:
|
|
6
6
|
author: kiwi-data
|
|
@@ -9,11 +9,11 @@ metadata:
|
|
|
9
9
|
|
|
10
10
|
# grimoire-verify
|
|
11
11
|
|
|
12
|
-
Verify that implementation matches the feature specs and decision records. Run after apply, before
|
|
12
|
+
Verify that implementation matches the feature specs and decision records. Run after apply, before commit and PR.
|
|
13
13
|
|
|
14
14
|
## Triggers
|
|
15
15
|
- User wants to verify a grimoire change is correctly implemented
|
|
16
|
-
- User asks to check, verify, or review a change before
|
|
16
|
+
- User asks to check, verify, or review a change before committing
|
|
17
17
|
- Loose match: "verify", "check", "review" with a change reference
|
|
18
18
|
|
|
19
19
|
## Routing
|
|
@@ -41,6 +41,7 @@ Two modes:
|
|
|
41
41
|
### 2. Load Artifacts
|
|
42
42
|
For change verification:
|
|
43
43
|
- Read `manifest.md`, proposed `.feature` files, decision records, `tasks.md`
|
|
44
|
+
- Read `baseline.md` if present (the test state captured at change start) — it's how you tell a regression from a failure that was already red
|
|
44
45
|
|
|
45
46
|
For baseline verification:
|
|
46
47
|
- Read all `features/**/*.feature` and `.grimoire/decisions/*.md`
|
|
@@ -76,6 +77,17 @@ Flag issues:
|
|
|
76
77
|
- Decision's Confirmation criteria not verifiable → WARNING
|
|
77
78
|
- Decision consequences not addressed → WARNING
|
|
78
79
|
|
|
80
|
+
### 3.C2 Regression vs Baseline
|
|
81
|
+
|
|
82
|
+
Run the configured suites (`config.tools.unit_test`, `config.tools.bdd_test`) and classify each failure against `baseline.md`:
|
|
83
|
+
|
|
84
|
+
- Failing now **and** in the baseline → **pre-existing**, already accepted by the user at change start. Not a regression. Do not blame the change.
|
|
85
|
+
- Failing now, **not** in the baseline → **regression** introduced by this change → CRITICAL. Must be fixed before the change finalizes.
|
|
86
|
+
- Passing now, failing in the baseline → incidentally fixed; note it, don't require it.
|
|
87
|
+
- **No `baseline.md` / baseline skipped** → you cannot classify. List all failures and say plainly they're untriaged. Do NOT assert "existing tests pass" or call anything "pre-existing" without a baseline to back it.
|
|
88
|
+
|
|
89
|
+
The rule: a failure is "pre-existing" only if it's in `baseline.md`. Otherwise it's the change's. Full protocol: `../references/test-baseline.md`.
|
|
90
|
+
|
|
79
91
|
### 3.D Test Quality Intelligence
|
|
80
92
|
|
|
81
93
|
Go beyond "does a step definition exist?" to "would this test catch a real bug?"
|
|
@@ -236,8 +248,8 @@ Produce a structured report:
|
|
|
236
248
|
|
|
237
249
|
### 8. Recommend Next Steps
|
|
238
250
|
Based on the report:
|
|
239
|
-
- **All clear** → recommend
|
|
240
|
-
- **Critical issues** → must fix before
|
|
251
|
+
- **All clear** → recommend committing and opening a PR (git diff is the staging area, the PR is the changelog)
|
|
252
|
+
- **Critical issues** → must fix before committing
|
|
241
253
|
- **Warnings only** → user decides whether to fix or accept
|
|
242
254
|
- **Dead features found** → suggest a removal change or updating the features
|
|
243
255
|
|
|
@@ -251,6 +263,6 @@ Based on the report:
|
|
|
251
263
|
|
|
252
264
|
## Done
|
|
253
265
|
When the verification report is presented, the workflow is complete. Suggest next steps based on findings:
|
|
254
|
-
- **All clear** → `grimoire
|
|
255
|
-
- **Critical issues** → must fix before
|
|
266
|
+
- **All clear** → `grimoire-commit` then `grimoire-pr`
|
|
267
|
+
- **Critical issues** → must fix before committing
|
|
256
268
|
- **Warnings only** → user decides whether to fix or accept
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: grimoire-vuln-remediate
|
|
3
|
+
description: File the dev work from a vulnerability triage — turn affected findings into tickets in the configured bug tracker, record risk-accepted items with expiry, and stub grimoire changes for non-trivial fixes. Consumes a grimoire-vuln-triage record. Use after triage, when you're ready to action the findings that actually matter.
|
|
4
|
+
compatibility: Designed for Claude Code (or similar products)
|
|
5
|
+
metadata:
|
|
6
|
+
author: kiwi-data
|
|
7
|
+
version: "0.1"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# grimoire-vuln-remediate
|
|
11
|
+
|
|
12
|
+
`grimoire-vuln-triage` decides *what matters*. This skill **files the work** for the findings that survived: it turns `affected` advisories into tickets in the team's configured bug reporting system, records `accept` items in a risk-acceptance register with an expiry, and stubs a grimoire change for fixes too big to be a one-line bump. It never invents urgency — it acts on the triage's verdicts.
|
|
13
|
+
|
|
14
|
+
The split is deliberate: triage classifies (read-only, repeatable), remediate commits to action (writes tickets, branches, registers). Run triage first.
|
|
15
|
+
|
|
16
|
+
## Triggers
|
|
17
|
+
- After triage: "file these", "create the tickets", "remediate the CVEs", "action the vuln triage"
|
|
18
|
+
- "open tickets for the affected vulnerabilities", "track the risk-accepted ones"
|
|
19
|
+
- User points at a triage record and asks to take it forward
|
|
20
|
+
- Loose match: "vuln remediate", "file vulnerabilities", "security tickets", "remediation plan"
|
|
21
|
+
|
|
22
|
+
## Routing
|
|
23
|
+
- No triage record yet → `grimoire-vuln-triage` first. Do not file tickets off a raw scanner dump — file only what triage marked `affected`.
|
|
24
|
+
- A fix that's a real code change (new abstraction, behavior change, schema) → stub a change and hand to `grimoire-draft` / `grimoire-plan` / `grimoire-apply`.
|
|
25
|
+
- A confirmed-exploitable code defect a developer will fix immediately → `grimoire-bug` (reproduction-first).
|
|
26
|
+
- Infra follow-ups (base-image bump, secrets-in-image, IaC misconfig from the triage's "Infra follow-ups") → infra board / `grimoire-draft`, not app remediation.
|
|
27
|
+
|
|
28
|
+
## Prerequisites
|
|
29
|
+
- A triage record at `.grimoire/security/vulns/<run-date>/triage.md` (from `grimoire-vuln-triage`). If the user points at a different path, use it.
|
|
30
|
+
- `.grimoire/config.yaml` — read `bug_trackers` (MCP) for where to file. If `none`, fall back to a local remediation doc.
|
|
31
|
+
|
|
32
|
+
## Workflow
|
|
33
|
+
|
|
34
|
+
### 1. Read the triage record
|
|
35
|
+
|
|
36
|
+
Load the triage. Pull the actionable buckets — **ignore `fixed` and `not_affected`** (triage already dismissed them; they are the audit trail, not work):
|
|
37
|
+
- **hotfix-now** — expedited, confidential handling.
|
|
38
|
+
- **next-release** — normal release-cycle work.
|
|
39
|
+
- **accept** — no fix available / low risk → goes to the risk-acceptance register, not a fix ticket.
|
|
40
|
+
- **under_investigation** — file a time-boxed investigation task, not a fix. **Does not enter the risk register** — it isn't a decision yet. When the investigation resolves, re-run remediate so it routes to close / ticket / register.
|
|
41
|
+
- **Infra follow-ups** — route separately (Step 5).
|
|
42
|
+
|
|
43
|
+
Cross-check the record's totals against what you're about to file so nothing is dropped or invented.
|
|
44
|
+
|
|
45
|
+
### 2. Decide the fix type per affected item
|
|
46
|
+
|
|
47
|
+
For each `affected` advisory, classify the remediation so it routes correctly:
|
|
48
|
+
- **Trivial bump** — a patch/minor version with a fix exists (`upgrade X 1.2.3 → 1.2.4`), no API break. Can be a direct PR or a simple ticket.
|
|
49
|
+
- **Non-trivial fix** — major-version bump, code changes, base-image rebuild, or a transitive dep that needs a constraint/override. Needs design → stub a grimoire change (Step 4).
|
|
50
|
+
- **No fix available** — `will_not_fix` / no fixed version. Not a fix ticket → risk-acceptance register with an expiry (Step 3). Never file an "upgrade X" ticket when no fixed version exists.
|
|
51
|
+
|
|
52
|
+
### 3. File the work into the configured bug reporting system
|
|
53
|
+
|
|
54
|
+
Read `bug_trackers` in `.grimoire/config.yaml`.
|
|
55
|
+
|
|
56
|
+
**If a tracker MCP is configured (Jira / Linear / GitHub):**
|
|
57
|
+
- **Idempotency first** — search the tracker for the CVE/GHSA id before creating anything. If a ticket exists, update it (link the triage, refresh urgency); don't duplicate. Mirror both directions like `grimoire-bug-triage`.
|
|
58
|
+
- **One ticket per advisory** (or per package-upgrade when several CVEs share one bump — group by the fix, not the CVE). Include: id(s), component + version, fixed version / action, urgency, reachability + exposure summary, and a link back to `.grimoire/security/vulns/<run-date>/triage.md`. Set priority from urgency (hotfix-now → highest).
|
|
59
|
+
- **hotfix-now is confidential** — mirror `grimoire-bug-triage` §7. Do **not** post exploit details, reachability specifics, or a step-by-step in a public tracker. If the tracker is public, the ticket states impact + "fix in progress, details held privately"; the detail stays in the local triage record. Notify the security owner out of band. Recommend an expedited branch (non-descriptive name) + out-of-band release.
|
|
60
|
+
- **under_investigation** → a time-boxed task ("confirm reachability of <CVE> in <path> by <date>"), assigned, with the open question from triage.
|
|
61
|
+
|
|
62
|
+
**If `bug_trackers: none`:**
|
|
63
|
+
- Write `.grimoire/security/vulns/<run-date>/remediation.md` — a checklist: one entry per actionable item with `[ ]` checkbox, id(s), action (exact upgrade or change-stub link or accept-ref), urgency, suggested owner, and the triage link. This is the deliverable the team works from until a tracker exists. Tell the user where it is.
|
|
64
|
+
|
|
65
|
+
### 4. Stub a grimoire change for non-trivial fixes
|
|
66
|
+
|
|
67
|
+
For each non-trivial fix, create `.grimoire/changes/<change-id>/manifest.md` so the normal build workflow takes over:
|
|
68
|
+
- Frontmatter `status: proposed`, plus `source: vuln-triage`, the CVE id(s), and the triage path.
|
|
69
|
+
- **Why**: the vulnerability + why a one-line bump isn't enough (major break, code path affected, transitive constraint).
|
|
70
|
+
- **Scope**: the upgrade/change needed and the blast radius from triage (which code paths touch the vulnerable surface).
|
|
71
|
+
- Point the user at `grimoire-draft` / `grimoire-plan` to continue. Reference the change-id from the ticket so the trail is intact.
|
|
72
|
+
|
|
73
|
+
### 5. Record risk-accepted items (with expiry)
|
|
74
|
+
|
|
75
|
+
**Register invariant: only a settled `accept` verdict enters the register.** The register means "we triaged this, decided, and consciously accepted the residual risk." Two states must stay out of it:
|
|
76
|
+
- **`under_investigation`** — not decided yet. It gets an investigation task (Step 3), nothing in the register. The register's `vex_justification` must be a real VEX code, not "pending"; a finding you can't yet justify hasn't been accepted. When the investigation resolves, *then* it routes — to `not_affected` (close), `affected` (ticket/change), or `accept` (register).
|
|
77
|
+
- **`not_affected`** — already dismissed by triage, deterministically, every scan. It needs no register entry; adding one would bloat the register with the unreachable os-package noise the reachability verdict already suppresses.
|
|
78
|
+
|
|
79
|
+
For every settled `accept` item, append to `.grimoire/security/accepted-risks.yml` (create from the template if absent). Each entry: `cve`, `component`, `vex_justification` (a real code), `reason` (why it's acceptable — reachability/exposure/no-fix), `owner`, `accepted` date, and an **`expires`** date (when to re-triage — sooner for higher residual risk, default ~90 days). An accepted risk is not closed — it's scheduled for re-evaluation.
|
|
80
|
+
|
|
81
|
+
**This register is read back by `grimoire-vuln-triage` during reconciliation** — an unexpired entry auto-suppresses that CVE as a known-accepted, so the same finding doesn't re-flood the queue next scan. An **expired** entry is re-surfaced for re-triage. Don't accept the same CVE twice; update the existing entry.
|
|
82
|
+
|
|
83
|
+
A no-fix os-package finding that is genuinely **`affected` and accepted** (reachable, no patched base yet) belongs here — with `component_type: os-package` and the trace summary from `container-scan-triage.md`. One that is **`not_affected`** (unreachable, like a headless API's GPU/terminal libs) does **not**.
|
|
84
|
+
|
|
85
|
+
### 6. Optionally execute trivial bumps (skippable)
|
|
86
|
+
|
|
87
|
+
Offer — don't assume — to apply trivial bumps directly: edit the manifest pin, run the lockfile update (`uv lock` / `npm install` / etc.), and run the configured `dep_audit` to confirm the advisory clears. Keep it on a branch. This step is **opt-in**; if the user just wants tickets, file and stop. If you do apply, the supply-chain rules in `security-compliance.md` still hold (committed lockfile + integrity hashes).
|
|
88
|
+
|
|
89
|
+
### 7. Report and update the record
|
|
90
|
+
|
|
91
|
+
Update the triage record (or a sibling `remediation.md`) with what was filed: ticket refs, change-ids, register entries. Report the headline:
|
|
92
|
+
- N tickets filed (M hotfix-now expedited), K risk-accepted (next review dates), J change stubs, I investigations.
|
|
93
|
+
- Any hotfix-now: restate it's flagged for the security owner and expedited.
|
|
94
|
+
- Where the artifacts are (tracker links / local docs / register).
|
|
95
|
+
|
|
96
|
+
## Important
|
|
97
|
+
- **Act only on triage verdicts.** This skill files what triage marked `affected` / `accept` / `under_investigation`. It does not re-triage, re-rank, or escalate on its own. If a verdict looks wrong, send it back to `grimoire-vuln-triage`, don't override it here.
|
|
98
|
+
- **No fixed version → no upgrade ticket.** A `will_not_fix` / no-fix finding goes to the risk register with an expiry, or to infra for a base bump. Filing "upgrade X" when X has no fix wastes a developer's time.
|
|
99
|
+
- **Group by the fix, not the CVE.** One upgrade often clears several advisories — one ticket, listing all the CVEs it resolves.
|
|
100
|
+
- **hotfix-now is confidential.** No exploit detail in public trackers; impact-only, details local, security owner notified out of band, expedited branch.
|
|
101
|
+
- **Idempotent.** Search before filing; update existing tickets and register entries instead of duplicating. Sync local ↔ tracker both ways.
|
|
102
|
+
- **`accept` carries an expiry and feeds back into triage.** The register is the loop that stops accepted noise from re-flooding every scan — and re-surfaces it when the expiry passes.
|
|
103
|
+
- **The register holds only settled `accept` verdicts.** `under_investigation` gets an investigation task, never a register entry (it isn't decided); `not_affected` is already suppressed by triage's reachability verdict each run. Keep the invariant clean: register = decided + accepted, with a real VEX justification.
|
|
104
|
+
- **Steps are skippable.** Filing, change-stubbing, and direct bumps are independent — do what the user asked for and stop.
|
|
105
|
+
|
|
106
|
+
## Done
|
|
107
|
+
When every actionable triage finding has a home — a ticket (or remediation.md entry), a change stub, or a risk-register entry with an expiry — and the triage record reflects what was filed, remediation is complete. Hotfix-now items are flagged and confidential; accepted items are scheduled for re-triage.
|