@opengsd/gsd-core 1.2.0 → 1.3.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/README.ja-JP.md +6 -5
- package/README.ko-KR.md +6 -5
- package/README.md +10 -45
- package/README.pt-BR.md +5 -4
- package/README.zh-CN.md +6 -5
- package/agents/gsd-ai-researcher.md +1 -1
- package/agents/gsd-debug-session-manager.md +1 -1
- package/agents/gsd-doc-writer.md +7 -6
- package/agents/gsd-domain-researcher.md +1 -1
- package/agents/gsd-eval-planner.md +1 -1
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +1 -1
- package/assets/gsd-logo-2000-transparent.png +0 -0
- package/assets/gsd-logo-2000-transparent.svg +17 -0
- package/assets/gsd-logo-2000.png +0 -0
- package/assets/gsd-logo-2000.svg +21 -0
- package/assets/terminal.svg +68 -0
- package/bin/install.js +86 -44
- package/commands/gsd/review.md +2 -1
- package/get-shit-done/bin/gsd-tools.cjs +37 -1
- package/get-shit-done/bin/lib/command-aliases.cjs +16 -0
- package/get-shit-done/bin/lib/commands.cjs +109 -5
- package/get-shit-done/bin/lib/config-types.cjs +19 -0
- package/get-shit-done/bin/lib/core.cjs +455 -63
- package/get-shit-done/bin/lib/gap-checker.cjs +56 -7
- package/get-shit-done/bin/lib/installer-migration-report.cjs +1 -0
- package/get-shit-done/bin/lib/milestone.cjs +59 -1
- package/get-shit-done/bin/lib/model-catalog.cjs +17 -0
- package/get-shit-done/bin/lib/phase-lifecycle.cjs +0 -1
- package/get-shit-done/bin/lib/review-reviewer-selection.cjs +1 -0
- package/get-shit-done/bin/lib/roadmap-command-router.cjs +134 -0
- package/get-shit-done/bin/lib/roadmap-upgrade.cjs +569 -0
- package/get-shit-done/bin/lib/roadmap.cjs +6 -5
- package/get-shit-done/bin/lib/semver-compare.cjs +34 -27
- package/get-shit-done/bin/lib/shell-command-projection.cjs +35 -0
- package/get-shit-done/bin/lib/state-document.cjs +0 -4
- package/get-shit-done/bin/lib/state.cjs +41 -6
- package/get-shit-done/bin/lib/ui-safety-gate.cjs +111 -0
- package/get-shit-done/bin/lib/validate.cjs +43 -17
- package/get-shit-done/bin/lib/verify.cjs +107 -4
- package/get-shit-done/bin/shared/config-defaults.manifest.json +1 -0
- package/get-shit-done/bin/shared/config-schema.manifest.json +12 -1
- package/get-shit-done/bin/shared/model-catalog.json +27 -0
- package/get-shit-done/references/checkpoints.md +1 -1
- package/get-shit-done/references/planner-human-verify-mode.md +1 -1
- package/get-shit-done/references/ui-brand.md +4 -2
- package/get-shit-done/workflows/audit-fix.md +1 -1
- package/get-shit-done/workflows/audit-milestone.md +2 -0
- package/get-shit-done/workflows/autonomous.md +7 -5
- package/get-shit-done/workflows/cleanup.md +43 -3
- package/get-shit-done/workflows/code-review-fix.md +3 -3
- package/get-shit-done/workflows/code-review.md +2 -0
- package/get-shit-done/workflows/debug.md +6 -1
- package/get-shit-done/workflows/diagnose-issues.md +2 -0
- package/get-shit-done/workflows/discuss-phase/modes/advisor.md +1 -1
- package/get-shit-done/workflows/discuss-phase-assumptions.md +2 -2
- package/get-shit-done/workflows/docs-update.md +18 -4
- package/get-shit-done/workflows/eval-review.md +1 -1
- package/get-shit-done/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/get-shit-done/workflows/execute-phase.md +21 -11
- package/get-shit-done/workflows/execute-plan.md +1 -1
- package/get-shit-done/workflows/explore.md +2 -0
- package/get-shit-done/workflows/help/modes/default.md +3 -3
- package/get-shit-done/workflows/help/modes/full.md +5 -5
- package/get-shit-done/workflows/import.md +2 -0
- package/get-shit-done/workflows/ingest-docs.md +2 -2
- package/get-shit-done/workflows/manager.md +2 -2
- package/get-shit-done/workflows/map-codebase.md +2 -0
- package/get-shit-done/workflows/new-milestone.md +2 -2
- package/get-shit-done/workflows/new-project.md +2 -2
- package/get-shit-done/workflows/plan-phase.md +16 -15
- package/get-shit-done/workflows/plan-review-convergence.md +3 -3
- package/get-shit-done/workflows/quick.md +5 -3
- package/get-shit-done/workflows/review.md +109 -1
- package/get-shit-done/workflows/scan.md +2 -0
- package/get-shit-done/workflows/secure-phase.md +2 -0
- package/get-shit-done/workflows/settings-advanced.md +195 -5
- package/get-shit-done/workflows/settings.md +15 -1
- package/get-shit-done/workflows/ui-phase.md +2 -2
- package/get-shit-done/workflows/ui-review.md +1 -1
- package/get-shit-done/workflows/validate-phase.md +2 -0
- package/get-shit-done/workflows/verify-work.md +2 -2
- package/hooks/dist/gsd-worktree-path-guard.js +169 -0
- package/hooks/gsd-worktree-path-guard.js +169 -0
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +9 -6
- package/scripts/build-hooks.js +1 -0
- package/scripts/ci-test-scope.cjs +10 -0
- package/scripts/run-tests.cjs +25 -1
- package/scripts/lint-shared-module-handsync.cjs +0 -388
- package/scripts/shared-module-handsync-allowlist.json +0 -183
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Shared Module hand-sync drift lint — Phase 6 of #3524 (#3575).
|
|
6
|
-
*
|
|
7
|
-
* Scans get-shit-done/bin/lib/ for .cjs files and checks whether a matching
|
|
8
|
-
* TypeScript file exists in sdk/src/<name>.ts, sdk/src/query/<name>.ts, or
|
|
9
|
-
* sdk/src/<name>/index.ts (excluding *.generated.ts and *.test.ts).
|
|
10
|
-
*
|
|
11
|
-
* Allowlist entries are keyed by the (cjs, ts) PAIR. An entry with cjs
|
|
12
|
-
* `bin/lib/foo.cjs` and ts `sdk/src/foo.ts` only allow-throughs that exact
|
|
13
|
-
* pair — a sibling at `sdk/src/query/foo.ts` is still flagged.
|
|
14
|
-
*
|
|
15
|
-
* Cross-name pairs are also supported when declared in the allowlist
|
|
16
|
-
* (for example `verify.cjs` <-> `validate.ts`), so cooperating siblings are
|
|
17
|
-
* observable even when basenames differ.
|
|
18
|
-
*
|
|
19
|
-
* If a pair is found:
|
|
20
|
-
* - cooperatingSiblings (matching cjs + ts): accepted silently (exit 0).
|
|
21
|
-
* - migrateMeBacklog (matching cjs + ts): emits a WARNING only when
|
|
22
|
-
* --warn-all is set; otherwise the pair passes silently. Backlog
|
|
23
|
-
* pairs never fail CI.
|
|
24
|
-
* - Unlisted pairs (cjs or ts not on either list): ERROR — exit 1.
|
|
25
|
-
*
|
|
26
|
-
* Usage:
|
|
27
|
-
* node scripts/lint-shared-module-handsync.cjs
|
|
28
|
-
* node scripts/lint-shared-module-handsync.cjs --root /path/to/repo
|
|
29
|
-
* node scripts/lint-shared-module-handsync.cjs --warn-all
|
|
30
|
-
* node scripts/lint-shared-module-handsync.cjs --cjs-dir custom/bin/lib --sdk-src custom/sdk/src
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
const fs = require('fs');
|
|
34
|
-
const path = require('path');
|
|
35
|
-
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
// Argument parsing
|
|
38
|
-
// ---------------------------------------------------------------------------
|
|
39
|
-
const args = process.argv.slice(2);
|
|
40
|
-
let ROOT = path.resolve(__dirname, '..');
|
|
41
|
-
let CJS_DIR = null; // resolved below
|
|
42
|
-
let SDK_SRC = null; // resolved below
|
|
43
|
-
let SDK_SRC_EXPLICIT = false;
|
|
44
|
-
let ALLOWLIST_OVERRIDE = null; // resolved below
|
|
45
|
-
let WARN_ALL = false;
|
|
46
|
-
let JSON_OUTPUT = false;
|
|
47
|
-
|
|
48
|
-
for (let i = 0; i < args.length; i++) {
|
|
49
|
-
if (args[i] === '--root' && args[i + 1]) {
|
|
50
|
-
ROOT = path.resolve(args[++i]);
|
|
51
|
-
} else if (args[i] === '--cjs-dir' && args[i + 1]) {
|
|
52
|
-
CJS_DIR = path.resolve(args[++i]);
|
|
53
|
-
} else if (args[i] === '--sdk-src' && args[i + 1]) {
|
|
54
|
-
SDK_SRC = path.resolve(args[++i]);
|
|
55
|
-
SDK_SRC_EXPLICIT = true;
|
|
56
|
-
} else if (args[i] === '--allowlist' && args[i + 1]) {
|
|
57
|
-
ALLOWLIST_OVERRIDE = path.resolve(args[++i]);
|
|
58
|
-
} else if (args[i] === '--warn-all') {
|
|
59
|
-
WARN_ALL = true;
|
|
60
|
-
} else if (args[i] === '--json') {
|
|
61
|
-
JSON_OUTPUT = true;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (!CJS_DIR) CJS_DIR = path.join(ROOT, 'get-shit-done', 'bin', 'lib');
|
|
66
|
-
if (!SDK_SRC) SDK_SRC = path.join(ROOT, 'sdk', 'src');
|
|
67
|
-
|
|
68
|
-
// ---------------------------------------------------------------------------
|
|
69
|
-
// Load allowlist
|
|
70
|
-
// When --root is given (e.g. in tests), prefer <ROOT>/scripts/allowlist.json
|
|
71
|
-
// so fixture trees can supply their own allowlist. Fall back to the copy
|
|
72
|
-
// co-located with this script (default production path).
|
|
73
|
-
// ---------------------------------------------------------------------------
|
|
74
|
-
const ALLOWLIST_PATH = ALLOWLIST_OVERRIDE
|
|
75
|
-
? ALLOWLIST_OVERRIDE
|
|
76
|
-
: fs.existsSync(path.join(ROOT, 'scripts', 'shared-module-handsync-allowlist.json'))
|
|
77
|
-
? path.join(ROOT, 'scripts', 'shared-module-handsync-allowlist.json')
|
|
78
|
-
: path.join(__dirname, 'shared-module-handsync-allowlist.json');
|
|
79
|
-
let allowlist;
|
|
80
|
-
try {
|
|
81
|
-
allowlist = JSON.parse(fs.readFileSync(ALLOWLIST_PATH, 'utf8'));
|
|
82
|
-
} catch (err) {
|
|
83
|
-
process.stderr.write(
|
|
84
|
-
`lint-shared-module-handsync: failed to read allowlist at ${ALLOWLIST_PATH}: ${err.message}\n`
|
|
85
|
-
);
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Pair identity = `${cjs}::${ts}`. Keying on the pair (not just cjs)
|
|
91
|
-
* prevents an allowlisted entry from silently passing an unintended
|
|
92
|
-
* sibling at a different ts path with the same basename.
|
|
93
|
-
*
|
|
94
|
-
* @type {Set<string>} pair identities in cooperatingSiblings
|
|
95
|
-
*/
|
|
96
|
-
const cooperatingPairs = new Set(
|
|
97
|
-
(allowlist.cooperatingSiblings || []).map((e) => `${e.cjs}::${e.ts}`)
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
/** @type {Map<string, object>} pair identity -> entry for migrateMeBacklog */
|
|
101
|
-
const migrateMap = new Map(
|
|
102
|
-
(allowlist.migrateMeBacklog || []).map((e) => [`${e.cjs}::${e.ts}`, e])
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
/** @type {Map<string, Set<string>>} cjs rel path -> explicit declared ts rel paths */
|
|
106
|
-
const explicitTsByCjs = new Map();
|
|
107
|
-
for (const entry of [
|
|
108
|
-
...(allowlist.cooperatingSiblings || []),
|
|
109
|
-
...(allowlist.migrateMeBacklog || []),
|
|
110
|
-
]) {
|
|
111
|
-
if (!entry || typeof entry.cjs !== 'string' || typeof entry.ts !== 'string') continue;
|
|
112
|
-
if (!explicitTsByCjs.has(entry.cjs)) explicitTsByCjs.set(entry.cjs, new Set());
|
|
113
|
-
explicitTsByCjs.get(entry.cjs).add(entry.ts);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// ---------------------------------------------------------------------------
|
|
117
|
-
// Build SDK name index: name -> array of absolute TS paths
|
|
118
|
-
// (excludes *.generated.ts and *.test.ts)
|
|
119
|
-
// ---------------------------------------------------------------------------
|
|
120
|
-
function buildSdkIndex(sdkSrc) {
|
|
121
|
-
const index = new Map(); // name -> [absPath, ...]
|
|
122
|
-
|
|
123
|
-
function addEntry(name, absPath) {
|
|
124
|
-
if (!index.has(name)) index.set(name, []);
|
|
125
|
-
index.get(name).push(absPath);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function walk(dir) {
|
|
129
|
-
let entries;
|
|
130
|
-
try {
|
|
131
|
-
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
132
|
-
} catch (_) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
for (const ent of entries) {
|
|
136
|
-
const abs = path.join(dir, ent.name);
|
|
137
|
-
if (ent.isDirectory()) {
|
|
138
|
-
walk(abs);
|
|
139
|
-
} else if (ent.isFile() && ent.name.endsWith('.ts') &&
|
|
140
|
-
!ent.name.endsWith('.generated.ts') &&
|
|
141
|
-
!ent.name.endsWith('.test.ts')) {
|
|
142
|
-
const rel = path.relative(sdkSrc, abs);
|
|
143
|
-
const parts = rel.split(path.sep);
|
|
144
|
-
|
|
145
|
-
// sdk/src/<name>.ts (direct child, not in a subdir)
|
|
146
|
-
if (parts.length === 1) {
|
|
147
|
-
const name = parts[0].slice(0, -3); // strip .ts
|
|
148
|
-
addEntry(name, abs);
|
|
149
|
-
}
|
|
150
|
-
// sdk/src/<name>/index.ts (one subdir deep, file is index.ts)
|
|
151
|
-
else if (parts.length === 2 && parts[1] === 'index.ts') {
|
|
152
|
-
const name = parts[0];
|
|
153
|
-
addEntry(name, abs);
|
|
154
|
-
}
|
|
155
|
-
// sdk/src/query/<name>.ts (exactly: query/<something>.ts)
|
|
156
|
-
else if (parts.length === 2 && parts[0] === 'query' && parts[1] !== 'index.ts') {
|
|
157
|
-
const name = parts[1].slice(0, -3); // strip .ts
|
|
158
|
-
addEntry(name, abs);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
walk(sdkSrc);
|
|
165
|
-
return index;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// ---------------------------------------------------------------------------
|
|
169
|
-
// Scan CJS files (direct children only; exclude *.generated.cjs)
|
|
170
|
-
// ---------------------------------------------------------------------------
|
|
171
|
-
function scanCjsFiles(cjsDir) {
|
|
172
|
-
let entries;
|
|
173
|
-
try {
|
|
174
|
-
entries = fs.readdirSync(cjsDir, { withFileTypes: true });
|
|
175
|
-
} catch (err) {
|
|
176
|
-
process.stderr.write(
|
|
177
|
-
`lint-shared-module-handsync: cannot read CJS dir ${cjsDir}: ${err.message}\n`
|
|
178
|
-
);
|
|
179
|
-
process.exit(1);
|
|
180
|
-
}
|
|
181
|
-
return entries
|
|
182
|
-
.filter(
|
|
183
|
-
(e) =>
|
|
184
|
-
e.isFile() &&
|
|
185
|
-
e.name.endsWith('.cjs') &&
|
|
186
|
-
!e.name.endsWith('.generated.cjs')
|
|
187
|
-
)
|
|
188
|
-
.map((e) => ({
|
|
189
|
-
name: e.name.slice(0, -4), // strip .cjs
|
|
190
|
-
absPath: path.join(cjsDir, e.name),
|
|
191
|
-
}));
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// ---------------------------------------------------------------------------
|
|
195
|
-
// Main
|
|
196
|
-
// ---------------------------------------------------------------------------
|
|
197
|
-
function emitJson(payload) {
|
|
198
|
-
process.stdout.write(JSON.stringify(payload) + '\n');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function main() {
|
|
202
|
-
// Check that the directories exist
|
|
203
|
-
if (!fs.existsSync(CJS_DIR)) {
|
|
204
|
-
if (JSON_OUTPUT) {
|
|
205
|
-
emitJson({ ok: false, reason: 'cjs_dir_missing', path: CJS_DIR });
|
|
206
|
-
} else {
|
|
207
|
-
process.stderr.write(
|
|
208
|
-
`lint-shared-module-handsync: CJS dir not found: ${CJS_DIR}\n` +
|
|
209
|
-
` Pass --root <repo-root> or --cjs-dir <path> to override.\n`
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
process.exit(1);
|
|
213
|
-
}
|
|
214
|
-
if (!fs.existsSync(SDK_SRC)) {
|
|
215
|
-
// SDK tree was retired in ADR-0174 Phase 5.2. In default repo mode this
|
|
216
|
-
// lint becomes a no-op success; explicit --sdk-src remains fail-loud.
|
|
217
|
-
if (SDK_SRC_EXPLICIT) {
|
|
218
|
-
if (JSON_OUTPUT) {
|
|
219
|
-
emitJson({ ok: false, reason: 'sdk_src_missing', path: SDK_SRC });
|
|
220
|
-
} else {
|
|
221
|
-
process.stderr.write(
|
|
222
|
-
`lint-shared-module-handsync: SDK src dir not found: ${SDK_SRC}\n` +
|
|
223
|
-
` Pass --root <repo-root> or --sdk-src <path> to override.\n`
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
process.exit(1);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (JSON_OUTPUT) {
|
|
230
|
-
emitJson({
|
|
231
|
-
ok: true,
|
|
232
|
-
reason: 'sdk_retired',
|
|
233
|
-
cooperatingCount: 0,
|
|
234
|
-
backlogCount: 0,
|
|
235
|
-
warnings: [],
|
|
236
|
-
});
|
|
237
|
-
} else {
|
|
238
|
-
process.stdout.write(
|
|
239
|
-
'ok lint-shared-module-handsync: SDK source tree retired; no hand-sync pairs to lint.\n'
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
process.exit(0);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const sdkIndex = buildSdkIndex(SDK_SRC);
|
|
246
|
-
const cjsFiles = scanCjsFiles(CJS_DIR);
|
|
247
|
-
|
|
248
|
-
const errors = [];
|
|
249
|
-
const warnings = [];
|
|
250
|
-
|
|
251
|
-
function candidateTsPathsFor(relCjs, name) {
|
|
252
|
-
const byName = sdkIndex.has(name)
|
|
253
|
-
? sdkIndex
|
|
254
|
-
.get(name)
|
|
255
|
-
.map((p) => path.relative(ROOT, p).replace(/\\/g, '/'))
|
|
256
|
-
: [];
|
|
257
|
-
|
|
258
|
-
const declared = explicitTsByCjs.has(relCjs)
|
|
259
|
-
? Array.from(explicitTsByCjs.get(relCjs))
|
|
260
|
-
: [];
|
|
261
|
-
|
|
262
|
-
const declaredExisting = declared.filter((relTs) => {
|
|
263
|
-
const abs = path.join(ROOT, relTs);
|
|
264
|
-
return (
|
|
265
|
-
relTs.endsWith('.ts') &&
|
|
266
|
-
!relTs.endsWith('.generated.ts') &&
|
|
267
|
-
!relTs.endsWith('.test.ts') &&
|
|
268
|
-
fs.existsSync(abs) &&
|
|
269
|
-
fs.statSync(abs).isFile()
|
|
270
|
-
);
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
return Array.from(new Set([...byName, ...declaredExisting]));
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
for (const { name, absPath } of cjsFiles) {
|
|
277
|
-
// Compute relative CJS path and all declared/discovered TS candidates.
|
|
278
|
-
const relCjs = path.relative(ROOT, absPath).replace(/\\/g, '/');
|
|
279
|
-
const tsPaths = candidateTsPathsFor(relCjs, name);
|
|
280
|
-
if (tsPaths.length === 0) continue;
|
|
281
|
-
|
|
282
|
-
// Pair-aware matching, per ts sibling. Each ts candidate is classified
|
|
283
|
-
// independently against the allowlist so a partially-allowlisted set of
|
|
284
|
-
// siblings still surfaces the unauthorized ones. See #3632.
|
|
285
|
-
const unauthorizedTs = [];
|
|
286
|
-
const backlogTsForCjs = [];
|
|
287
|
-
for (const relTs of tsPaths) {
|
|
288
|
-
const pairKey = `${relCjs}::${relTs}`;
|
|
289
|
-
if (cooperatingPairs.has(pairKey)) continue;
|
|
290
|
-
if (migrateMap.has(pairKey)) {
|
|
291
|
-
backlogTsForCjs.push(relTs);
|
|
292
|
-
continue;
|
|
293
|
-
}
|
|
294
|
-
unauthorizedTs.push(relTs);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (unauthorizedTs.length > 0) {
|
|
298
|
-
errors.push({ relCjs, tsPaths: unauthorizedTs });
|
|
299
|
-
}
|
|
300
|
-
if (backlogTsForCjs.length > 0) {
|
|
301
|
-
const entry = migrateMap.get(`${relCjs}::${backlogTsForCjs[0]}`);
|
|
302
|
-
warnings.push({ relCjs, tsPaths: backlogTsForCjs, entry });
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// Count cjs files whose pair identity (cjs+ts) is on cooperatingSiblings.
|
|
307
|
-
// A file with multiple ts candidates is counted once if any pair matches.
|
|
308
|
-
const cooperatingCount = cjsFiles.filter((f) => {
|
|
309
|
-
const relCjs = path.relative(ROOT, f.absPath).replace(/\\/g, '/');
|
|
310
|
-
return candidateTsPathsFor(relCjs, f.name).some((relTs) =>
|
|
311
|
-
cooperatingPairs.has(`${relCjs}::${relTs}`)
|
|
312
|
-
);
|
|
313
|
-
}).length;
|
|
314
|
-
|
|
315
|
-
// -------------------------------------------------------------------------
|
|
316
|
-
// Report errors (exit 1)
|
|
317
|
-
// -------------------------------------------------------------------------
|
|
318
|
-
if (errors.length > 0) {
|
|
319
|
-
if (JSON_OUTPUT) {
|
|
320
|
-
emitJson({
|
|
321
|
-
ok: false,
|
|
322
|
-
reason: 'unauthorized_pairs',
|
|
323
|
-
errors,
|
|
324
|
-
warnings,
|
|
325
|
-
cooperatingCount,
|
|
326
|
-
});
|
|
327
|
-
} else {
|
|
328
|
-
process.stderr.write(
|
|
329
|
-
`\nERROR lint-shared-module-handsync: ${errors.length} unauthorized hand-sync pair(s) found.\n\n`
|
|
330
|
-
);
|
|
331
|
-
for (const { relCjs, tsPaths } of errors) {
|
|
332
|
-
process.stderr.write(` CJS: ${relCjs}\n`);
|
|
333
|
-
for (const ts of tsPaths) {
|
|
334
|
-
process.stderr.write(` TS: ${ts}\n`);
|
|
335
|
-
}
|
|
336
|
-
process.stderr.write('\n');
|
|
337
|
-
}
|
|
338
|
-
process.stderr.write(
|
|
339
|
-
'To resolve, choose one of:\n' +
|
|
340
|
-
' 1. Migrate to a Shared Module (preferred): create sdk/src/<name>/index.ts as the\n' +
|
|
341
|
-
' source-of-truth, write a generator script (sdk/scripts/gen-<name>.mjs), add a\n' +
|
|
342
|
-
' freshness check, and update CI. See docs/agents/cjs-sdk-seam.md for the pattern.\n' +
|
|
343
|
-
' 2. Add an explicit allowlist entry to scripts/shared-module-handsync-allowlist.json\n' +
|
|
344
|
-
' with a justification explaining why this pair is a legitimate cooperating sibling\n' +
|
|
345
|
-
' rather than a drift anti-pattern. Requires maintainer review via CODEOWNERS.\n\n'
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
|
-
process.exit(1);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// -------------------------------------------------------------------------
|
|
352
|
-
// Report warnings (no exit code change)
|
|
353
|
-
// -------------------------------------------------------------------------
|
|
354
|
-
if (warnings.length > 0 && WARN_ALL && !JSON_OUTPUT) {
|
|
355
|
-
process.stderr.write(
|
|
356
|
-
`\nWARNING lint-shared-module-handsync: ${warnings.length} known drift anti-pattern pair(s) in migrateMeBacklog.\n` +
|
|
357
|
-
`These are tracked for future Shared Module migration but do not block CI.\n\n`
|
|
358
|
-
);
|
|
359
|
-
for (const { relCjs, tsPaths, entry } of warnings) {
|
|
360
|
-
process.stderr.write(` CJS: ${relCjs}\n`);
|
|
361
|
-
for (const ts of tsPaths) {
|
|
362
|
-
process.stderr.write(` TS: ${ts}\n`);
|
|
363
|
-
}
|
|
364
|
-
process.stderr.write(` Tracked: ${entry.trackedIn}\n`);
|
|
365
|
-
process.stderr.write(` Hint: ${entry.justification}\n\n`);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// -------------------------------------------------------------------------
|
|
370
|
-
// Success
|
|
371
|
-
// -------------------------------------------------------------------------
|
|
372
|
-
if (JSON_OUTPUT) {
|
|
373
|
-
emitJson({
|
|
374
|
-
ok: true,
|
|
375
|
-
cooperatingCount,
|
|
376
|
-
backlogCount: warnings.length,
|
|
377
|
-
warnings,
|
|
378
|
-
});
|
|
379
|
-
} else {
|
|
380
|
-
process.stdout.write(
|
|
381
|
-
`ok lint-shared-module-handsync: no unauthorized hand-sync pairs found` +
|
|
382
|
-
` (${cooperatingCount} cooperating sibling(s), ${warnings.length} backlog pair(s))\n`
|
|
383
|
-
);
|
|
384
|
-
}
|
|
385
|
-
process.exit(0);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
main();
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"_comment": "Allowlist for scripts/lint-shared-module-handsync.cjs — Phase 6 of #3524 (#3575). Two categories: cooperatingSiblings (legitimate pairs, lint accepts silently) and migrateMeBacklog (known drift anti-patterns, lint warns but does not fail). All entries require cjs + ts path + classification + justification.",
|
|
4
|
-
"cooperatingSiblings": [
|
|
5
|
-
{
|
|
6
|
-
"cjs": "get-shit-done/bin/lib/active-workstream-store.cjs",
|
|
7
|
-
"ts": "sdk/src/query/active-workstream-store.ts",
|
|
8
|
-
"classification": "cooperating-sibling",
|
|
9
|
-
"justification": "CJS manages filesystem-backed workstream store; SDK layer wraps via Adapter for query dispatch. Different responsibilities, not drift."
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"cjs": "get-shit-done/bin/lib/config-schema.cjs",
|
|
13
|
-
"ts": "sdk/src/query/config-schema.ts",
|
|
14
|
-
"classification": "cooperating-sibling",
|
|
15
|
-
"justification": "SDK config-schema.ts is the generated source-of-truth derived from sdk/shared/config-schema.manifest.json (Phase 2/#3540). CJS config-schema.cjs is the Adapter that reads from that manifest. Not a hand-sync pair; freshness check enforces alignment."
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"cjs": "get-shit-done/bin/lib/frontmatter.cjs",
|
|
19
|
-
"ts": "sdk/src/query/frontmatter.ts",
|
|
20
|
-
"classification": "cooperating-sibling",
|
|
21
|
-
"justification": "CJS implements full frontmatter parsing/mutation; SDK frontmatter.ts is the native SDK query handler delegating to the CJS runtime via the seam bridge. Not duplicating logic."
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
"cjs": "get-shit-done/bin/lib/init.cjs",
|
|
25
|
-
"ts": "sdk/src/query/init.ts",
|
|
26
|
-
"classification": "cooperating-sibling",
|
|
27
|
-
"justification": "CJS init.cjs is the authoritative initializer; SDK init.ts provides the native handler layer for the SDK query seam. Phase 5.2+ will migrate remaining subcommands, but current architecture is intentional."
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"cjs": "get-shit-done/bin/lib/phase.cjs",
|
|
31
|
-
"ts": "sdk/src/query/phase.ts",
|
|
32
|
-
"classification": "cooperating-sibling",
|
|
33
|
-
"justification": "CJS phase.cjs implements sync mutation handlers (phaseAdd, phaseInsert, phaseRemove, phaseComplete) and query handlers with sync I/O; SDK phase.ts provides the native async query handler. The async mutation handlers (phase-lifecycle.ts) and pure policy helpers (phase-lifecycle-policy.ts) are I/O-bound or pure and remain per-side (ADR-3524 §4). Issue #4 fix: phase.cjs cmdPhaseComplete now consumes pure helpers from phase-lifecycle.generated.cjs (generated from sdk/src/query/phase-lifecycle.ts) for idempotent Completed Phases counting and clamped percent. *.generated.cjs files are excluded from lint scanner; see sdk/scripts/check-phase-lifecycle-fresh.mjs for freshness enforcement."
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"cjs": "get-shit-done/bin/lib/phase-lifecycle.cjs",
|
|
37
|
-
"ts": "sdk/src/query/phase-lifecycle.ts",
|
|
38
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
39
|
-
"justification": "CJS phase-lifecycle.cjs is the pure helper module consumed by phase.cjs; sdk/src/query/phase-lifecycle.ts remains the typed source counterpart. This pair is intentionally tracked as adapter-over-module rather than an unauthorized hand-sync pair."
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
"cjs": "get-shit-done/bin/lib/profile-output.cjs",
|
|
43
|
-
"ts": "sdk/src/query/profile-output.ts",
|
|
44
|
-
"classification": "cooperating-sibling",
|
|
45
|
-
"justification": "CJS profile-output.cjs handles profiling output rendering; SDK profile-output.ts is the corresponding SDK query handler. Separate responsibilities across the seam."
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"cjs": "get-shit-done/bin/lib/roadmap.cjs",
|
|
49
|
-
"ts": "sdk/src/query/roadmap.ts",
|
|
50
|
-
"classification": "cooperating-sibling",
|
|
51
|
-
"justification": "CJS roadmap.cjs is the full roadmap implementation; SDK roadmap.ts provides the native handler for SDK query dispatch. Phase 5.2+ candidate."
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"cjs": "get-shit-done/bin/lib/state.cjs",
|
|
55
|
-
"ts": "sdk/src/query/state.ts",
|
|
56
|
-
"classification": "cooperating-sibling",
|
|
57
|
-
"justification": "CJS state.cjs is the full state implementation; SDK state.ts routes known subcommands via executeForCjs (Phase 5.0/#3558, Phase 5.1/#3574). Intentional seam delegation pattern."
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
"cjs": "get-shit-done/bin/lib/state-document.cjs",
|
|
61
|
-
"ts": "sdk/src/state/index.ts",
|
|
62
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
63
|
-
"justification": "CJS state-document.cjs is a thin Adapter over get-shit-done/bin/lib/state-document.generated.cjs. That generated artifact is emitted from sdk/src/state/index.ts by sdk/scripts/gen-state-document.ts; freshness is enforced by sdk/scripts/check-state-document-fresh.mjs."
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"cjs": "get-shit-done/bin/lib/template.cjs",
|
|
67
|
-
"ts": "sdk/src/query/template.ts",
|
|
68
|
-
"classification": "cooperating-sibling",
|
|
69
|
-
"justification": "CJS template.cjs handles template operations; SDK template.ts is the corresponding SDK native handler. Separate responsibilities across the seam."
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
"cjs": "get-shit-done/bin/lib/uat.cjs",
|
|
73
|
-
"ts": "sdk/src/query/uat.ts",
|
|
74
|
-
"classification": "cooperating-sibling",
|
|
75
|
-
"justification": "CJS uat.cjs implements UAT workflows; SDK uat.ts provides the SDK query handler layer. Separate responsibilities."
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"cjs": "get-shit-done/bin/lib/verify.cjs",
|
|
79
|
-
"ts": "sdk/src/query/verify.ts",
|
|
80
|
-
"classification": "cooperating-sibling",
|
|
81
|
-
"justification": "CJS verify.cjs is the full verify implementation; SDK verify.ts provides the native handler. Phase 5.2+ candidate for further delegation. Check 8 (W006/W007) helpers now generated from sdk/src/query/validate.ts via sdk/scripts/gen-validate.mjs (issue #6); freshness check: sdk/scripts/check-validate-fresh.mjs."
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
"cjs": "get-shit-done/bin/lib/validate.cjs",
|
|
85
|
-
"ts": "sdk/src/query/validate.ts",
|
|
86
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
87
|
-
"justification": "CJS validate.cjs provides the pure validation helpers consumed by verify.cjs while sdk/src/query/validate.ts is the SDK handler-side counterpart. Keep this explicit adapter pair allowlisted to avoid false-positive hand-sync lint failures."
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
"cjs": "get-shit-done/bin/lib/workstream.cjs",
|
|
91
|
-
"ts": "sdk/src/query/workstream.ts",
|
|
92
|
-
"classification": "cooperating-sibling",
|
|
93
|
-
"justification": "CJS workstream.cjs handles workstream management; SDK workstream.ts provides the SDK query handler. Workstream support inside sync bridge is an open follow-up item."
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
"cjs": "get-shit-done/bin/lib/workstream-inventory.cjs",
|
|
97
|
-
"ts": "sdk/src/query/workstream-inventory.ts",
|
|
98
|
-
"classification": "cooperating-sibling",
|
|
99
|
-
"justification": "CJS workstream-inventory.cjs is the generated Adapter for the workstream-inventory Shared Module (Phase 3/#3548). SDK workstream-inventory.ts is the source-of-truth query handler. Freshness check enforces alignment."
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
"cjs": "get-shit-done/bin/lib/config.cjs",
|
|
103
|
-
"ts": "sdk/src/config.ts",
|
|
104
|
-
"classification": "CJS-CLI-ONLY",
|
|
105
|
-
"justification": "Phase 2 (#3536) already migrated CONFIG_DEFAULTS and loadConfig/mergeDefaults to the Configuration Module and sdk/src/config.ts. What remains in config.cjs is exclusively CLI command handlers (cmdConfigGet, cmdConfigSet, cmdConfigNewProject, cmdConfigEnsureSection, cmdConfigSetModelProfile, cmdConfigPath, cmdMigrateConfig, buildNewProjectConfig, setConfigValue, ensureConfigFile) that depend on CJS-only APIs (withPlanningLock, platformWriteSync/ReadSync/EnsureDir, sync fs ops, process.exit). sdk/src/config.ts provides only the async loadConfig/mergeDefaults SDK layer. The two files serve disjoint surfaces with no logical overlap — not a hand-sync drift anti-pattern."
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
"cjs": "get-shit-done/bin/lib/config.cjs",
|
|
109
|
-
"ts": "sdk/src/config/index.ts",
|
|
110
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
111
|
-
"justification": "sdk/src/config/index.ts is the Configuration Module source-of-truth; CJS config.cjs consumes its generated Adapter through core/config-schema integration. This is an intentional seam relationship, not manual hand-sync."
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
"cjs": "get-shit-done/bin/lib/state.cjs",
|
|
115
|
-
"ts": "sdk/src/state/index.ts",
|
|
116
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
117
|
-
"justification": "sdk/src/state/index.ts is the STATE.md Document Module source-of-truth that emits get-shit-done/bin/lib/state-document.generated.cjs. state.cjs consumes that generated module as an Adapter dependency; basename overlap is intentional and not a duplicated implementation."
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
"cjs": "get-shit-done/bin/lib/intel.cjs",
|
|
121
|
-
"ts": "sdk/src/query/intel.ts",
|
|
122
|
-
"classification": "cooperating-sibling",
|
|
123
|
-
"justification": "CJS intel.cjs is the synchronous runtime implementation used by gsd-tools.cjs; sdk/src/query/intel.ts is the async QueryHandler port for the SDK query seam (explicitly documented as a port in its file header). The two files intentionally diverge on INTEL_FILES naming (CJS: file-roles.json/api-map.json/dependency-graph.json/arch-decisions.json; SDK: files.json/apis.json/deps.json/arch.md) — existing CJS tests are locked to the old naming. Not a hand-sync drift pattern; separate runtime responsibilities across the seam."
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
"cjs": "get-shit-done/bin/lib/model-catalog.cjs",
|
|
127
|
-
"ts": "sdk/src/model-catalog.ts",
|
|
128
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
129
|
-
"justification": "Both files read from sdk/shared/model-catalog.json (ADR-0003 precedent) as independent consumers of the shared manifest. CJS exposes VALID_AGENT_TIERS, MODEL_ALIAS_MAP, RUNTIME_PROFILE_MAP, KNOWN_RUNTIMES, RUNTIMES_WITH_REASONING_EFFORT, nextTier, formatAgentToModelMapAsTable for core.cjs and model-profiles.cjs consumers. SDK exposes resolveRuntimeTierDefault, runtimesWithReasoningEffort for session-runner.ts and query handlers. The shared JSON is the single source-of-truth; both adapters derive their exports from it without duplicating any logic between themselves."
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
"cjs": "get-shit-done/bin/lib/plan-scan.cjs",
|
|
133
|
-
"ts": "sdk/src/query/plan-scan.ts",
|
|
134
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
135
|
-
"justification": "CJS plan-scan.cjs is the generated Adapter reading from sdk/src/query/plan-scan.ts Shared Module (Phase 6/#3575). SDK plan-scan.ts is the source-of-truth. Freshness check (check-plan-scan-fresh.mjs) enforces alignment."
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
"cjs": "get-shit-done/bin/lib/secrets.cjs",
|
|
139
|
-
"ts": "sdk/src/query/secrets.ts",
|
|
140
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
141
|
-
"justification": "CJS secrets.cjs is the generated Adapter reading from sdk/src/query/secrets.ts Shared Module (Phase 6/#3575). SDK secrets.ts is the source-of-truth. Freshness check (check-secrets-fresh.mjs) enforces alignment."
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
"cjs": "get-shit-done/bin/lib/schema-detect.cjs",
|
|
145
|
-
"ts": "sdk/src/query/schema-detect.ts",
|
|
146
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
147
|
-
"justification": "CJS schema-detect.cjs is the generated Adapter reading from sdk/src/query/schema-detect.ts Shared Module (Phase 6/#3575). SDK schema-detect.ts is the source-of-truth. Generated CJS adds detectSchemaOrm compat export (not in SDK) and exports SCHEMA_PATTERNS/ORM_INFO for backward compatibility. Freshness check (check-schema-detect-fresh.mjs) enforces alignment."
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
"cjs": "get-shit-done/bin/lib/decisions.cjs",
|
|
151
|
-
"ts": "sdk/src/query/decisions.ts",
|
|
152
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
153
|
-
"justification": "Phase 6 (#3575): CJS decisions.cjs is the generated Adapter reading from sdk/src/query/decisions.ts Shared Module. SDK source-of-truth; regex aligned to accept alphanumeric IDs (D-INFRA-01). CJS callers (gap-checker.cjs) use {id, text} subset; extra fields {category, tags, trackable} are present but ignored. Freshness check (check-decisions-fresh.mjs) enforces alignment."
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
"cjs": "get-shit-done/bin/lib/workstream-name-policy.cjs",
|
|
157
|
-
"ts": "sdk/src/workstream-name-policy.ts",
|
|
158
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
159
|
-
"justification": "Phase 6 (#3575): CJS workstream-name-policy.cjs is the generated Adapter reading from sdk/src/workstream-name-policy.ts Shared Module. SDK source-of-truth now exports all three functions used by CJS callers (toWorkstreamSlug, hasInvalidPathSegment, isValidActiveWorkstreamName) plus validateWorkstreamName alias. Freshness check (check-workstream-name-policy-fresh.mjs) enforces alignment."
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
"cjs": "get-shit-done/bin/lib/runtime-name-policy.cjs",
|
|
163
|
-
"ts": "sdk/src/runtime-name-policy.ts",
|
|
164
|
-
"classification": "ADAPTER-OVER-MODULE",
|
|
165
|
-
"justification": "Both CJS and SDK runtime-name adapters consume sdk/shared/runtime-aliases.manifest.json as the single source of truth for alias canonicalization. This pair is an intentional seam-level adapter split, not a drift-prone hand-sync anti-pattern."
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
"cjs": "get-shit-done/bin/lib/prompt-budget.cjs",
|
|
169
|
-
"ts": "sdk/src/query/prompt-budget.ts",
|
|
170
|
-
"classification": "cooperating-sibling",
|
|
171
|
-
"justification": "CJS prompt-budget.cjs provides the applyBudget implementation used by gsd-tools.cjs case 'prompt-budget'. SDK prompt-budget.ts is the native QueryHandler port for gsd-sdk query dispatch (#3081). The SDK handler ports the pure budget logic and adds CLI arg parsing / file I/O directly, satisfying the registry-integration drift-guard without duplicating shared state."
|
|
172
|
-
}
|
|
173
|
-
],
|
|
174
|
-
"migrateMeBacklog": [
|
|
175
|
-
{
|
|
176
|
-
"cjs": "get-shit-done/bin/lib/verify.cjs",
|
|
177
|
-
"ts": "sdk/src/query/validate.ts",
|
|
178
|
-
"classification": "drift-anti-pattern",
|
|
179
|
-
"justification": "Cross-name cooperating pair where validate policy changes can drift from verify checks; keep explicitly visible until Shared Module extraction removes hand-sync risk.",
|
|
180
|
-
"trackedIn": "#11"
|
|
181
|
-
}
|
|
182
|
-
]
|
|
183
|
-
}
|