@opengsd/gsd-core 1.4.2 → 1.5.0-rc.1
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 +1 -1
- package/README.md +3 -3
- package/agents/gsd-executor.md +1 -1
- package/agents/gsd-plan-checker.md +11 -2
- package/agents/gsd-planner.md +11 -7
- package/agents/gsd-verifier.md +3 -3
- package/bin/install.js +947 -149
- package/commands/gsd/autonomous.md +5 -1
- package/commands/gsd/ns-manage.md +8 -1
- package/commands/gsd/ns-project.md +5 -0
- package/commands/gsd/ns-review.md +4 -1
- package/commands/gsd/ns-workflow.md +7 -1
- package/commands/gsd/plan-review-convergence.md +6 -5
- package/commands/gsd/surface.md +12 -5
- package/gemini-extension.json +1 -1
- package/gsd-core/bin/gsd-tools.cjs +198 -101
- package/gsd-core/bin/lib/audit-command-router.cjs +61 -0
- package/gsd-core/bin/lib/capability-registry.cjs +417 -0
- package/gsd-core/bin/lib/capability-state.cjs +336 -0
- package/gsd-core/bin/lib/cli-exit.cjs +22 -3
- package/gsd-core/bin/lib/config-loader.cjs +716 -0
- package/gsd-core/bin/lib/configuration.cjs +4 -34
- package/gsd-core/bin/lib/core-utils.cjs +198 -0
- package/gsd-core/bin/lib/core.cjs +57 -1817
- package/gsd-core/bin/lib/federated-config.cjs +182 -0
- package/gsd-core/bin/lib/graphify-command-router.cjs +74 -0
- package/gsd-core/bin/lib/init.cjs +58 -12
- package/gsd-core/bin/lib/install-profiles.cjs +157 -3
- package/gsd-core/bin/lib/installer-migrations/004-prune-stale-pristine-snapshots.cjs +123 -0
- package/gsd-core/bin/lib/intel-command-router.cjs +116 -0
- package/gsd-core/bin/lib/io.cjs +167 -0
- package/gsd-core/bin/lib/loop-host-contract.cjs +105 -0
- package/gsd-core/bin/lib/loop-resolver.cjs +460 -0
- package/gsd-core/bin/lib/model-resolver.cjs +426 -0
- package/gsd-core/bin/lib/phase-id.cjs +215 -0
- package/gsd-core/bin/lib/phase-locator.cjs +148 -0
- package/gsd-core/bin/lib/profile-pipeline.cjs +2 -2
- package/gsd-core/bin/lib/roadmap-parser.cjs +443 -0
- package/gsd-core/bin/lib/roadmap.cjs +4 -1
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +96 -9
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +2 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +40 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +1 -0
- package/gsd-core/bin/lib/shell-command-projection.cjs +13 -0
- package/gsd-core/bin/lib/state.cjs +114 -2
- package/gsd-core/bin/lib/surface.cjs +66 -14
- package/gsd-core/bin/lib/verify.cjs +1 -1
- package/gsd-core/bin/shared/model-catalog.json +5 -0
- package/gsd-core/bin/shared/runtime-aliases.manifest.json +3 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +57 -7
- package/gsd-core/references/planner-reviews.md +5 -2
- package/gsd-core/templates/phase-prompt.md +7 -7
- package/gsd-core/templates/project.md +19 -2
- package/gsd-core/templates/summary-complex.md +1 -0
- package/gsd-core/templates/summary-minimal.md +1 -0
- package/gsd-core/templates/summary-standard.md +1 -0
- package/gsd-core/templates/summary.md +1 -0
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +1 -1
- package/gsd-core/workflows/add-tests.md +1 -1
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +1 -1
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +1 -1
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous.md +86 -15
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +1 -1
- package/gsd-core/workflows/code-review-fix.md +6 -4
- package/gsd-core/workflows/code-review.md +3 -2
- package/gsd-core/workflows/complete-milestone.md +11 -5
- package/gsd-core/workflows/debug.md +1 -1
- package/gsd-core/workflows/diagnose-issues.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/auto.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
- package/gsd-core/workflows/discuss-phase.md +8 -1
- package/gsd-core/workflows/do.md +1 -1
- package/gsd-core/workflows/docs-update.md +1 -1
- package/gsd-core/workflows/edit-phase.md +1 -1
- package/gsd-core/workflows/eval-review.md +4 -1
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
- package/gsd-core/workflows/execute-phase.md +8 -1
- package/gsd-core/workflows/execute-plan.md +1 -1
- package/gsd-core/workflows/explore.md +1 -1
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +1 -1
- package/gsd-core/workflows/help/modes/full.md +1 -1
- package/gsd-core/workflows/import.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +1 -1
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +1 -1
- package/gsd-core/workflows/new-project.md +1 -1
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-milestone-gaps.md +1 -1
- package/gsd-core/workflows/plan-phase.md +27 -2
- package/gsd-core/workflows/plan-review-convergence.md +76 -63
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress.md +1 -1
- package/gsd-core/workflows/quick.md +2 -2
- package/gsd-core/workflows/reapply-patches.md +18 -1
- package/gsd-core/workflows/remove-phase.md +1 -1
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +1 -1
- package/gsd-core/workflows/review.md +1 -1
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/settings-advanced.md +1 -1
- package/gsd-core/workflows/settings-integrations.md +1 -1
- package/gsd-core/workflows/settings.md +1 -1
- package/gsd-core/workflows/ship.md +8 -1
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/spec-phase.md +1 -1
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/thread.md +1 -1
- package/gsd-core/workflows/transition.md +1 -1
- package/gsd-core/workflows/ui-phase.md +1 -1
- package/gsd-core/workflows/ui-review.md +1 -1
- package/gsd-core/workflows/ultraplan-phase.md +1 -1
- package/gsd-core/workflows/update.md +20 -15
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-phase.md +1 -1
- package/gsd-core/workflows/verify-work.md +8 -1
- package/package.json +7 -2
- package/scripts/base64-scan.sh +1 -1
- package/scripts/changeset/cli.cjs +9 -2
- package/scripts/changeset/lint.cjs +38 -2
- package/scripts/ci-test-scope.cjs +21 -10
- package/scripts/gen-capability-registry.cjs +1808 -0
- package/scripts/gen-loop-host-contract.cjs +471 -0
- package/scripts/lint-regression-test-names.allowlist.json +269 -0
- package/scripts/lint-regression-test-names.cjs +117 -0
- package/scripts/lint-test-file-count.allowlist.json +12 -4
- package/scripts/prompt-injection-scan.sh +4 -4
- package/scripts/run-tests.cjs +79 -16
- package/scripts/secret-scan.sh +3 -3
- package/scripts/run-cross-platform-tests.cjs +0 -67
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Intel command router — CLI subcommand dispatcher for `gsd-tools intel`.
|
|
4
|
+
*
|
|
5
|
+
* ADR-959 (phase 4d-impl-4): intel command family cutover — last first-party
|
|
6
|
+
* command cutover in the initial capability rollout.
|
|
7
|
+
* Extracted from the hardcoded `case 'intel':` arm in gsd-tools.cjs.
|
|
8
|
+
* Behaviour is preserved byte-for-behaviour from the prior inline case;
|
|
9
|
+
* the dispatch path now flows: default → dispatchCapabilityCommand →
|
|
10
|
+
* require(intel-command-router.cjs) → routeIntelCommand.
|
|
11
|
+
*
|
|
12
|
+
* Router signature: { args, cwd, raw, error } — identical to the existing
|
|
13
|
+
* host routers. No new handler/arg convention; the capability registry
|
|
14
|
+
* discovers this router by name.
|
|
15
|
+
*
|
|
16
|
+
* Arg indexing (preserved exactly from the original case):
|
|
17
|
+
* args[0] = 'intel' (family — matched by dispatchCapabilityCommand)
|
|
18
|
+
* args[1] = subcommand (query | status | diff | snapshot | patch-meta |
|
|
19
|
+
* validate | extract-exports | update | api-surface)
|
|
20
|
+
* args[2] = term (query) | filePath (patch-meta | extract-exports)
|
|
21
|
+
*
|
|
22
|
+
* Notable: the `status` subcommand applies a `timeAgo` transform on
|
|
23
|
+
* `status.files[*].updated_at` in non-raw mode — preserved exactly.
|
|
24
|
+
*
|
|
25
|
+
* Test seams: pass `_intel` to inject a mock intel module; pass `_core` to
|
|
26
|
+
* inject a mock core module (captures `output` calls and provides a
|
|
27
|
+
* deterministic `timeAgo` without writing to real stdout). The `_`-prefix
|
|
28
|
+
* follows the repo's established seam convention (see audit-command-router.cts
|
|
29
|
+
* for the `_core` seam pattern). Production callers omit both.
|
|
30
|
+
*
|
|
31
|
+
* Note on `error(); return` pairs: in production `error()` calls
|
|
32
|
+
* `process.exit(1)` so the `return` is an equivalent no-op halt. The pairs
|
|
33
|
+
* are kept for lint/control-flow clarity; they do NOT change behaviour.
|
|
34
|
+
*
|
|
35
|
+
* Lazy require: intel.cjs is required INSIDE the route function so it is
|
|
36
|
+
* only loaded when an intel command is actually dispatched (preserves
|
|
37
|
+
* equivalence with the old inline case arm which required it at the top of
|
|
38
|
+
* the case block).
|
|
39
|
+
*/
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
41
|
+
const core = require("./core.cjs");
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
43
|
+
const io = require("./io.cjs");
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
45
|
+
const path = require("path");
|
|
46
|
+
const { ERROR_REASON } = io;
|
|
47
|
+
// ─── Implementation ───────────────────────────────────────────────────────────
|
|
48
|
+
function routeIntelCommand({ args, cwd, raw, error, _intel, _core }) {
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment
|
|
50
|
+
const intel = _intel ?? require('./intel.cjs');
|
|
51
|
+
const c = _core ?? core;
|
|
52
|
+
const subcommand = args[1];
|
|
53
|
+
if (subcommand === 'query') {
|
|
54
|
+
const term = args[2];
|
|
55
|
+
if (!term) {
|
|
56
|
+
error('Usage: gsd-tools intel query <term>', ERROR_REASON.USAGE);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const planningDir = path.join(cwd, '.planning');
|
|
60
|
+
c.output(intel.intelQuery(term, planningDir), raw);
|
|
61
|
+
}
|
|
62
|
+
else if (subcommand === 'status') {
|
|
63
|
+
const planningDir = path.join(cwd, '.planning');
|
|
64
|
+
const status = intel.intelStatus(planningDir);
|
|
65
|
+
if (!raw && status.files) {
|
|
66
|
+
for (const file of Object.values(status.files)) {
|
|
67
|
+
if (file.updated_at) {
|
|
68
|
+
file.updated_at = c.timeAgo(new Date(file.updated_at));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
c.output(status, raw);
|
|
73
|
+
}
|
|
74
|
+
else if (subcommand === 'diff') {
|
|
75
|
+
const planningDir = path.join(cwd, '.planning');
|
|
76
|
+
c.output(intel.intelDiff(planningDir), raw);
|
|
77
|
+
}
|
|
78
|
+
else if (subcommand === 'snapshot') {
|
|
79
|
+
const planningDir = path.join(cwd, '.planning');
|
|
80
|
+
c.output(intel.intelSnapshot(planningDir), raw);
|
|
81
|
+
}
|
|
82
|
+
else if (subcommand === 'patch-meta') {
|
|
83
|
+
const filePath = args[2];
|
|
84
|
+
if (!filePath) {
|
|
85
|
+
error('Usage: gsd-tools intel patch-meta <file-path>', ERROR_REASON.USAGE);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
c.output(intel.intelPatchMeta(path.resolve(cwd, filePath)), raw);
|
|
89
|
+
}
|
|
90
|
+
else if (subcommand === 'validate') {
|
|
91
|
+
const planningDir = path.join(cwd, '.planning');
|
|
92
|
+
c.output(intel.intelValidate(planningDir), raw);
|
|
93
|
+
}
|
|
94
|
+
else if (subcommand === 'extract-exports') {
|
|
95
|
+
const filePath = args[2];
|
|
96
|
+
if (!filePath) {
|
|
97
|
+
error('Usage: gsd-tools intel extract-exports <file-path>', ERROR_REASON.USAGE);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
c.output(intel.intelExtractExports(path.resolve(cwd, filePath)), raw);
|
|
101
|
+
}
|
|
102
|
+
else if (subcommand === 'update') {
|
|
103
|
+
const planningDir = path.join(cwd, '.planning');
|
|
104
|
+
c.output(intel.intelUpdate(planningDir), raw);
|
|
105
|
+
}
|
|
106
|
+
else if (subcommand === 'api-surface') {
|
|
107
|
+
const planningDir = path.join(cwd, '.planning');
|
|
108
|
+
c.output(intel.intelApiSurface(planningDir), raw);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
error('Unknown intel subcommand. Available: query, status, update, diff, snapshot, patch-meta, validate, extract-exports, api-surface', ERROR_REASON.SDK_UNKNOWN_COMMAND);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
module.exports = {
|
|
115
|
+
routeIntelCommand,
|
|
116
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLI I/O primitives — output(), error(), ERROR_REASON, JSON-error mode,
|
|
4
|
+
* and the temp-file helpers that output() depends on.
|
|
5
|
+
*
|
|
6
|
+
* Extracted from core.cts (ADR-857 rollout phase 1 / issue #859).
|
|
7
|
+
* The hand-written bodies are preserved byte-for-behaviour; only the module
|
|
8
|
+
* boundary moved. core.cts re-exports every symbol here under its own
|
|
9
|
+
* `export =` object so existing consumers are unaffected.
|
|
10
|
+
*
|
|
11
|
+
* New imports should pull I/O primitives from io.cjs directly.
|
|
12
|
+
*/
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
17
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
18
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
19
|
+
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
20
|
+
// ─── Temp-file helpers (needed by output()) ──────────────────────────────────
|
|
21
|
+
/**
|
|
22
|
+
* Dedicated GSD temp directory: path.join(os.tmpdir(), 'gsd').
|
|
23
|
+
* Created on first use. Keeps GSD temp files isolated from the system
|
|
24
|
+
* temp directory so reap scans only GSD files (#1975).
|
|
25
|
+
*/
|
|
26
|
+
const GSD_TEMP_DIR = node_path_1.default.join(node_os_1.default.tmpdir(), 'gsd');
|
|
27
|
+
function ensureGsdTempDir() {
|
|
28
|
+
(0, shell_command_projection_cjs_1.platformEnsureDir)(GSD_TEMP_DIR);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Remove stale gsd-* temp files/dirs older than maxAgeMs (default: 5 minutes).
|
|
32
|
+
* Runs opportunistically before each new temp file write to prevent unbounded accumulation.
|
|
33
|
+
* @param prefix - filename prefix to match (e.g., 'gsd-')
|
|
34
|
+
* @param opts
|
|
35
|
+
* @param opts.maxAgeMs - max age in ms before removal (default: 5 min)
|
|
36
|
+
* @param opts.dirsOnly - if true, only remove directories (default: false)
|
|
37
|
+
*/
|
|
38
|
+
function reapStaleTempFiles(prefix = 'gsd-', { maxAgeMs = 5 * 60 * 1000, dirsOnly = false } = {}) {
|
|
39
|
+
try {
|
|
40
|
+
ensureGsdTempDir();
|
|
41
|
+
const now = Date.now();
|
|
42
|
+
const entries = node_fs_1.default.readdirSync(GSD_TEMP_DIR);
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
if (!entry.startsWith(prefix))
|
|
45
|
+
continue;
|
|
46
|
+
const fullPath = node_path_1.default.join(GSD_TEMP_DIR, entry);
|
|
47
|
+
try {
|
|
48
|
+
const stat = node_fs_1.default.statSync(fullPath);
|
|
49
|
+
if (now - stat.mtimeMs > maxAgeMs) {
|
|
50
|
+
if (stat.isDirectory()) {
|
|
51
|
+
node_fs_1.default.rmSync(fullPath, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
else if (!dirsOnly) {
|
|
54
|
+
node_fs_1.default.unlinkSync(fullPath);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// File may have been removed between readdir and stat — ignore
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Non-critical — don't let cleanup failures break output
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// ─── Output helpers ───────────────────────────────────────────────────────────
|
|
68
|
+
function output(result, raw, rawValue) {
|
|
69
|
+
let data;
|
|
70
|
+
if (raw && rawValue !== undefined) {
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
72
|
+
data = String(rawValue);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const json = JSON.stringify(result, null, 2);
|
|
76
|
+
// Large payloads exceed Claude Code's Bash tool buffer (~50KB).
|
|
77
|
+
// Write to tmpfile and output the path prefixed with @file: so callers can detect it.
|
|
78
|
+
if (json.length > 50000) {
|
|
79
|
+
reapStaleTempFiles();
|
|
80
|
+
ensureGsdTempDir();
|
|
81
|
+
const tmpPath = node_path_1.default.join(GSD_TEMP_DIR, `gsd-${Date.now()}.json`);
|
|
82
|
+
(0, shell_command_projection_cjs_1.platformWriteSync)(tmpPath, json);
|
|
83
|
+
data = '@file:' + tmpPath;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
data = json;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// process.stdout.write() is async when stdout is a pipe — process.exit()
|
|
90
|
+
// can tear down the process before the reader consumes the buffer.
|
|
91
|
+
// fs.writeSync(1, ...) blocks until the kernel accepts the bytes, and
|
|
92
|
+
// skipping process.exit() lets the event loop drain naturally.
|
|
93
|
+
node_fs_1.default.writeSync(1, data);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Frozen enum of typed reason codes used by error() for structured errors.
|
|
97
|
+
* Each subcommand contributes its own codes; the enum exists so tests can
|
|
98
|
+
* assert against typed values instead of grepping stderr (#2974).
|
|
99
|
+
*
|
|
100
|
+
* Adding a new code:
|
|
101
|
+
* - Pick a snake_case lowercase value (the JSON wire form)
|
|
102
|
+
* - Group by subsystem prefix (CONFIG_*, SDK_*, etc)
|
|
103
|
+
* - Pass it to error(msg, ERROR_REASON.NEW_CODE) at the call site
|
|
104
|
+
*/
|
|
105
|
+
const ERROR_REASON = Object.freeze({
|
|
106
|
+
// config-get / config-set
|
|
107
|
+
CONFIG_KEY_NOT_FOUND: 'config_key_not_found',
|
|
108
|
+
CONFIG_NO_FILE: 'config_no_file',
|
|
109
|
+
CONFIG_PARSE_FAILED: 'config_parse_failed',
|
|
110
|
+
CONFIG_INVALID_KEY: 'config_invalid_key',
|
|
111
|
+
// SDK / gsd-tools dispatch
|
|
112
|
+
SDK_FAIL_FAST: 'sdk_fail_fast',
|
|
113
|
+
SDK_UNKNOWN_COMMAND: 'sdk_unknown_command',
|
|
114
|
+
SDK_MISSING_ARG: 'sdk_missing_arg',
|
|
115
|
+
// workflow / phase
|
|
116
|
+
PHASE_NOT_FOUND: 'phase_not_found',
|
|
117
|
+
SUMMARY_NO_PLANNING: 'summary_no_planning',
|
|
118
|
+
// graphify
|
|
119
|
+
GRAPHIFY_NO_GRAPH: 'graphify_no_graph',
|
|
120
|
+
GRAPHIFY_INVALID_QUERY: 'graphify_invalid_query',
|
|
121
|
+
// hooks
|
|
122
|
+
HOOKS_OPT_OUT: 'hooks_opt_out',
|
|
123
|
+
// security-scan
|
|
124
|
+
SECURITY_SCAN_FAILED: 'security_scan_failed',
|
|
125
|
+
// generic
|
|
126
|
+
USAGE: 'usage',
|
|
127
|
+
UNKNOWN: 'unknown',
|
|
128
|
+
});
|
|
129
|
+
/**
|
|
130
|
+
* Process-level flag: when true, error() emits structured JSON to stderr
|
|
131
|
+
* instead of plain "Error: <message>" text. Set by gsd-tools.cjs when the
|
|
132
|
+
* CLI is invoked with `--json-errors`. Tests opt in to typed-IR error
|
|
133
|
+
* assertions by passing that flag and parsing the JSON.
|
|
134
|
+
*
|
|
135
|
+
* Default off so existing callers and human operators keep their plain-text
|
|
136
|
+
* diagnostics. The structured form is opt-in for tooling and tests (#2974).
|
|
137
|
+
*/
|
|
138
|
+
let _jsonErrorMode = false;
|
|
139
|
+
function setJsonErrorMode(v) { _jsonErrorMode = !!v; }
|
|
140
|
+
function getJsonErrorMode() { return _jsonErrorMode; }
|
|
141
|
+
/**
|
|
142
|
+
* Emit an error and exit. When the second argument is provided it must be
|
|
143
|
+
* a value from ERROR_REASON; tests can assert on `result.reason`. When the
|
|
144
|
+
* process is in JSON-error mode, stderr receives `{ ok: false, reason,
|
|
145
|
+
* message }` so callers can parse it; otherwise stderr keeps the plain
|
|
146
|
+
* text form for human operators.
|
|
147
|
+
*/
|
|
148
|
+
function error(message, reason = ERROR_REASON.UNKNOWN) {
|
|
149
|
+
if (_jsonErrorMode) {
|
|
150
|
+
const payload = JSON.stringify({ ok: false, reason, message }) + '\n';
|
|
151
|
+
node_fs_1.default.writeSync(2, payload);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
node_fs_1.default.writeSync(2, 'Error: ' + message + '\n');
|
|
155
|
+
}
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
module.exports = {
|
|
159
|
+
GSD_TEMP_DIR,
|
|
160
|
+
ensureGsdTempDir,
|
|
161
|
+
reapStaleTempFiles,
|
|
162
|
+
output,
|
|
163
|
+
ERROR_REASON,
|
|
164
|
+
setJsonErrorMode,
|
|
165
|
+
getJsonErrorMode,
|
|
166
|
+
error,
|
|
167
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* loop-host-contract.cjs — generated by scripts/gen-loop-host-contract.cjs
|
|
5
|
+
* DO NOT EDIT BY HAND. Run: node scripts/gen-loop-host-contract.cjs --write
|
|
6
|
+
* ADR-894 §3 — Loop Host Contract, generated from workflow markers.
|
|
7
|
+
* 12 points: discuss:pre/post, plan:pre/post, execute:pre/wave:pre/wave:post/post,
|
|
8
|
+
* verify:pre/post, ship:pre/post. Per-step agentRoles and coreArtifacts.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const LOOP_HOST_CONTRACT = [
|
|
12
|
+
{
|
|
13
|
+
"step": "discuss",
|
|
14
|
+
"points": [
|
|
15
|
+
"discuss:pre",
|
|
16
|
+
"discuss:post"
|
|
17
|
+
],
|
|
18
|
+
"agentRoles": [
|
|
19
|
+
"orchestrator"
|
|
20
|
+
],
|
|
21
|
+
"coreArtifacts": {
|
|
22
|
+
"produces": [
|
|
23
|
+
"CONTEXT.md"
|
|
24
|
+
],
|
|
25
|
+
"consumes": []
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"step": "plan",
|
|
30
|
+
"points": [
|
|
31
|
+
"plan:pre",
|
|
32
|
+
"plan:post"
|
|
33
|
+
],
|
|
34
|
+
"agentRoles": [
|
|
35
|
+
"researcher",
|
|
36
|
+
"planner",
|
|
37
|
+
"checker"
|
|
38
|
+
],
|
|
39
|
+
"coreArtifacts": {
|
|
40
|
+
"produces": [
|
|
41
|
+
"PLAN.md"
|
|
42
|
+
],
|
|
43
|
+
"consumes": [
|
|
44
|
+
"CONTEXT.md"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"step": "execute",
|
|
50
|
+
"points": [
|
|
51
|
+
"execute:pre",
|
|
52
|
+
"execute:wave:pre",
|
|
53
|
+
"execute:wave:post",
|
|
54
|
+
"execute:post"
|
|
55
|
+
],
|
|
56
|
+
"agentRoles": [
|
|
57
|
+
"executor",
|
|
58
|
+
"verifier"
|
|
59
|
+
],
|
|
60
|
+
"coreArtifacts": {
|
|
61
|
+
"produces": [
|
|
62
|
+
"SUMMARY.md"
|
|
63
|
+
],
|
|
64
|
+
"consumes": [
|
|
65
|
+
"PLAN.md"
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"step": "verify",
|
|
71
|
+
"points": [
|
|
72
|
+
"verify:pre",
|
|
73
|
+
"verify:post"
|
|
74
|
+
],
|
|
75
|
+
"agentRoles": [
|
|
76
|
+
"orchestrator"
|
|
77
|
+
],
|
|
78
|
+
"coreArtifacts": {
|
|
79
|
+
"produces": [
|
|
80
|
+
"UAT.md"
|
|
81
|
+
],
|
|
82
|
+
"consumes": [
|
|
83
|
+
"SUMMARY.md"
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"step": "ship",
|
|
89
|
+
"points": [
|
|
90
|
+
"ship:pre",
|
|
91
|
+
"ship:post"
|
|
92
|
+
],
|
|
93
|
+
"agentRoles": [
|
|
94
|
+
"orchestrator"
|
|
95
|
+
],
|
|
96
|
+
"coreArtifacts": {
|
|
97
|
+
"produces": [],
|
|
98
|
+
"consumes": [
|
|
99
|
+
"UAT.md"
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
module.exports = { LOOP_HOST_CONTRACT };
|