gsdd-cli 0.3.1 → 0.18.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 (62) hide show
  1. package/README.md +131 -67
  2. package/agents/DISTILLATION.md +15 -13
  3. package/agents/README.md +1 -1
  4. package/agents/planner.md +2 -0
  5. package/bin/adapters/agents.mjs +1 -0
  6. package/bin/adapters/claude.mjs +20 -4
  7. package/bin/adapters/codex.mjs +9 -1
  8. package/bin/adapters/opencode.mjs +20 -5
  9. package/bin/gsdd.mjs +24 -7
  10. package/bin/lib/cli-utils.mjs +1 -1
  11. package/bin/lib/evidence-contract.mjs +112 -0
  12. package/bin/lib/file-ops.mjs +161 -0
  13. package/bin/lib/health-truth.mjs +186 -0
  14. package/bin/lib/health.mjs +72 -67
  15. package/bin/lib/init-flow.mjs +50 -3
  16. package/bin/lib/init-prompts.mjs +22 -83
  17. package/bin/lib/init-runtime.mjs +47 -25
  18. package/bin/lib/init.mjs +3 -3
  19. package/bin/lib/lifecycle-preflight.mjs +333 -0
  20. package/bin/lib/lifecycle-state.mjs +293 -0
  21. package/bin/lib/models.mjs +19 -4
  22. package/bin/lib/phase.mjs +159 -18
  23. package/bin/lib/plan-constants.mjs +30 -0
  24. package/bin/lib/provenance.mjs +165 -0
  25. package/bin/lib/rendering.mjs +8 -0
  26. package/bin/lib/runtime-freshness.mjs +239 -0
  27. package/bin/lib/session-fingerprint.mjs +106 -0
  28. package/bin/lib/templates.mjs +17 -0
  29. package/distilled/DESIGN.md +733 -49
  30. package/distilled/EVIDENCE-INDEX.md +402 -0
  31. package/distilled/README.md +73 -33
  32. package/distilled/SKILL.md +89 -85
  33. package/distilled/templates/agents.block.md +13 -84
  34. package/distilled/templates/agents.md +0 -7
  35. package/distilled/templates/delegates/plan-checker.md +6 -3
  36. package/distilled/workflows/audit-milestone.md +56 -6
  37. package/distilled/workflows/complete-milestone.md +333 -0
  38. package/distilled/workflows/execute.md +201 -19
  39. package/distilled/workflows/map-codebase.md +17 -4
  40. package/distilled/workflows/new-milestone.md +262 -0
  41. package/distilled/workflows/new-project.md +7 -6
  42. package/distilled/workflows/pause.md +40 -6
  43. package/distilled/workflows/plan-milestone-gaps.md +183 -0
  44. package/distilled/workflows/plan.md +77 -11
  45. package/distilled/workflows/progress.md +107 -29
  46. package/distilled/workflows/quick.md +23 -12
  47. package/distilled/workflows/resume.md +135 -12
  48. package/distilled/workflows/verify-work.md +260 -0
  49. package/distilled/workflows/verify.md +159 -33
  50. package/docs/BROWNFIELD-PROOF.md +95 -0
  51. package/docs/RUNTIME-SUPPORT.md +77 -0
  52. package/docs/USER-GUIDE.md +439 -0
  53. package/docs/VERIFICATION-DISCIPLINE.md +59 -0
  54. package/docs/claude/context-monitor.md +98 -0
  55. package/docs/proof/consumer-node-cli/README.md +37 -0
  56. package/docs/proof/consumer-node-cli/ROADMAP.md +14 -0
  57. package/docs/proof/consumer-node-cli/SPEC.md +17 -0
  58. package/docs/proof/consumer-node-cli/brief.md +9 -0
  59. package/docs/proof/consumer-node-cli/phases/01-foundation/01-01-PLAN.md +34 -0
  60. package/docs/proof/consumer-node-cli/phases/01-foundation/01-01-SUMMARY.md +10 -0
  61. package/docs/proof/consumer-node-cli/phases/01-foundation/01-VERIFICATION.md +30 -0
  62. package/package.json +38 -29
