@hegemonart/get-design-done 1.55.0 → 1.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +90 -0
  4. package/README.md +6 -0
  5. package/SKILL.md +2 -0
  6. package/agents/design-fixer.md +16 -0
  7. package/dist/claude-code/.claude/skills/override/SKILL.md +86 -0
  8. package/dist/claude-code/.claude/skills/state/SKILL.md +106 -0
  9. package/hooks/gdd-decision-injector.js +58 -0
  10. package/hooks/gdd-fact-force.js +434 -0
  11. package/hooks/gdd-risk-gate.js +406 -0
  12. package/hooks/hooks.json +18 -0
  13. package/package.json +1 -1
  14. package/reference/schemas/events.schema.json +61 -1
  15. package/reference/skill-graph.md +3 -1
  16. package/scripts/lib/manifest/skills.json +16 -0
  17. package/scripts/lib/risk/calibration.cjs +385 -0
  18. package/scripts/lib/risk/compute-risk.cjs +229 -0
  19. package/scripts/lib/risk/consumers.cjs +211 -0
  20. package/scripts/lib/risk/override.cjs +87 -0
  21. package/scripts/lib/risk/route.cjs +59 -0
  22. package/scripts/lib/risk/tables.cjs +221 -0
  23. package/scripts/lib/state/migrate-to-sqlite.cjs +664 -0
  24. package/scripts/lib/state/query-surface.cjs +391 -0
  25. package/scripts/lib/state/render-markdown.cjs +717 -0
  26. package/scripts/lib/state/state-backend.cjs +345 -0
  27. package/scripts/lib/state/state-store.cjs +735 -0
  28. package/sdk/cli/index.js +193 -96
  29. package/sdk/dashboard/data/source.cjs +44 -5
  30. package/sdk/mcp/gdd-state/server.js +127 -30
  31. package/sdk/mcp/gdd-state/tools/get.ts +8 -0
  32. package/sdk/state/index.ts +267 -13
  33. package/sdk/state/lockfile.ts +48 -0
  34. package/sdk/state/schema.sql +218 -0
  35. package/skills/override/SKILL.md +86 -0
  36. package/skills/state/SKILL.md +106 -0
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: gdd-override
3
+ description: "Escalation surface for a risk-blocked action or a fact-force gate. Use when the Phase 56 risk gate blocked a writer action (suggested_action=block) and a reviewer has signed off, or when the first-write fact-force gate is holding a file you have legitimately reviewed. Activates for requests involving overriding a blocked edit, approving a high-risk change, or clearing a fact-force hold on a path."
4
+ argument-hint: "<finding-id | factforce <path>> [--approver <who>] [--reason <text>]"
5
+ user-invocable: true
6
+ tools: Read, Write, Bash, Grep, Glob
7
+ ---
8
+
9
+ # /gdd:override
10
+
11
+ A risk-blocked action is hard: the Phase 56 risk gate routes `suggested_action=block`
12
+ to `override` (see `scripts/lib/risk/route.cjs`), and the fact-force gate holds the
13
+ first write to a file until its facts are read. This skill is the audited way past
14
+ either hold. It mirrors `/gdd:unlock-decision`: a named approver plus a
15
+ reason, recorded before anything is let through. Override is never silent.
16
+
17
+ ## Invocation
18
+
19
+ | Command | Behavior |
20
+ |---|---|
21
+ | `/gdd:override <finding-id> --approver <who> --reason <text>` | Record a `D-XX` `override`-tagged decision in STATE.md `<decisions>` and let the risk-blocked action through. |
22
+ | `/gdd:override factforce <path> --approver <who> --reason <text>` | Set `checked[path]` in the session fact-force state so the fact-force gate stops holding that path. |
23
+
24
+ Both modes ask for a rationale: the audit trail is the reason override exists.
25
+
26
+ ## Steps
27
+
28
+ 1. **Parse args.** Mode is `factforce` when the first token is the literal `factforce`
29
+ (the next token is the `<path>`); otherwise the first token is a `<finding-id>`.
30
+ `--approver` is required (a non-empty name). Missing `--approver` prints the usage
31
+ and changes nothing. If `--reason` is absent, ASK for one (AskUserQuestion or a
32
+ prompt) before continuing: an override with no rationale is rejected.
33
+
34
+ 2. **Preview.** Show what will be written and stop for confirmation:
35
+ - finding mode: the decision entry from `overrideDecisionEntry(<id>, {approver, reason})`
36
+ (its `text`, `status: locked`, and `override` tag) plus the action it unblocks.
37
+ - factforce mode: the `<path>` that will gain `checked[path] = true` and the
38
+ session-state file it lands in.
39
+
40
+ 3. **Apply (finding mode).** Record the audited decision via the STATE writer
41
+ `mcp__gdd_state__add_decision` (it auto-assigns the next `D-N`). Pass the `text`
42
+ from the pure builder so the `override` tag is embedded and greppable:
43
+
44
+ ```bash
45
+ node -e '
46
+ const o = require("./scripts/lib/risk/override.cjs");
47
+ const [id, who, reason] = process.argv.slice(1);
48
+ const entry = o.overrideDecisionEntry(id, { approver: who, reason });
49
+ console.log(JSON.stringify(entry));
50
+ ' "<finding-id>" "<who>" "<reason>"
51
+ ```
52
+
53
+ Then call `mcp__gdd_state__add_decision` with `{ text: <entry.text>, status: "locked" }`.
54
+ The blocked action is now approved on the audit record; proceed with it.
55
+
56
+ 4. **Apply (factforce mode).** Set `checked[path]` in the session state file at
57
+ `<cwd>/.design/locks/factforce-<session_id>.json` (atomic tmp then rename), using
58
+ the pure helper so the shape matches what the fact-force gate reads:
59
+
60
+ ```bash
61
+ node -e '
62
+ const fs = require("fs"); const path = require("path");
63
+ const o = require("./scripts/lib/risk/override.cjs");
64
+ const [file, p] = process.argv.slice(1);
65
+ let state = {}; try { state = JSON.parse(fs.readFileSync(file, "utf8")); } catch {}
66
+ const next = o.setFactForceChecked(state, p);
67
+ fs.mkdirSync(path.dirname(file), { recursive: true });
68
+ const tmp = file + ".tmp";
69
+ fs.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n");
70
+ fs.renameSync(tmp, file);
71
+ console.log(JSON.stringify(next.checked));
72
+ ' "<cwd>/.design/locks/factforce-<session_id>.json" "<path>"
73
+ ```
74
+
75
+ The fact-force gate stops holding `<path>` for the rest of the session.
76
+
77
+ 5. **Report** the recorded approver, the reason, and either the new `D-XX` id (finding
78
+ mode) or the unblocked path (factforce mode).
79
+
80
+ ## Do Not
81
+
82
+ - Do not skip the rationale: every override is audited.
83
+ - Do not override a finding that the risk gate did not actually block.
84
+ - Do not edit `scripts/lib/risk/route.cjs` or `compute-risk.cjs`: this skill consumes them.
85
+
86
+ ## OVERRIDE COMPLETE
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: gdd-state
3
+ description: "Query, recover, or roll back the Phase 57 SQLite state backbone. Use when you need to inspect the decisions/blockers/plans tables with a raw SELECT, rebuild a corrupt state.sqlite from the markdown STATE.md, or revert to the markdown-only source of truth by removing state.sqlite. Activates for requests involving querying the SQLite state database, recovering from SQLite corruption, or reverting the migration (demigrate)."
4
+ argument-hint: "<query \"<sql>\" | recover | demigrate>"
5
+ user-invocable: true
6
+ tools: Read, Bash, Grep, Glob
7
+ ---
8
+
9
+ # /gdd:state
10
+
11
+ The Phase 57 SQLite state backbone is opt-in (`--migrate-state`) and fully reversible.
12
+ Markdown `.design/STATE.md` is always the human-editable SoT; SQLite is a faster query
13
+ layer derived from it. This skill exposes three subcommands for operating on that layer.
14
+
15
+ ## Subcommands
16
+
17
+ | Subcommand | What it does |
18
+ |---|---|
19
+ | `/gdd:state query "<sql>"` | Run a read-only SELECT against `.design/state.sqlite`. |
20
+ | `/gdd:state recover` | Rotate the current sqlite to a `.bak` and rebuild from markdown. |
21
+ | `/gdd:state demigrate` | Remove `.design/state.sqlite`; markdown becomes the SoT again. |
22
+
23
+ ---
24
+
25
+ ## query
26
+
27
+ Execute a read-only SELECT against the state database.
28
+
29
+ The engine opens the file with `readonly:true` so all writes are rejected at the
30
+ engine level. A first-token denylist (Set membership, no regex) additionally blocks
31
+ DROP, DELETE, UPDATE, INSERT, ALTER, ATTACH, CREATE, PRAGMA, VACUUM, ANALYZE,
32
+ REINDEX, and REPLACE before the connection is opened.
33
+
34
+ ```bash
35
+ node -e '
36
+ const qs = require("./scripts/lib/state/query-surface.cjs");
37
+ const result = qs.query(process.argv[1], { projectRoot: process.cwd() });
38
+ console.log(JSON.stringify(result, null, 2));
39
+ ' "<sql>"
40
+ ```
41
+
42
+ Outputs `{ rows: [...], backend: "sqlite" }` on success, or
43
+ `{ degraded: true, message: "..." }` when SQLite is not active.
44
+
45
+ Degrades gracefully (no throw) when `BACKEND==='markdown'` or when
46
+ `.design/state.sqlite` has not been created yet (run `--migrate-state` first).
47
+
48
+ ---
49
+
50
+ ## recover
51
+
52
+ Rotate the current (possibly corrupt) `.design/state.sqlite` to `.bak.0`, then
53
+ rebuild a fresh database from the markdown `.design/STATE.md` using
54
+ `migrate-to-sqlite.cjs` in force mode. Runs `PRAGMA integrity_check` on the
55
+ result and reports the outcome.
56
+
57
+ ```bash
58
+ node -e '
59
+ const qs = require("./scripts/lib/state/query-surface.cjs");
60
+ const result = qs.recover({ projectRoot: process.cwd() });
61
+ console.log(JSON.stringify(result, null, 2));
62
+ '
63
+ ```
64
+
65
+ Outputs `{ recovered: true, integrity: true, message: "..." }` on success.
66
+
67
+ Backup rotation keeps at most 10 files (`.bak.0` through `.bak.9`). The oldest
68
+ backup is overwritten when the cap is reached.
69
+
70
+ ---
71
+
72
+ ## demigrate
73
+
74
+ Remove `.design/state.sqlite` so the markdown `STATE.md` becomes the SoT again.
75
+ Idempotent: if the file does not exist, returns a clear no-op message without error.
76
+ A backup is taken in `.bak.0` before removal.
77
+
78
+ ```bash
79
+ node -e '
80
+ const qs = require("./scripts/lib/state/query-surface.cjs");
81
+ const result = qs.demigrate({ projectRoot: process.cwd() });
82
+ console.log(JSON.stringify(result, null, 2));
83
+ '
84
+ ```
85
+
86
+ Outputs `{ demigrated: true, message: "..." }` when the file was removed, or
87
+ `{ demigrated: false, message: "..." }` when it was already absent (no-op).
88
+
89
+ To re-enable SQLite after a demigrate, run `--migrate-state` again.
90
+
91
+ ---
92
+
93
+ ## Key design decisions
94
+
95
+ - **Markdown is always the SoT.** SQLite is opt-in via `--migrate-state` and
96
+ reversible via `demigrate`. The markdown file is never silently overwritten.
97
+ - **Read-only queries only.** The `query` subcommand enforces SELECT-only via both
98
+ the engine (`readonly:true`) and a defense-in-depth denylist. No writes
99
+ are possible through this skill.
100
+ - **Backup rotation cap.** `rotateBak` shifts `.bak.0..8` up by one index and caps
101
+ at `.bak.9` (10 files total). The oldest backup is overwritten automatically.
102
+ - **Graceful degradation.** All subcommands return a clear `{ degraded, message }`
103
+ object (no throw) when `better-sqlite3` is not installed or when
104
+ `GDD_STATE_BACKEND=markdown` is set.
105
+
106
+ ## STATE COMPLETE