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.
- package/README.md +131 -67
- package/agents/DISTILLATION.md +15 -13
- package/agents/README.md +1 -1
- package/agents/planner.md +2 -0
- package/bin/adapters/agents.mjs +1 -0
- package/bin/adapters/claude.mjs +20 -4
- package/bin/adapters/codex.mjs +9 -1
- package/bin/adapters/opencode.mjs +20 -5
- package/bin/gsdd.mjs +24 -7
- package/bin/lib/cli-utils.mjs +1 -1
- package/bin/lib/evidence-contract.mjs +112 -0
- package/bin/lib/file-ops.mjs +161 -0
- package/bin/lib/health-truth.mjs +186 -0
- package/bin/lib/health.mjs +72 -67
- package/bin/lib/init-flow.mjs +50 -3
- package/bin/lib/init-prompts.mjs +22 -83
- package/bin/lib/init-runtime.mjs +47 -25
- package/bin/lib/init.mjs +3 -3
- package/bin/lib/lifecycle-preflight.mjs +333 -0
- package/bin/lib/lifecycle-state.mjs +293 -0
- package/bin/lib/models.mjs +19 -4
- package/bin/lib/phase.mjs +159 -18
- package/bin/lib/plan-constants.mjs +30 -0
- package/bin/lib/provenance.mjs +165 -0
- package/bin/lib/rendering.mjs +8 -0
- package/bin/lib/runtime-freshness.mjs +239 -0
- package/bin/lib/session-fingerprint.mjs +106 -0
- package/bin/lib/templates.mjs +17 -0
- package/distilled/DESIGN.md +733 -49
- package/distilled/EVIDENCE-INDEX.md +402 -0
- package/distilled/README.md +73 -33
- package/distilled/SKILL.md +89 -85
- package/distilled/templates/agents.block.md +13 -84
- package/distilled/templates/agents.md +0 -7
- package/distilled/templates/delegates/plan-checker.md +6 -3
- package/distilled/workflows/audit-milestone.md +56 -6
- package/distilled/workflows/complete-milestone.md +333 -0
- package/distilled/workflows/execute.md +201 -19
- package/distilled/workflows/map-codebase.md +17 -4
- package/distilled/workflows/new-milestone.md +262 -0
- package/distilled/workflows/new-project.md +7 -6
- package/distilled/workflows/pause.md +40 -6
- package/distilled/workflows/plan-milestone-gaps.md +183 -0
- package/distilled/workflows/plan.md +77 -11
- package/distilled/workflows/progress.md +107 -29
- package/distilled/workflows/quick.md +23 -12
- package/distilled/workflows/resume.md +135 -12
- package/distilled/workflows/verify-work.md +260 -0
- package/distilled/workflows/verify.md +159 -33
- package/docs/BROWNFIELD-PROOF.md +95 -0
- package/docs/RUNTIME-SUPPORT.md +77 -0
- package/docs/USER-GUIDE.md +439 -0
- package/docs/VERIFICATION-DISCIPLINE.md +59 -0
- package/docs/claude/context-monitor.md +98 -0
- package/docs/proof/consumer-node-cli/README.md +37 -0
- package/docs/proof/consumer-node-cli/ROADMAP.md +14 -0
- package/docs/proof/consumer-node-cli/SPEC.md +17 -0
- package/docs/proof/consumer-node-cli/brief.md +9 -0
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-01-PLAN.md +34 -0
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-01-SUMMARY.md +10 -0
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-VERIFICATION.md +30 -0
- 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
|
+
}
|
package/bin/lib/templates.mjs
CHANGED
|
@@ -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
|
}
|