@@ -0,0 +1,106 @@
1
+ // session-fingerprint.mjs — Planning state drift detection
2
+ //
3
+ // Computes a SHA-256 fingerprint from the combined contents of ROADMAP.md,
4
+ // SPEC.md, and config.json. When the fingerprint stored in
5
+ // .planning/.state-fingerprint.json no longer matches the live files, the
6
+ // preflight and health systems can warn that planning state drifted since
7
+ // the last recorded session.
8
+ //
9
+ // The fingerprint file is session-local and gitignored by convention.
10
+
11
+ import { createHash } from 'crypto';
12
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
13
+ import { join } from 'path';
14
+
15
+ const FINGERPRINT_FILE = '.state-fingerprint.json';
16
+ const FINGERPRINT_SOURCES = ['ROADMAP.md', 'SPEC.md', 'config.json'];
17
+
18
+ /**
19
+ * Compute a SHA-256 fingerprint from the planning truth files.
20
+ * Missing files contribute an empty string (so a newly created file
21
+ * registers as drift).
22
+ */
23
+ export function computeFingerprint(planningDir) {
24
+ const hash = createHash('sha256');
25
+ const sources = {};
26
+ for (const file of FINGERPRINT_SOURCES) {
27
+ const filePath = join(planningDir, file);
28
+ const content = existsSync(filePath) ? readFileSync(filePath, 'utf-8') : '';
29
+ hash.update(`${file}:${content}\n`);
30
+ sources[file] = existsSync(filePath);
31
+ }
32
+ return { hash: hash.digest('hex'), sources };
33
+ }
34
+
35
+ /**
36
+ * Read the stored fingerprint from .planning/.state-fingerprint.json.
37
+ * Returns null if the file does not exist or is unparseable.
38
+ */
39
+ export function readStoredFingerprint(planningDir) {
40
+ const filePath = join(planningDir, FINGERPRINT_FILE);
41
+ if (!existsSync(filePath)) return null;
42
+ try {
43
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Write the current fingerprint to .planning/.state-fingerprint.json.
51
+ */
52
+ export function writeFingerprint(planningDir) {
53
+ const { hash, sources } = computeFingerprint(planningDir);
54
+ const data = {
55
+ hash,
56
+ sources,
57
+ timestamp: new Date().toISOString(),
58
+ };
59
+ writeFileSync(join(planningDir, FINGERPRINT_FILE), JSON.stringify(data, null, 2) + '\n');
60
+ return data;
61
+ }
62
+
63
+ /**
64
+ * Check whether the current planning state has drifted from the stored
65
+ * fingerprint. Returns { drifted, details, stored, current }.
66
+ *
67
+ * If no stored fingerprint exists, returns drifted: false with a note
68
+ * that no baseline was found (first session after adoption).
69
+ */
70
+ export function checkDrift(planningDir) {
71
+ const stored = readStoredFingerprint(planningDir);
72
+ const { hash: currentHash, sources: currentSources } = computeFingerprint(planningDir);
73
+
74
+ if (!stored) {
75
+ return {
76
+ drifted: false,
77
+ noBaseline: true,
78
+ details: ['No stored fingerprint found — first session or fingerprint was cleared.'],
79
+ stored: null,
80
+ current: { hash: currentHash, sources: currentSources },
81
+ };
82
+ }
83
+
84
+ const drifted = stored.hash !== currentHash;
85
+ const details = [];
86
+ if (drifted) {
87
+ for (const file of FINGERPRINT_SOURCES) {
88
+ const was = stored.sources?.[file] ?? false;
89
+ const now = currentSources[file];
90
+ if (was && !now) details.push(`${file} was removed`);
91
+ else if (!was && now) details.push(`${file} was created`);
92
+ else if (was && now) details.push(`${file} may have changed`);
93
+ }
94
+ if (details.length === 0) {
95
+ details.push('Planning state hash changed since last recorded session.');
96
+ }
97
+ }
98
+
99
+ return {
100
+ drifted,
101
+ noBaseline: false,
102
+ details,
103
+ stored: { hash: stored.hash, timestamp: stored.timestamp },
104
+ current: { hash: currentHash, sources: currentSources },
105
+ };
106
+ }
@@ -12,6 +12,23 @@ export function installProjectTemplates({ planningDir, distilledDir, agentsDir }
12
12
  if (existsSync(globalTemplatesDir)) {
13
13
  cpSync(globalTemplatesDir, localTemplatesDir, { recursive: true });
14
14
  console.log(' - copied templates to .planning/templates/');
15
+ // Warn-only by design: init should not fail on missing templates because
16
+ // the user may still proceed and fix later. The hard gate lives in
17
+ // `gsdd health` (E6/E7/E8) which reports these as errors. This is the
18
+ // first layer of the 3-layer scaffold defense (warn at init, error at
19
+ // health, regression tests in manifest suite).
20
+ const expectedSubdirs = ['delegates', 'research', 'codebase'];
21
+ for (const subdir of expectedSubdirs) {
22
+ if (!existsSync(join(localTemplatesDir, subdir))) {
23
+ console.log(` - WARN: missing expected template subdir: ${subdir}/`);
24
+ }
25
+ }
26
+ const expectedRootFiles = ['spec.md', 'roadmap.md', 'auth-matrix.md'];
27
+ for (const file of expectedRootFiles) {
28
+ if (!existsSync(join(localTemplatesDir, file))) {
29
+ console.log(` - WARN: missing expected root template file: ${file}`);
30
+ }
31
+ }
15
32
  } else {
16
33
  console.log(' - WARN: missing distilled/templates/; cannot copy templates');
17
34
  }