gsdd-cli 0.18.4 → 0.19.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/LICENSE +21 -21
- package/README.md +625 -607
- package/agents/DISTILLATION.md +421 -421
- package/agents/README.md +62 -62
- package/agents/approach-explorer.md +361 -361
- package/agents/debugger.md +82 -82
- package/agents/executor.md +394 -394
- package/agents/integration-checker.md +318 -318
- package/agents/mapper.md +103 -103
- package/agents/planner.md +313 -313
- package/agents/researcher.md +84 -84
- package/agents/roadmapper.md +296 -296
- package/agents/synthesizer.md +236 -236
- package/agents/verifier.md +337 -337
- package/bin/adapters/agents.mjs +34 -34
- package/bin/adapters/claude.mjs +191 -191
- package/bin/adapters/codex.mjs +85 -85
- package/bin/adapters/index.mjs +20 -20
- package/bin/adapters/opencode.mjs +278 -278
- package/bin/gsdd.mjs +123 -116
- package/bin/lib/cli-utils.mjs +28 -28
- package/bin/lib/evidence-contract.mjs +112 -112
- package/bin/lib/file-ops.mjs +209 -161
- package/bin/lib/health-truth.mjs +181 -178
- package/bin/lib/health.mjs +265 -235
- package/bin/lib/init-flow.mjs +252 -236
- package/bin/lib/init-prompts.mjs +248 -247
- package/bin/lib/init-runtime.mjs +225 -212
- package/bin/lib/init.mjs +17 -17
- package/bin/lib/lifecycle-preflight.mjs +360 -333
- package/bin/lib/lifecycle-state.mjs +351 -267
- package/bin/lib/manifest.mjs +116 -114
- package/bin/lib/models.mjs +411 -411
- package/bin/lib/phase.mjs +397 -378
- package/bin/lib/plan-constants.mjs +30 -30
- package/bin/lib/provenance.mjs +109 -106
- package/bin/lib/rendering.mjs +178 -130
- package/bin/lib/runtime-freshness.mjs +221 -219
- package/bin/lib/templates.mjs +225 -224
- package/bin/lib/workspace-root.mjs +132 -0
- package/distilled/DESIGN.md +2347 -2327
- package/distilled/EVIDENCE-INDEX.md +397 -394
- package/distilled/README.md +196 -193
- package/distilled/SKILL.md +86 -85
- package/distilled/templates/agents.block.md +21 -21
- package/distilled/templates/agents.md +6 -6
- package/distilled/templates/approach.md +232 -232
- package/distilled/templates/auth-matrix.md +78 -78
- package/distilled/templates/brownfield-change/CHANGE.md +99 -0
- package/distilled/templates/brownfield-change/HANDOFF.md +38 -0
- package/distilled/templates/brownfield-change/VERIFICATION.md +56 -0
- package/distilled/templates/codebase/architecture.md +110 -110
- package/distilled/templates/codebase/concerns.md +95 -95
- package/distilled/templates/codebase/conventions.md +193 -193
- package/distilled/templates/codebase/stack.md +96 -96
- package/distilled/templates/delegates/approach-explorer.md +25 -25
- package/distilled/templates/delegates/mapper-arch.md +26 -26
- package/distilled/templates/delegates/mapper-concerns.md +27 -27
- package/distilled/templates/delegates/mapper-quality.md +28 -28
- package/distilled/templates/delegates/mapper-tech.md +25 -25
- package/distilled/templates/delegates/plan-checker.md +68 -68
- package/distilled/templates/delegates/researcher-architecture.md +30 -30
- package/distilled/templates/delegates/researcher-features.md +30 -30
- package/distilled/templates/delegates/researcher-pitfalls.md +30 -30
- package/distilled/templates/delegates/researcher-stack.md +30 -30
- package/distilled/templates/delegates/researcher-synthesizer.md +31 -31
- package/distilled/templates/research/architecture.md +57 -57
- package/distilled/templates/research/features.md +23 -23
- package/distilled/templates/research/pitfalls.md +46 -46
- package/distilled/templates/research/stack.md +45 -45
- package/distilled/templates/research/summary.md +67 -67
- package/distilled/templates/roadmap.md +74 -62
- package/distilled/templates/spec.md +110 -110
- package/distilled/workflows/audit-milestone.md +275 -271
- package/distilled/workflows/complete-milestone.md +336 -332
- package/distilled/workflows/execute.md +454 -449
- package/distilled/workflows/map-codebase.md +253 -253
- package/distilled/workflows/new-milestone.md +242 -238
- package/distilled/workflows/new-project.md +398 -398
- package/distilled/workflows/pause.md +160 -156
- package/distilled/workflows/plan-milestone-gaps.md +183 -183
- package/distilled/workflows/plan.md +451 -447
- package/distilled/workflows/progress.md +227 -223
- package/distilled/workflows/quick.md +351 -347
- package/distilled/workflows/resume.md +220 -212
- package/distilled/workflows/verify-work.md +260 -260
- package/distilled/workflows/verify.md +431 -429
- package/docs/BROWNFIELD-PROOF.md +95 -95
- package/docs/RUNTIME-SUPPORT.md +93 -75
- package/docs/USER-GUIDE.md +440 -399
- package/docs/VERIFICATION-DISCIPLINE.md +59 -59
- package/docs/claude/context-monitor.md +98 -98
- package/docs/proof/consumer-node-cli/README.md +37 -37
- package/docs/proof/consumer-node-cli/ROADMAP.md +14 -14
- package/docs/proof/consumer-node-cli/SPEC.md +17 -17
- package/docs/proof/consumer-node-cli/brief.md +9 -9
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-01-PLAN.md +34 -34
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-01-SUMMARY.md +10 -10
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-VERIFICATION.md +30 -30
- package/package.json +62 -61
package/bin/gsdd.mjs
CHANGED
|
@@ -1,66 +1,64 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// gsdd - Workspine CLI
|
|
4
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
5
3
|
import { realpathSync, readFileSync } from 'fs';
|
|
6
|
-
import { join, dirname } from 'path';
|
|
7
|
-
import { fileURLToPath } from 'url';
|
|
8
|
-
import { createAdapterRegistry } from './adapters/index.mjs';
|
|
9
|
-
import {
|
|
10
|
-
renderAgentsBoundedBlock,
|
|
11
|
-
renderAgentsFileContent,
|
|
12
|
-
renderOpenCodeCommandContent,
|
|
13
|
-
renderSkillContent,
|
|
14
|
-
upsertBoundedBlock,
|
|
15
|
-
getDelegateContent,
|
|
16
|
-
} from './lib/rendering.mjs';
|
|
17
|
-
import { loadProjectModelConfig, getRuntimeModelOverride, resolveRuntimeAgentModel, cmdModels } from './lib/models.mjs';
|
|
18
|
-
import { createCmdInit, createCmdUpdate, cmdHelp } from './lib/init.mjs';
|
|
19
|
-
import { cmdFindPhase, cmdVerify, cmdScaffold, cmdPhaseStatus } from './lib/phase.mjs';
|
|
20
|
-
import { cmdFileOp } from './lib/file-ops.mjs';
|
|
21
|
-
import { createCmdHealth } from './lib/health.mjs';
|
|
22
|
-
import { cmdLifecyclePreflight } from './lib/lifecycle-preflight.mjs';
|
|
23
|
-
|
|
4
|
+
import { join, dirname } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { createAdapterRegistry } from './adapters/index.mjs';
|
|
7
|
+
import {
|
|
8
|
+
renderAgentsBoundedBlock,
|
|
9
|
+
renderAgentsFileContent,
|
|
10
|
+
renderOpenCodeCommandContent,
|
|
11
|
+
renderSkillContent,
|
|
12
|
+
upsertBoundedBlock,
|
|
13
|
+
getDelegateContent,
|
|
14
|
+
} from './lib/rendering.mjs';
|
|
15
|
+
import { loadProjectModelConfig, getRuntimeModelOverride, resolveRuntimeAgentModel, cmdModels } from './lib/models.mjs';
|
|
16
|
+
import { createCmdInit, createCmdUpdate, cmdHelp } from './lib/init.mjs';
|
|
17
|
+
import { cmdFindPhase, cmdVerify, cmdScaffold, cmdPhaseStatus } from './lib/phase.mjs';
|
|
18
|
+
import { cmdFileOp } from './lib/file-ops.mjs';
|
|
19
|
+
import { createCmdHealth } from './lib/health.mjs';
|
|
20
|
+
import { cmdLifecyclePreflight } from './lib/lifecycle-preflight.mjs';
|
|
21
|
+
import { resolveWorkspaceContext } from './lib/workspace-root.mjs';
|
|
22
|
+
|
|
24
23
|
const __filename = fileURLToPath(import.meta.url);
|
|
25
24
|
const __dirname = dirname(__filename);
|
|
26
25
|
const DISTILLED_DIR = join(__dirname, '..', 'distilled');
|
|
27
26
|
const AGENTS_DIR = join(__dirname, '..', 'agents');
|
|
28
27
|
const PACKAGE_JSON = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
mutatesArtifacts,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
defineWorkflow({ name: 'gsdd-
|
|
47
|
-
defineWorkflow({ name: 'gsdd-
|
|
48
|
-
defineWorkflow({ name: 'gsdd-
|
|
49
|
-
defineWorkflow({ name: 'gsdd-
|
|
50
|
-
defineWorkflow({ name: 'gsdd-verify', workflow: 'verify.md', description: '
|
|
51
|
-
defineWorkflow({ name: 'gsdd-
|
|
52
|
-
defineWorkflow({ name: 'gsdd-
|
|
53
|
-
defineWorkflow({ name: 'gsdd-
|
|
54
|
-
defineWorkflow({ name: 'gsdd-
|
|
55
|
-
defineWorkflow({ name: 'gsdd-
|
|
56
|
-
defineWorkflow({ name: 'gsdd-
|
|
57
|
-
defineWorkflow({ name: 'gsdd-
|
|
58
|
-
defineWorkflow({ name: 'gsdd-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
28
|
+
const IS_MAIN = process.argv[1]
|
|
29
|
+
? realpathSync(process.argv[1]) === realpathSync(__filename)
|
|
30
|
+
: false;
|
|
31
|
+
|
|
32
|
+
const [,, command, ...args] = process.argv;
|
|
33
|
+
|
|
34
|
+
function defineWorkflow({ mutatesArtifacts = true, ...workflow }) {
|
|
35
|
+
return {
|
|
36
|
+
...workflow,
|
|
37
|
+
mutatesArtifacts,
|
|
38
|
+
agent: mutatesArtifacts ? 'Code' : 'Plan',
|
|
39
|
+
opencodeType: mutatesArtifacts ? 'edit' : 'plan',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const WORKFLOWS = [
|
|
44
|
+
defineWorkflow({ name: 'gsdd-new-project', workflow: 'new-project.md', description: 'New project - questioning, codebase audit, research, spec, roadmap' }),
|
|
45
|
+
defineWorkflow({ name: 'gsdd-map-codebase', workflow: 'map-codebase.md', description: 'Map or refresh codebase - 4 parallel mappers, staleness check, secrets scan' }),
|
|
46
|
+
defineWorkflow({ name: 'gsdd-plan', workflow: 'plan.md', description: 'Plan a phase - research check, backward planning, task creation' }),
|
|
47
|
+
defineWorkflow({ name: 'gsdd-execute', workflow: 'execute.md', description: 'Execute a phase plan - implement tasks, verify changes, follow repo git conventions' }),
|
|
48
|
+
defineWorkflow({ name: 'gsdd-verify', workflow: 'verify.md', description: 'Verify a completed phase - 3-level checks, anti-pattern scan' }),
|
|
49
|
+
defineWorkflow({ name: 'gsdd-verify-work', workflow: 'verify-work.md', description: 'Conversational UAT testing - validate user-facing behavior with structured gap tracking' }),
|
|
50
|
+
defineWorkflow({ name: 'gsdd-audit-milestone', workflow: 'audit-milestone.md', description: 'Audit a completed milestone - cross-phase integration, requirements coverage, E2E flows' }),
|
|
51
|
+
defineWorkflow({ name: 'gsdd-complete-milestone', workflow: 'complete-milestone.md', description: 'Complete milestone - archive, evolve spec, collapse roadmap' }),
|
|
52
|
+
defineWorkflow({ name: 'gsdd-new-milestone', workflow: 'new-milestone.md', description: 'New milestone - gather goals, define requirements, create roadmap phases' }),
|
|
53
|
+
defineWorkflow({ name: 'gsdd-plan-milestone-gaps', workflow: 'plan-milestone-gaps.md', description: 'Plan gap closure phases from audit results' }),
|
|
54
|
+
defineWorkflow({ name: 'gsdd-quick', workflow: 'quick.md', description: 'Quick task - plan and execute a sub-hour task outside the phase cycle' }),
|
|
55
|
+
defineWorkflow({ name: 'gsdd-pause', workflow: 'pause.md', description: 'Pause work - save session context for seamless resumption' }),
|
|
56
|
+
defineWorkflow({ name: 'gsdd-resume', workflow: 'resume.md', description: 'Resume work - restore context and route to next action' }),
|
|
57
|
+
defineWorkflow({ name: 'gsdd-progress', workflow: 'progress.md', description: 'Check progress - show project status and route to next action', mutatesArtifacts: false }),
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const FRAMEWORK_VERSION = 'v1.4';
|
|
61
|
+
|
|
64
62
|
function createCliContext(cwd = process.cwd()) {
|
|
65
63
|
return {
|
|
66
64
|
cwd,
|
|
@@ -71,62 +69,71 @@ function createCliContext(cwd = process.cwd()) {
|
|
|
71
69
|
packageVersion: PACKAGE_JSON.version,
|
|
72
70
|
workflows: WORKFLOWS,
|
|
73
71
|
frameworkVersion: FRAMEWORK_VERSION,
|
|
74
|
-
adapters: createAdapterRegistry({
|
|
75
|
-
cwd,
|
|
76
|
-
workflows: WORKFLOWS,
|
|
77
|
-
renderAgentsBoundedBlock,
|
|
78
|
-
renderAgentsFileContent,
|
|
79
|
-
renderOpenCodeCommandContent,
|
|
80
|
-
renderSkillContent,
|
|
81
|
-
upsertBoundedBlock,
|
|
82
|
-
getDelegateContent,
|
|
83
|
-
loadProjectModelConfig,
|
|
84
|
-
getRuntimeModelOverride,
|
|
85
|
-
resolveRuntimeAgentModel,
|
|
86
|
-
}),
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const INIT_CONTEXT = createCliContext(
|
|
91
|
-
|
|
92
|
-
const cmdInit = createCmdInit(INIT_CONTEXT);
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
72
|
+
adapters: createAdapterRegistry({
|
|
73
|
+
cwd,
|
|
74
|
+
workflows: WORKFLOWS,
|
|
75
|
+
renderAgentsBoundedBlock,
|
|
76
|
+
renderAgentsFileContent,
|
|
77
|
+
renderOpenCodeCommandContent,
|
|
78
|
+
renderSkillContent,
|
|
79
|
+
upsertBoundedBlock,
|
|
80
|
+
getDelegateContent,
|
|
81
|
+
loadProjectModelConfig,
|
|
82
|
+
getRuntimeModelOverride,
|
|
83
|
+
resolveRuntimeAgentModel,
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const INIT_CONTEXT = createCliContext(process.cwd());
|
|
89
|
+
|
|
90
|
+
const cmdInit = createCmdInit(INIT_CONTEXT);
|
|
91
|
+
const cmdHealth = createCmdHealth(INIT_CONTEXT);
|
|
92
|
+
|
|
93
|
+
const cmdUpdate = (...updateArgs) => {
|
|
94
|
+
const { args: normalizedArgs, workspaceRoot, invalid, error } = resolveWorkspaceContext(updateArgs, { cwd: INIT_CONTEXT.cwd });
|
|
95
|
+
if (invalid) {
|
|
96
|
+
console.error(error);
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
return createCmdUpdate(createCliContext(workspaceRoot))(...normalizedArgs);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const COMMANDS = {
|
|
104
|
+
init: cmdInit,
|
|
105
|
+
update: cmdUpdate,
|
|
106
|
+
models: cmdModels,
|
|
107
|
+
health: cmdHealth,
|
|
108
|
+
'file-op': cmdFileOp,
|
|
109
|
+
'lifecycle-preflight': cmdLifecyclePreflight,
|
|
110
|
+
'find-phase': cmdFindPhase,
|
|
111
|
+
'phase-status': cmdPhaseStatus,
|
|
112
|
+
verify: cmdVerify,
|
|
113
|
+
scaffold: cmdScaffold,
|
|
114
|
+
help: cmdHelp,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
async function runCli(cliCommand = command, ...cliArgs) {
|
|
118
|
+
const normalizedArgs = cliArgs.length === 0
|
|
119
|
+
? args
|
|
120
|
+
: cliArgs.length === 1 && Array.isArray(cliArgs[0])
|
|
121
|
+
? cliArgs[0]
|
|
122
|
+
: cliArgs;
|
|
123
|
+
|
|
124
|
+
process.exitCode = 0;
|
|
125
|
+
|
|
126
|
+
if (!cliCommand || !COMMANDS[cliCommand]) {
|
|
127
|
+
cmdHelp();
|
|
128
|
+
if (cliCommand) process.exitCode = 1;
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
await COMMANDS[cliCommand](...normalizedArgs);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (IS_MAIN) {
|
|
136
|
+
await runCli();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export { cmdHelp, cmdInit, cmdUpdate, cmdModels, cmdHealth, cmdFileOp, cmdLifecyclePreflight, cmdFindPhase, cmdPhaseStatus, cmdVerify, cmdScaffold, runCli, FRAMEWORK_VERSION, createCliContext };
|
package/bin/lib/cli-utils.mjs
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
// cli-utils.mjs — Pure CLI utility functions (no external deps)
|
|
2
|
-
|
|
3
|
-
export function parseFlagValue(flagArgs, flagName) {
|
|
4
|
-
const idx = flagArgs.indexOf(flagName);
|
|
5
|
-
if (idx === -1) return { present: false, value: null, invalid: false };
|
|
6
|
-
|
|
7
|
-
const value = flagArgs[idx + 1];
|
|
8
|
-
if (!value || value.startsWith('--')) {
|
|
9
|
-
return { present: true, value: null, invalid: true };
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
return { present: true, value, invalid: false };
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function parseToolsFlag(flagArgs) {
|
|
16
|
-
const { value } = parseFlagValue(flagArgs, '--tools');
|
|
17
|
-
if (!value) return [];
|
|
18
|
-
if (value === 'all') return ['claude', 'opencode', 'codex', 'agents', 'cursor', 'copilot', 'gemini'];
|
|
19
|
-
return value.split(',').map((v) => v.trim()).filter(Boolean);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function parseAutoFlag(flagArgs) {
|
|
23
|
-
return flagArgs.includes('--auto');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function output(data) {
|
|
27
|
-
console.log(JSON.stringify(data, null, 2));
|
|
28
|
-
}
|
|
1
|
+
// cli-utils.mjs — Pure CLI utility functions (no external deps)
|
|
2
|
+
|
|
3
|
+
export function parseFlagValue(flagArgs, flagName) {
|
|
4
|
+
const idx = flagArgs.indexOf(flagName);
|
|
5
|
+
if (idx === -1) return { present: false, value: null, invalid: false };
|
|
6
|
+
|
|
7
|
+
const value = flagArgs[idx + 1];
|
|
8
|
+
if (!value || value.startsWith('--')) {
|
|
9
|
+
return { present: true, value: null, invalid: true };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return { present: true, value, invalid: false };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function parseToolsFlag(flagArgs) {
|
|
16
|
+
const { value } = parseFlagValue(flagArgs, '--tools');
|
|
17
|
+
if (!value) return [];
|
|
18
|
+
if (value === 'all') return ['claude', 'opencode', 'codex', 'agents', 'cursor', 'copilot', 'gemini'];
|
|
19
|
+
return value.split(',').map((v) => v.trim()).filter(Boolean);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function parseAutoFlag(flagArgs) {
|
|
23
|
+
return flagArgs.includes('--auto');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function output(data) {
|
|
27
|
+
console.log(JSON.stringify(data, null, 2));
|
|
28
|
+
}
|
|
@@ -1,112 +1,112 @@
|
|
|
1
|
-
const EVIDENCE_KINDS = Object.freeze(['code', 'test', 'runtime', 'delivery', 'human']);
|
|
2
|
-
const DELIVERY_POSTURES = Object.freeze(['repo_only', 'delivery_sensitive']);
|
|
3
|
-
const CLOSURE_SURFACES = Object.freeze(['verify', 'audit-milestone', 'complete-milestone']);
|
|
4
|
-
|
|
5
|
-
const LEGACY_EVIDENCE_ALIASES = Object.freeze({
|
|
6
|
-
code: 'code',
|
|
7
|
-
test: 'test',
|
|
8
|
-
runtime: 'runtime',
|
|
9
|
-
delivery: 'delivery',
|
|
10
|
-
human: 'human',
|
|
11
|
-
'code-evidence': 'code',
|
|
12
|
-
'repo-test': 'test',
|
|
13
|
-
'runtime-check': 'runtime',
|
|
14
|
-
'user-confirmation': 'human',
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const EVIDENCE_MATRIX = Object.freeze({
|
|
18
|
-
verify: Object.freeze({
|
|
19
|
-
repo_only: Object.freeze({
|
|
20
|
-
requiredKinds: Object.freeze(['code']),
|
|
21
|
-
recommendedKinds: Object.freeze(['test']),
|
|
22
|
-
blockedSoloKinds: Object.freeze(['human', 'delivery']),
|
|
23
|
-
}),
|
|
24
|
-
delivery_sensitive: Object.freeze({
|
|
25
|
-
requiredKinds: Object.freeze(['code', 'runtime']),
|
|
26
|
-
recommendedKinds: Object.freeze(['test', 'delivery', 'human']),
|
|
27
|
-
blockedSoloKinds: Object.freeze(['code', 'human']),
|
|
28
|
-
}),
|
|
29
|
-
}),
|
|
30
|
-
'audit-milestone': Object.freeze({
|
|
31
|
-
repo_only: Object.freeze({
|
|
32
|
-
requiredKinds: Object.freeze(['code', 'test']),
|
|
33
|
-
recommendedKinds: Object.freeze(['runtime', 'human']),
|
|
34
|
-
blockedSoloKinds: Object.freeze(['human', 'delivery']),
|
|
35
|
-
}),
|
|
36
|
-
delivery_sensitive: Object.freeze({
|
|
37
|
-
requiredKinds: Object.freeze(['code', 'test', 'runtime', 'delivery']),
|
|
38
|
-
recommendedKinds: Object.freeze(['human']),
|
|
39
|
-
blockedSoloKinds: Object.freeze(['code', 'human']),
|
|
40
|
-
}),
|
|
41
|
-
}),
|
|
42
|
-
'complete-milestone': Object.freeze({
|
|
43
|
-
repo_only: Object.freeze({
|
|
44
|
-
requiredKinds: Object.freeze(['code', 'test']),
|
|
45
|
-
recommendedKinds: Object.freeze(['runtime']),
|
|
46
|
-
blockedSoloKinds: Object.freeze(['human', 'delivery']),
|
|
47
|
-
}),
|
|
48
|
-
delivery_sensitive: Object.freeze({
|
|
49
|
-
requiredKinds: Object.freeze(['code', 'test', 'runtime', 'delivery']),
|
|
50
|
-
recommendedKinds: Object.freeze(['human']),
|
|
51
|
-
blockedSoloKinds: Object.freeze(['code', 'human']),
|
|
52
|
-
}),
|
|
53
|
-
}),
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
export { CLOSURE_SURFACES, DELIVERY_POSTURES, EVIDENCE_KINDS };
|
|
57
|
-
|
|
58
|
-
export function normalizeEvidenceKind(kind) {
|
|
59
|
-
if (!kind) {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return LEGACY_EVIDENCE_ALIASES[kind] ?? null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function normalizeEvidenceKinds(kinds = []) {
|
|
67
|
-
const normalized = [];
|
|
68
|
-
for (const kind of kinds) {
|
|
69
|
-
const resolved = normalizeEvidenceKind(kind);
|
|
70
|
-
if (resolved && !normalized.includes(resolved)) {
|
|
71
|
-
normalized.push(resolved);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return normalized;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function isClosureSurface(surface) {
|
|
78
|
-
return CLOSURE_SURFACES.includes(surface);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function getEvidenceContract(surface, deliveryPosture) {
|
|
82
|
-
const matrix = EVIDENCE_MATRIX[surface];
|
|
83
|
-
if (!matrix) {
|
|
84
|
-
throw new Error(`Unsupported closure evidence surface: ${surface}`);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const posture = matrix[deliveryPosture];
|
|
88
|
-
if (!posture) {
|
|
89
|
-
throw new Error(`Unsupported delivery posture for ${surface}: ${deliveryPosture}`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
surface,
|
|
94
|
-
deliveryPosture,
|
|
95
|
-
supportedKinds: [...EVIDENCE_KINDS],
|
|
96
|
-
requiredKinds: [...posture.requiredKinds],
|
|
97
|
-
recommendedKinds: [...posture.recommendedKinds],
|
|
98
|
-
blockedSoloKinds: [...posture.blockedSoloKinds],
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function describeEvidenceSurface(surface) {
|
|
103
|
-
if (!isClosureSurface(surface)) {
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
surface,
|
|
109
|
-
supportedKinds: [...EVIDENCE_KINDS],
|
|
110
|
-
deliveryPostures: DELIVERY_POSTURES.map((deliveryPosture) => getEvidenceContract(surface, deliveryPosture)),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
1
|
+
const EVIDENCE_KINDS = Object.freeze(['code', 'test', 'runtime', 'delivery', 'human']);
|
|
2
|
+
const DELIVERY_POSTURES = Object.freeze(['repo_only', 'delivery_sensitive']);
|
|
3
|
+
const CLOSURE_SURFACES = Object.freeze(['verify', 'audit-milestone', 'complete-milestone']);
|
|
4
|
+
|
|
5
|
+
const LEGACY_EVIDENCE_ALIASES = Object.freeze({
|
|
6
|
+
code: 'code',
|
|
7
|
+
test: 'test',
|
|
8
|
+
runtime: 'runtime',
|
|
9
|
+
delivery: 'delivery',
|
|
10
|
+
human: 'human',
|
|
11
|
+
'code-evidence': 'code',
|
|
12
|
+
'repo-test': 'test',
|
|
13
|
+
'runtime-check': 'runtime',
|
|
14
|
+
'user-confirmation': 'human',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const EVIDENCE_MATRIX = Object.freeze({
|
|
18
|
+
verify: Object.freeze({
|
|
19
|
+
repo_only: Object.freeze({
|
|
20
|
+
requiredKinds: Object.freeze(['code']),
|
|
21
|
+
recommendedKinds: Object.freeze(['test']),
|
|
22
|
+
blockedSoloKinds: Object.freeze(['human', 'delivery']),
|
|
23
|
+
}),
|
|
24
|
+
delivery_sensitive: Object.freeze({
|
|
25
|
+
requiredKinds: Object.freeze(['code', 'runtime']),
|
|
26
|
+
recommendedKinds: Object.freeze(['test', 'delivery', 'human']),
|
|
27
|
+
blockedSoloKinds: Object.freeze(['code', 'human']),
|
|
28
|
+
}),
|
|
29
|
+
}),
|
|
30
|
+
'audit-milestone': Object.freeze({
|
|
31
|
+
repo_only: Object.freeze({
|
|
32
|
+
requiredKinds: Object.freeze(['code', 'test']),
|
|
33
|
+
recommendedKinds: Object.freeze(['runtime', 'human']),
|
|
34
|
+
blockedSoloKinds: Object.freeze(['human', 'delivery']),
|
|
35
|
+
}),
|
|
36
|
+
delivery_sensitive: Object.freeze({
|
|
37
|
+
requiredKinds: Object.freeze(['code', 'test', 'runtime', 'delivery']),
|
|
38
|
+
recommendedKinds: Object.freeze(['human']),
|
|
39
|
+
blockedSoloKinds: Object.freeze(['code', 'human']),
|
|
40
|
+
}),
|
|
41
|
+
}),
|
|
42
|
+
'complete-milestone': Object.freeze({
|
|
43
|
+
repo_only: Object.freeze({
|
|
44
|
+
requiredKinds: Object.freeze(['code', 'test']),
|
|
45
|
+
recommendedKinds: Object.freeze(['runtime']),
|
|
46
|
+
blockedSoloKinds: Object.freeze(['human', 'delivery']),
|
|
47
|
+
}),
|
|
48
|
+
delivery_sensitive: Object.freeze({
|
|
49
|
+
requiredKinds: Object.freeze(['code', 'test', 'runtime', 'delivery']),
|
|
50
|
+
recommendedKinds: Object.freeze(['human']),
|
|
51
|
+
blockedSoloKinds: Object.freeze(['code', 'human']),
|
|
52
|
+
}),
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export { CLOSURE_SURFACES, DELIVERY_POSTURES, EVIDENCE_KINDS };
|
|
57
|
+
|
|
58
|
+
export function normalizeEvidenceKind(kind) {
|
|
59
|
+
if (!kind) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return LEGACY_EVIDENCE_ALIASES[kind] ?? null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function normalizeEvidenceKinds(kinds = []) {
|
|
67
|
+
const normalized = [];
|
|
68
|
+
for (const kind of kinds) {
|
|
69
|
+
const resolved = normalizeEvidenceKind(kind);
|
|
70
|
+
if (resolved && !normalized.includes(resolved)) {
|
|
71
|
+
normalized.push(resolved);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return normalized;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function isClosureSurface(surface) {
|
|
78
|
+
return CLOSURE_SURFACES.includes(surface);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function getEvidenceContract(surface, deliveryPosture) {
|
|
82
|
+
const matrix = EVIDENCE_MATRIX[surface];
|
|
83
|
+
if (!matrix) {
|
|
84
|
+
throw new Error(`Unsupported closure evidence surface: ${surface}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const posture = matrix[deliveryPosture];
|
|
88
|
+
if (!posture) {
|
|
89
|
+
throw new Error(`Unsupported delivery posture for ${surface}: ${deliveryPosture}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
surface,
|
|
94
|
+
deliveryPosture,
|
|
95
|
+
supportedKinds: [...EVIDENCE_KINDS],
|
|
96
|
+
requiredKinds: [...posture.requiredKinds],
|
|
97
|
+
recommendedKinds: [...posture.recommendedKinds],
|
|
98
|
+
blockedSoloKinds: [...posture.blockedSoloKinds],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function describeEvidenceSurface(surface) {
|
|
103
|
+
if (!isClosureSurface(surface)) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
surface,
|
|
109
|
+
supportedKinds: [...EVIDENCE_KINDS],
|
|
110
|
+
deliveryPostures: DELIVERY_POSTURES.map((deliveryPosture) => getEvidenceContract(surface, deliveryPosture)),
|
|
111
|
+
};
|
|
112
|
+
}
|