cohorte 3.0.0-dev.3 → 3.0.0-dev.5
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/assets/manifest.json +1 -1
- package/dist/bundle-manifest.json +14 -14
- package/dist/chunks/{auth-RuhYgTI7.mjs → auth-Dnlksuo5.mjs} +3 -3
- package/dist/chunks/{auth-RuhYgTI7.mjs.map → auth-Dnlksuo5.mjs.map} +1 -1
- package/dist/chunks/{compose-D8rro98O.mjs → compose-CKo_q39e.mjs} +4 -4
- package/dist/chunks/{compose-D8rro98O.mjs.map → compose-CKo_q39e.mjs.map} +1 -1
- package/dist/chunks/{discover-eS01-me1.mjs → discover-BJMwXyGL.mjs} +2 -2
- package/dist/chunks/{discover-eS01-me1.mjs.map → discover-BJMwXyGL.mjs.map} +1 -1
- package/dist/chunks/{init-BUnzIkeE.mjs → init-CP6puNbE.mjs} +2 -2
- package/dist/chunks/{init-BUnzIkeE.mjs.map → init-CP6puNbE.mjs.map} +1 -1
- package/dist/chunks/{reconcile-Bhy3IIYo.mjs → reconcile-czNaLOP6.mjs} +2 -2
- package/dist/chunks/{reconcile-Bhy3IIYo.mjs.map → reconcile-czNaLOP6.mjs.map} +1 -1
- package/dist/chunks/{scan-8Gy_B6kI.mjs → scan-C5uDr7Yq.mjs} +51 -6
- package/dist/chunks/scan-C5uDr7Yq.mjs.map +1 -0
- package/dist/cli.mjs +6 -6
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/scan-8Gy_B6kI.mjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { N as errorOf, j as CohorteError } from "./src-Cu3TxNob.mjs";
|
|
2
2
|
import "./src-CmFjh4M0.mjs";
|
|
3
|
-
import { t as scanRepository } from "./scan-
|
|
3
|
+
import { t as scanRepository } from "./scan-C5uDr7Yq.mjs";
|
|
4
4
|
//#region src/commands/discover/index.ts
|
|
5
5
|
const discover = {
|
|
6
6
|
verb: "discover",
|
|
@@ -18,4 +18,4 @@ const discover = {
|
|
|
18
18
|
//#endregion
|
|
19
19
|
export { discover as default };
|
|
20
20
|
|
|
21
|
-
//# sourceMappingURL=discover-
|
|
21
|
+
//# sourceMappingURL=discover-BJMwXyGL.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover-
|
|
1
|
+
{"version":3,"file":"discover-BJMwXyGL.mjs","names":[],"sources":["../../../../apps/cli/src/commands/discover/index.ts"],"sourcesContent":["import { CohorteError, errorOf } from '@cohorte/base';\nimport { scanRepository } from '@cohorte/project-model';\nimport type { CommandModule } from '../../contract/index.ts';\n\nconst discover: CommandModule = {\n verb: 'discover',\n async run(ctx, args) {\n if (args.positionals.includes('--semantic')) {\n throw new CohorteError(\n errorOf('configuration/phase-not-available', 'semantic discovery is not available in V3.0'),\n );\n }\n const model = await scanRepository(ctx.cwd, { clock: ctx.clock, toolVersion: '3.0.0' });\n if (args.json) ctx.stdio.stdout.write(`${JSON.stringify(model)}\\n`);\n else ctx.stdio.stdout.write(`${JSON.stringify(model, null, 2)}\\n`);\n return 0;\n },\n};\n\nexport default discover;\n"],"mappings":";;;;AAIA,MAAM,WAA0B;CAC9B,MAAM;CACN,MAAM,IAAI,KAAK,MAAM;EACnB,IAAI,KAAK,YAAY,SAAS,YAAY,GACxC,MAAM,IAAI,aACR,QAAQ,qCAAqC,6CAA6C,CAC5F;EAEF,MAAM,QAAQ,MAAM,eAAe,IAAI,KAAK;GAAE,OAAO,IAAI;GAAO,aAAa;EAAQ,CAAC;EACtF,IAAI,KAAK,MAAM,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,UAAU,KAAK,EAAE,GAAG;OAC7D,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,GAAG;EACjE,OAAO;CACT;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as applyV2Import, i as planInit, o as exportV2, r as applyInit, s as planV2Import } from "./src-CmFjh4M0.mjs";
|
|
2
|
-
import { t as scanRepository } from "./scan-
|
|
2
|
+
import { t as scanRepository } from "./scan-C5uDr7Yq.mjs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
//#region src/commands/init/index.ts
|
|
5
5
|
const init = {
|
|
@@ -60,4 +60,4 @@ const init = {
|
|
|
60
60
|
//#endregion
|
|
61
61
|
export { init as default };
|
|
62
62
|
|
|
63
|
-
//# sourceMappingURL=init-
|
|
63
|
+
//# sourceMappingURL=init-CP6puNbE.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-
|
|
1
|
+
{"version":3,"file":"init-CP6puNbE.mjs","names":[],"sources":["../../../../apps/cli/src/commands/init/index.ts"],"sourcesContent":["// apps/cli/src/commands/init/index.ts — DESIGN §9 verb `init` (PLAN §3 rule 3 \"later units fill\n// stub files that lie inside their owned paths; they never edit ... the registry\"). Wave-0 stub: exits with the\n// documented not-available error (spec 24 `configuration/phase-not-available`); filled by the Wave-4/5\n// unit that owns `apps/cli/src/commands/init/**`.\nimport { resolve } from 'node:path';\nimport { applyInit, applyV2Import, exportV2, planInit, planV2Import, scanRepository } from '@cohorte/project-model';\nimport type { CommandModule } from '../../contract/index.ts';\n\nconst init: CommandModule = {\n verb: 'init',\n async run(ctx, args) {\n const fromV2 = args.positionals.indexOf('--from-v2');\n const exportV2At = args.positionals.indexOf('--export-v2');\n const optionValues = new Set(\n [fromV2, exportV2At]\n .filter((index) => index !== -1)\n .map((index) => args.positionals[index + 1])\n .filter((value): value is string => value !== undefined),\n );\n const requestedRoot = args.positionals.find((value) => !value.startsWith('--') && !optionValues.has(value));\n const root = requestedRoot === undefined ? ctx.cwd : resolve(ctx.cwd, requestedRoot);\n if (fromV2 !== -1) {\n const bundle = args.positionals[fromV2 + 1];\n if (!bundle) throw new Error('configuration/import-invalid: init --from-v2 requires a bundle directory');\n const model = await scanRepository(root, { clock: ctx.clock, toolVersion: '3.0.0-v2-import' });\n const plan = await planV2Import(resolve(ctx.cwd, bundle), root, { model });\n if (!args.positionals.includes('--yes')) {\n ctx.stdio.stdout.write(`${JSON.stringify(plan, null, 2)}\\n`);\n return plan.conflicts.length ? 3 : 0;\n }\n const result = await applyV2Import(plan, {\n confirm: args.positionals.includes('--yes'),\n backupRoot: resolve(root, '..', '.cohorte-migration-backups'),\n });\n ctx.stdio.stdout.write(`${JSON.stringify(result)}\\n`);\n return 0;\n }\n if (exportV2At !== -1) {\n const destination = args.positionals[exportV2At + 1];\n if (!destination) throw new Error('configuration/import-invalid: init --export-v2 requires a destination');\n const result = await exportV2({ root, destination: resolve(ctx.cwd, destination) });\n ctx.stdio.stdout.write(`${JSON.stringify(result)}\\n`);\n return result.manifest.warnings.some((item) => item.blocking) ? 3 : 0;\n }\n const model = await scanRepository(root, { clock: ctx.clock, toolVersion: '3.0.0' });\n const plan = await planInit({ root, model, cohorteVersion: '3.0.0' });\n if (args.positionals.includes('--plan') || args.json) {\n ctx.stdio.stdout.write(`${JSON.stringify(plan)}\\n`);\n return 0;\n }\n const result = await applyInit(plan);\n ctx.stdio.stdout.write(`written: ${result.written.join(', ') || 'none'}\\n`);\n return 0;\n },\n};\n\nexport default init;\n"],"mappings":";;;;AAQA,MAAM,OAAsB;CAC1B,MAAM;CACN,MAAM,IAAI,KAAK,MAAM;EACnB,MAAM,SAAS,KAAK,YAAY,QAAQ,WAAW;EACnD,MAAM,aAAa,KAAK,YAAY,QAAQ,aAAa;EACzD,MAAM,eAAe,IAAI,IACvB,CAAC,QAAQ,UAAU,CAAC,CACjB,QAAQ,UAAU,UAAU,EAAE,CAAC,CAC/B,KAAK,UAAU,KAAK,YAAY,QAAQ,EAAE,CAAC,CAC3C,QAAQ,UAA2B,UAAU,KAAA,CAAS,CAC3D;EACA,MAAM,gBAAgB,KAAK,YAAY,MAAM,UAAU,CAAC,MAAM,WAAW,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC;EAC1G,MAAM,OAAO,kBAAkB,KAAA,IAAY,IAAI,MAAM,QAAQ,IAAI,KAAK,aAAa;EACnF,IAAI,WAAW,IAAI;GACjB,MAAM,SAAS,KAAK,YAAY,SAAS;GACzC,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,0EAA0E;GACvG,MAAM,QAAQ,MAAM,eAAe,MAAM;IAAE,OAAO,IAAI;IAAO,aAAa;GAAkB,CAAC;GAC7F,MAAM,OAAO,MAAM,aAAa,QAAQ,IAAI,KAAK,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC;GACzE,IAAI,CAAC,KAAK,YAAY,SAAS,OAAO,GAAG;IACvC,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,EAAE,GAAG;IAC3D,OAAO,KAAK,UAAU,SAAS,IAAI;GACrC;GACA,MAAM,SAAS,MAAM,cAAc,MAAM;IACvC,SAAS,KAAK,YAAY,SAAS,OAAO;IAC1C,YAAY,QAAQ,MAAM,MAAM,4BAA4B;GAC9D,CAAC;GACD,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,EAAE,GAAG;GACpD,OAAO;EACT;EACA,IAAI,eAAe,IAAI;GACrB,MAAM,cAAc,KAAK,YAAY,aAAa;GAClD,IAAI,CAAC,aAAa,MAAM,IAAI,MAAM,uEAAuE;GACzG,MAAM,SAAS,MAAM,SAAS;IAAE;IAAM,aAAa,QAAQ,IAAI,KAAK,WAAW;GAAE,CAAC;GAClF,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,EAAE,GAAG;GACpD,OAAO,OAAO,SAAS,SAAS,MAAM,SAAS,KAAK,QAAQ,IAAI,IAAI;EACtE;EACA,MAAM,QAAQ,MAAM,eAAe,MAAM;GAAE,OAAO,IAAI;GAAO,aAAa;EAAQ,CAAC;EACnF,MAAM,OAAO,MAAM,SAAS;GAAE;GAAM;GAAO,gBAAgB;EAAQ,CAAC;EACpE,IAAI,KAAK,YAAY,SAAS,QAAQ,KAAK,KAAK,MAAM;GACpD,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,UAAU,IAAI,EAAE,GAAG;GAClD,OAAO;EACT;EACA,MAAM,SAAS,MAAM,UAAU,IAAI;EACnC,IAAI,MAAM,OAAO,MAAM,YAAY,OAAO,QAAQ,KAAK,IAAI,KAAK,OAAO,GAAG;EAC1E,OAAO;CACT;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { s as DEFAULT_CONFIG } from "./schema-C9QbUW4H.mjs";
|
|
2
2
|
import { l as deriveDesiredState, n as planReconcile, t as applyReconcile } from "./src-CmFjh4M0.mjs";
|
|
3
|
-
import { t as scanRepository } from "./scan-
|
|
3
|
+
import { t as scanRepository } from "./scan-C5uDr7Yq.mjs";
|
|
4
4
|
//#region src/commands/reconcile/index.ts
|
|
5
5
|
const reconcile = {
|
|
6
6
|
verb: "reconcile",
|
|
@@ -47,4 +47,4 @@ const reconcile = {
|
|
|
47
47
|
//#endregion
|
|
48
48
|
export { reconcile as default };
|
|
49
49
|
|
|
50
|
-
//# sourceMappingURL=reconcile-
|
|
50
|
+
//# sourceMappingURL=reconcile-czNaLOP6.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile-
|
|
1
|
+
{"version":3,"file":"reconcile-czNaLOP6.mjs","names":[],"sources":["../../../../apps/cli/src/commands/reconcile/index.ts"],"sourcesContent":["import { DEFAULT_CONFIG } from '@cohorte/config/schema';\nimport { applyReconcile, deriveDesiredState, planReconcile, scanRepository } from '@cohorte/project-model';\nimport type { CommandModule } from '../../contract/index.ts';\n\nconst reconcile: CommandModule = {\n verb: 'reconcile',\n async run(ctx, args) {\n const model = await scanRepository(ctx.cwd, { clock: ctx.clock, toolVersion: '3.0.0' });\n const plan = await planReconcile({\n root: ctx.cwd,\n scan: (root) => scanRepository(root, { clock: ctx.clock, toolVersion: '3.0.0' }),\n cohorteVersion: '3.0.0',\n clock: ctx.clock,\n });\n if (args.positionals.includes('--apply')) {\n const result = await applyReconcile({\n root: ctx.cwd,\n plan,\n desired: deriveDesiredState({ model, config: DEFAULT_CONFIG, cohorteVersion: '3.0.0', skills: {} }),\n backup: !args.positionals.includes('--no-backup'),\n clock: ctx.clock,\n });\n if (args.json) ctx.stdio.stdout.write(`${JSON.stringify({ plan, result })}\\n`);\n else ctx.stdio.stdout.write(`applied: ${result.applied.join(', ') || 'none'}\\n`);\n return 0;\n }\n if (!args.positionals.includes('--plan')) return 2;\n if (args.json) ctx.stdio.stdout.write(`${JSON.stringify(plan)}\\n`);\n else ctx.stdio.stdout.write(`${plan.operations.length} operation(s) planned\\n`);\n return 0;\n },\n};\n\nexport default reconcile;\n"],"mappings":";;;;AAIA,MAAM,YAA2B;CAC/B,MAAM;CACN,MAAM,IAAI,KAAK,MAAM;EACnB,MAAM,QAAQ,MAAM,eAAe,IAAI,KAAK;GAAE,OAAO,IAAI;GAAO,aAAa;EAAQ,CAAC;EACtF,MAAM,OAAO,MAAM,cAAc;GAC/B,MAAM,IAAI;GACV,OAAO,SAAS,eAAe,MAAM;IAAE,OAAO,IAAI;IAAO,aAAa;GAAQ,CAAC;GAC/E,gBAAgB;GAChB,OAAO,IAAI;EACb,CAAC;EACD,IAAI,KAAK,YAAY,SAAS,SAAS,GAAG;GACxC,MAAM,SAAS,MAAM,eAAe;IAClC,MAAM,IAAI;IACV;IACA,SAAS,mBAAmB;KAAE;KAAO,QAAQ;KAAgB,gBAAgB;KAAS,QAAQ,CAAC;IAAE,CAAC;IAClG,QAAQ,CAAC,KAAK,YAAY,SAAS,aAAa;IAChD,OAAO,IAAI;GACb,CAAC;GACD,IAAI,KAAK,MAAM,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,UAAU;IAAE;IAAM;GAAO,CAAC,EAAE,GAAG;QACxE,IAAI,MAAM,OAAO,MAAM,YAAY,OAAO,QAAQ,KAAK,IAAI,KAAK,OAAO,GAAG;GAC/E,OAAO;EACT;EACA,IAAI,CAAC,KAAK,YAAY,SAAS,QAAQ,GAAG,OAAO;EACjD,IAAI,KAAK,MAAM,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,UAAU,IAAI,EAAE,GAAG;OAC5D,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,WAAW,OAAO,wBAAwB;EAC9E,OAAO;CACT;AACF"}
|
|
@@ -29,6 +29,55 @@ function field(value, detector, sources, className = "observed") {
|
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
+
const WORKSPACE_ROOTS = /* @__PURE__ */ new Set([
|
|
33
|
+
"apps",
|
|
34
|
+
"packages",
|
|
35
|
+
"services",
|
|
36
|
+
"modules",
|
|
37
|
+
"libs",
|
|
38
|
+
"plugins"
|
|
39
|
+
]);
|
|
40
|
+
function surfaceId(path) {
|
|
41
|
+
return path.replaceAll("/", "-").replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 128);
|
|
42
|
+
}
|
|
43
|
+
const topLevelOf = (file) => file.split("/")[0];
|
|
44
|
+
/**
|
|
45
|
+
* Finds stable, implementation-sized boundaries without making semantic guesses. A package manifest is the
|
|
46
|
+
* strongest local signal; for repositories without manifests we fall back to top-level directories.
|
|
47
|
+
*/
|
|
48
|
+
function discoverSurfacePaths(files) {
|
|
49
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
50
|
+
const packageDirs = files.filter((file) => file.endsWith("/package.json")).map((file) => file.slice(0, -13)).filter((dir) => dir.includes("/"));
|
|
51
|
+
for (const dir of packageDirs) {
|
|
52
|
+
const first = topLevelOf(dir);
|
|
53
|
+
if (first === void 0 || !WORKSPACE_ROOTS.has(first)) continue;
|
|
54
|
+
const glob = `${dir}/**`;
|
|
55
|
+
candidates.set(surfaceId(dir), {
|
|
56
|
+
glob,
|
|
57
|
+
sources: files.filter((file) => file === dir || file.startsWith(`${dir}/`))
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
const topLevelDirectories = new Set(files.filter((file) => file.includes("/")).map(topLevelOf).filter((name) => Boolean(name && !name.startsWith("."))));
|
|
61
|
+
for (const topLevel of [...topLevelDirectories].sort()) {
|
|
62
|
+
if (WORKSPACE_ROOTS.has(topLevel)) continue;
|
|
63
|
+
const glob = `${topLevel}/**`;
|
|
64
|
+
candidates.set(topLevel, {
|
|
65
|
+
glob,
|
|
66
|
+
sources: files.filter((file) => file.startsWith(`${topLevel}/`))
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (candidates.size === 0) {
|
|
70
|
+
const topLevelDirectoriesOnly = new Set(files.filter((file) => file.includes("/")).map(topLevelOf).filter((name) => Boolean(name && !name.startsWith("."))));
|
|
71
|
+
for (const topLevel of [...topLevelDirectoriesOnly].sort()) {
|
|
72
|
+
const glob = `${topLevel}/**`;
|
|
73
|
+
candidates.set(topLevel, {
|
|
74
|
+
glob,
|
|
75
|
+
sources: files.filter((file) => file.startsWith(`${topLevel}/`))
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return candidates;
|
|
80
|
+
}
|
|
32
81
|
async function scanRepository(root, options) {
|
|
33
82
|
const files = await filesUnder(root);
|
|
34
83
|
const packagePath = join(root, "package.json");
|
|
@@ -69,11 +118,7 @@ async function scanRepository(root, options) {
|
|
|
69
118
|
}
|
|
70
119
|
const testLocations = files.filter((file) => /(^|\/)(test|tests|__tests__)(\/|$)|\.(test|spec)\./u.test(file));
|
|
71
120
|
const surfaces = {};
|
|
72
|
-
const
|
|
73
|
-
for (const name of topLevel.sort()) {
|
|
74
|
-
const paths = files.filter((file) => file === name || file.startsWith(`${name}/`));
|
|
75
|
-
if (paths.length) surfaces[name.replace(/[^A-Za-z0-9_.-]/g, "_")] = { paths: field([`${name}/**`], "workspace-layout", paths) };
|
|
76
|
-
}
|
|
121
|
+
for (const [id, candidate] of discoverSurfacePaths(files)) surfaces[id] = { paths: field([candidate.glob], "workspace-layout", candidate.sources) };
|
|
77
122
|
const id = pkg.name?.replace(/^@[^/]+\//u, "") ?? (relative(process.cwd(), root).replace(/[^A-Za-z0-9_.-]/g, "_") || "project");
|
|
78
123
|
const unknowns = locks.length > 1 ? [{
|
|
79
124
|
id: "package-manager",
|
|
@@ -119,4 +164,4 @@ async function scanRepository(root, options) {
|
|
|
119
164
|
//#endregion
|
|
120
165
|
export { scanRepository as t };
|
|
121
166
|
|
|
122
|
-
//# sourceMappingURL=scan-
|
|
167
|
+
//# sourceMappingURL=scan-C5uDr7Yq.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-C5uDr7Yq.mjs","names":[],"sources":["../../../../packages/project-model/src/scan/index.ts"],"sourcesContent":["// Deterministic repository scan: bounded filesystem observations, never guessed semantics.\n\nimport { readdir, readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { Clock } from '@cohorte/base';\nimport type { ProjectModel } from '../contract.ts';\n\nexport interface ScanOptions {\n clock: Clock;\n /** stamped into `provenance.toolVersion` */\n toolVersion: string;\n}\n\nasync function filesUnder(root: string): Promise<string[]> {\n const found: string[] = [];\n const visit = async (dir: string): Promise<void> => {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n if (\n entry.name === '.git' ||\n entry.name === 'node_modules' ||\n entry.name === '.cohorte' ||\n entry.name === '.pi' ||\n entry.name === '.build' ||\n entry.name === 'dist' ||\n entry.name === 'coverage'\n )\n continue;\n const path = join(dir, entry.name);\n if (entry.isDirectory()) await visit(path);\n else if (entry.isFile()) found.push(relative(root, path).split('\\\\').join('/'));\n }\n } catch {\n return;\n }\n };\n await visit(root);\n return found.sort();\n}\n\nfunction field<T>(\n value: T,\n detector: string,\n sources: string[],\n className: ProjectModel['project']['id']['class'] = 'observed',\n) {\n return { value, class: className, provenance: { detector, sources } };\n}\n\nconst WORKSPACE_ROOTS = new Set(['apps', 'packages', 'services', 'modules', 'libs', 'plugins']);\n\nfunction surfaceId(path: string): string {\n return path\n .replaceAll('/', '-')\n .replace(/[^A-Za-z0-9_.-]/g, '_')\n .slice(0, 128);\n}\n\nconst topLevelOf = (file: string): string | undefined => file.split('/')[0];\n\n/**\n * Finds stable, implementation-sized boundaries without making semantic guesses. A package manifest is the\n * strongest local signal; for repositories without manifests we fall back to top-level directories.\n */\nfunction discoverSurfacePaths(files: string[]): Map<string, { glob: string; sources: string[] }> {\n const candidates = new Map<string, { glob: string; sources: string[] }>();\n const packageDirs = files\n .filter((file) => file.endsWith('/package.json'))\n .map((file) => file.slice(0, -'/package.json'.length))\n .filter((dir) => dir.includes('/'));\n\n for (const dir of packageDirs) {\n const first = topLevelOf(dir);\n if (first === undefined || !WORKSPACE_ROOTS.has(first)) continue;\n const glob = `${dir}/**`;\n candidates.set(surfaceId(dir), {\n glob,\n sources: files.filter((file) => file === dir || file.startsWith(`${dir}/`)),\n });\n }\n\n const topLevelDirectories = new Set(\n files\n .filter((file) => file.includes('/'))\n .map(topLevelOf)\n .filter((name): name is string => Boolean(name && !name.startsWith('.'))),\n );\n for (const topLevel of [...topLevelDirectories].sort()) {\n if (WORKSPACE_ROOTS.has(topLevel)) continue;\n const glob = `${topLevel}/**`;\n candidates.set(topLevel, { glob, sources: files.filter((file) => file.startsWith(`${topLevel}/`)) });\n }\n\n if (candidates.size === 0) {\n const topLevelDirectoriesOnly = new Set(\n files\n .filter((file) => file.includes('/'))\n .map(topLevelOf)\n .filter((name): name is string => Boolean(name && !name.startsWith('.'))),\n );\n for (const topLevel of [...topLevelDirectoriesOnly].sort()) {\n const glob = `${topLevel}/**`;\n candidates.set(topLevel, { glob, sources: files.filter((file) => file.startsWith(`${topLevel}/`)) });\n }\n }\n\n return candidates;\n}\n\nexport async function scanRepository(root: string, options: ScanOptions): Promise<ProjectModel> {\n const files = await filesUnder(root);\n const packagePath = join(root, 'package.json');\n let pkg: {\n name?: string;\n packageManager?: string;\n scripts?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n } = {};\n try {\n pkg = JSON.parse(await readFile(packagePath, 'utf8')) as typeof pkg;\n } catch {\n /* absent or invalid package.json is an observation */\n }\n const ext = new Map<string, string>([\n ['.ts', 'typescript'],\n ['.tsx', 'typescript'],\n ['.js', 'javascript'],\n ['.jsx', 'javascript'],\n ['.py', 'python'],\n ['.go', 'go'],\n ['.rs', 'rust'],\n ['.java', 'java'],\n ]);\n const languages = [\n ...new Set(\n files\n .map((file) => ext.get(file.slice(file.lastIndexOf('.'))))\n .filter((value): value is string => value !== undefined),\n ),\n ].sort();\n const supportedLocks = ['pnpm-lock.yaml', 'package-lock.json', 'yarn.lock', 'bun.lockb'];\n const locks = files.filter((file) => supportedLocks.includes(file));\n const lock = locks.length === 1 ? locks[0] : undefined;\n const packageManager =\n lock === undefined\n ? (pkg.packageManager?.split('@')[0] ?? null)\n : lock === 'pnpm-lock.yaml'\n ? 'pnpm'\n : lock === 'package-lock.json'\n ? 'npm'\n : lock === 'yarn.lock'\n ? 'yarn'\n : 'bun';\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n const frameworks = Object.keys(deps)\n .filter((name) =>\n /^(react|vue|angular|svelte|next|nuxt|express|nestjs|fastify|vite|vitest|jest|playwright)/i.test(name),\n )\n .sort();\n const scripts = pkg.scripts ?? {};\n const commands: Record<string, ReturnType<typeof field<string[]>>> = {};\n for (const name of Object.keys(scripts).sort()) {\n const command = scripts[name];\n if (command !== undefined) commands[name] = field(command.split(/\\s+/u), 'package-json', ['package.json']);\n }\n const testLocations = files.filter((file) => /(^|\\/)(test|tests|__tests__)(\\/|$)|\\.(test|spec)\\./u.test(file));\n const surfaces: ProjectModel['surfaces'] = {};\n for (const [id, candidate] of discoverSurfacePaths(files))\n surfaces[id] = { paths: field([candidate.glob], 'workspace-layout', candidate.sources) };\n const id =\n pkg.name?.replace(/^@[^/]+\\//u, '') ??\n (relative(process.cwd(), root).replace(/[^A-Za-z0-9_.-]/g, '_') || 'project');\n const unknowns =\n locks.length > 1\n ? [\n {\n id: 'package-manager',\n question: 'more than one supported lockfile was detected; which package manager is authoritative?',\n candidates: [...locks].sort(),\n sources: [...locks].sort(),\n },\n ]\n : [];\n return {\n schemaVersion: 1,\n project: { id: field(id, 'package-json', ['package.json'], 'human'), root: field(root, 'filesystem', []) },\n stack: {\n languages: field(languages, 'file-extensions', files),\n packageManager: field(packageManager, 'lockfile', lock ? [lock] : []),\n frameworks: field(frameworks, 'package-json', ['package.json']),\n },\n surfaces,\n commands,\n testStrategy: field(\n { runner: scripts.test ? (scripts.test.split(/\\s+/u)[0] ?? null) : null, locations: testLocations },\n 'package-json',\n ['package.json'],\n ),\n deploymentHints: field(\n files.filter((file) => /(^|\\/)(Dockerfile|Procfile|vercel\\.json|fly\\.toml)$/u.test(file)),\n 'file-presence',\n files,\n ),\n ownership: field(\n { codeowners: files.includes('.github/CODEOWNERS') ? '.github/CODEOWNERS' : null },\n 'file-presence',\n ['.github/CODEOWNERS'],\n ),\n risks:\n packageManager === null\n ? [{ id: 'missing-lockfile', severity: 'medium', message: 'no supported lockfile was detected', sources: [] }]\n : [],\n conventions: field(\n files.filter((file) => /(^|\\/)(CONTRIBUTING|conventions)\\.(md|yaml)$/iu.test(file)),\n 'file-presence',\n files,\n ),\n generatedArtifacts: field(['manifest.yaml', 'project.yaml'], 'manifest', ['.cohorte/manifest.yaml']),\n unknowns,\n provenance: { generatedAt: options.clock.now(), toolVersion: options.toolVersion, analysis: 'deterministic' },\n };\n}\n"],"mappings":"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"}
|
package/dist/cli.mjs
CHANGED
|
@@ -13,9 +13,9 @@ import { Command, CommanderError } from "commander";
|
|
|
13
13
|
* registry without a loader — or the reverse — fails Wave 0's own check.
|
|
14
14
|
*/
|
|
15
15
|
const COMMAND_MODULES = Object.freeze({
|
|
16
|
-
init: () => import("./chunks/init-
|
|
16
|
+
init: () => import("./chunks/init-CP6puNbE.mjs"),
|
|
17
17
|
doctor: () => import("./chunks/doctor-CginW8y8.mjs"),
|
|
18
|
-
discover: () => import("./chunks/discover-
|
|
18
|
+
discover: () => import("./chunks/discover-BJMwXyGL.mjs"),
|
|
19
19
|
run: () => import("./chunks/run-CgTWYlcd.mjs"),
|
|
20
20
|
status: () => import("./chunks/status-SMjiOMYy.mjs"),
|
|
21
21
|
inspect: () => import("./chunks/inspect-Buby4cQD.mjs"),
|
|
@@ -33,12 +33,12 @@ const COMMAND_MODULES = Object.freeze({
|
|
|
33
33
|
review: () => import("./chunks/review-BDdjb6kB.mjs"),
|
|
34
34
|
fix: () => import("./chunks/fix-D4Tj8RVA.mjs"),
|
|
35
35
|
ship: () => import("./chunks/ship-DTuLGoaJ.mjs"),
|
|
36
|
-
auth: () => import("./chunks/auth-
|
|
36
|
+
auth: () => import("./chunks/auth-Dnlksuo5.mjs"),
|
|
37
37
|
providers: () => import("./chunks/providers-Dx78imKj.mjs"),
|
|
38
38
|
models: () => import("./chunks/models-Btp6X2YZ.mjs"),
|
|
39
39
|
config: () => import("./chunks/config-DefHA2Lw.mjs"),
|
|
40
40
|
migrate: () => import("./chunks/migrate-DybihKzZ.mjs"),
|
|
41
|
-
reconcile: () => import("./chunks/reconcile-
|
|
41
|
+
reconcile: () => import("./chunks/reconcile-czNaLOP6.mjs"),
|
|
42
42
|
spec: () => import("./chunks/spec-Bq0P3jVh.mjs"),
|
|
43
43
|
policy: () => import("./chunks/policy-Clypo20s.mjs"),
|
|
44
44
|
gc: () => import("./chunks/gc-BBXlBF5w.mjs"),
|
|
@@ -61,7 +61,7 @@ async function loadCommandModule(verb) {
|
|
|
61
61
|
* only through here, so a read-only verb whose action never runs never pays for it either (DESIGN 1.3).
|
|
62
62
|
*/
|
|
63
63
|
async function loadCliContext(inputs) {
|
|
64
|
-
const mod = await import("./chunks/compose-
|
|
64
|
+
const mod = await import("./chunks/compose-CKo_q39e.mjs");
|
|
65
65
|
if (typeof mod.composeCliContext !== "function") throw new TypeError("lazy.ts: compose/index.ts has no composeCliContext export");
|
|
66
66
|
return mod.composeCliContext(inputs);
|
|
67
67
|
}
|
|
@@ -69,7 +69,7 @@ async function loadCliContext(inputs) {
|
|
|
69
69
|
//#region src/cli.ts
|
|
70
70
|
/** Mirrors `apps/cli/package.json` "version"; `apps/cli/test/registry/version.test.ts` reads that file and fails
|
|
71
71
|
* if the two ever drift (a literal keeps `--version` free of any file read on the one-shot start-up path). */
|
|
72
|
-
const COHORTE_VERSION = "3.0.0-dev.
|
|
72
|
+
const COHORTE_VERSION = "3.0.0-dev.5";
|
|
73
73
|
function printError(deps, info) {
|
|
74
74
|
deps.stderr.write(`error: ${info.code}: ${info.message}\n`);
|
|
75
75
|
deps.stderr.write(`impact: ${info.impact}\n`);
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":[],"sources":["../../../apps/cli/src/lazy.ts","../../../apps/cli/src/cli.ts"],"sourcesContent":["// apps/cli/src/lazy.ts — the ONLY `import(` site of `apps/cli/src` (DESIGN 1.2 net 3 rule g, DESIGN 1.3, DESIGN\n// 6.3 §\"read-only verbs never load core/runtime\"). `check-layers` refuses `import(` anywhere else under\n// `apps/cli/src/**` (rule g is per FILE, not per occurrence), so a verb module that needs `compose`/`host`/etc.\n// reaches them only through here, which keeps `cli.ts` (and every module reachable from it without going through\n// `lazy.ts`) inside François' 10 s / 4 MiB one-shot budget for a verb that never needs the heavy ports.\nimport type { CliContext, CommandModule } from './contract/index.ts';\n\n/** What `compose/index.ts` (U4.01) exports: assembles the real `CliContext` from process-level inputs. */\nexport interface ComposeInputs {\n readonly cwd: string;\n readonly env: NodeJS.ProcessEnv;\n readonly stdio: {\n readonly stdout: NodeJS.WritableStream;\n readonly stderr: NodeJS.WritableStream;\n readonly stdin: NodeJS.ReadableStream;\n };\n}\n\n/**\n * One LITERAL specifier per verb, closed over a thunk. A computed specifier (`` import(`./commands/${verb}/…`) ``)\n * is invisible to every bundler: rolldown would leave the template in `dist/cli.mjs` and emit no verb chunk, so the\n * SHIPPED cli could not execute a single verb (it would try to load a `.ts` file next to `dist/`). Written out, each\n * specifier is statically analysable: rolldown code-splits one chunk per verb, laziness is preserved, and\n * `apps/cli/test/registry/lazy.test.ts` pins this map against `VERBS` in both directions so a verb added to the\n * registry without a loader — or the reverse — fails Wave 0's own check.\n */\nexport const COMMAND_MODULES: Readonly<Record<string, () => Promise<unknown>>> = Object.freeze({\n init: () => import('./commands/init/index.ts'),\n doctor: () => import('./commands/doctor/index.ts'),\n discover: () => import('./commands/discover/index.ts'),\n run: () => import('./commands/run/index.ts'),\n status: () => import('./commands/status/index.ts'),\n inspect: () => import('./commands/inspect/index.ts'),\n resume: () => import('./commands/resume/index.ts'),\n pause: () => import('./commands/pause/index.ts'),\n cancel: () => import('./commands/cancel/index.ts'),\n shutdown: () => import('./commands/shutdown/index.ts'),\n approve: () => import('./commands/approve/index.ts'),\n deny: () => import('./commands/deny/index.ts'),\n retry: () => import('./commands/retry/index.ts'),\n skip: () => import('./commands/skip/index.ts'),\n logs: () => import('./commands/logs/index.ts'),\n tail: () => import('./commands/tail/index.ts'),\n diff: () => import('./commands/diff/index.ts'),\n review: () => import('./commands/review/index.ts'),\n fix: () => import('./commands/fix/index.ts'),\n ship: () => import('./commands/ship/index.ts'),\n auth: () => import('./commands/auth/index.ts'),\n providers: () => import('./commands/providers/index.ts'),\n models: () => import('./commands/models/index.ts'),\n config: () => import('./commands/config/index.ts'),\n migrate: () => import('./commands/migrate/index.ts'),\n reconcile: () => import('./commands/reconcile/index.ts'),\n spec: () => import('./commands/spec/index.ts'),\n policy: () => import('./commands/policy/index.ts'),\n gc: () => import('./commands/gc/index.ts'),\n update: () => import('./commands/update/index.ts'),\n brainstorm: () => import('./commands/brainstorm/index.ts'),\n 'run-tool': () => import('./commands/run-tool/index.ts'),\n send: () => import('./commands/send/index.ts'),\n __host: () => import('./commands/__host/index.ts'),\n});\n\n/** Loads `commands/<verb>/index.ts` and returns its default export. */\nexport async function loadCommandModule(verb: string): Promise<CommandModule> {\n const load = COMMAND_MODULES[verb];\n if (!load) throw new RangeError(`lazy.ts: no command module registered for verb \"${verb}\"`);\n const loaded = await load();\n const mod = loaded as { default?: CommandModule };\n if (!mod.default || typeof mod.default.run !== 'function') {\n throw new TypeError(`lazy.ts: commands/${verb}/index.ts has no default CommandModule export`);\n }\n return mod.default;\n}\n\n/**\n * The one `import(` of `./compose/index.ts` (DESIGN 1.2 net 3 rule g): `cli.ts` reaches the real `CliContext`\n * only through here, so a read-only verb whose action never runs never pays for it either (DESIGN 1.3).\n */\nexport async function loadCliContext(inputs: ComposeInputs): Promise<CliContext> {\n const loaded: unknown = await import('./compose/index.ts');\n const mod = loaded as { composeCliContext?: (inputs: ComposeInputs) => Promise<CliContext> };\n if (typeof mod.composeCliContext !== 'function') {\n throw new TypeError('lazy.ts: compose/index.ts has no composeCliContext export');\n }\n return mod.composeCliContext(inputs);\n}\n","#!/usr/bin/env node\n// apps/cli/src/cli.ts — DESIGN §9 CLI row: the whole verb registry, built from `contract/verbs.ts` and nothing\n// else (PLAN §3 rule 3 \"cli.ts pre-registers every verb against commands/<verb>/index.ts; ... nobody edits the\n// registry\"). `cli.ts` never imports `core`/`runtime-*`/`security`/`persistence` directly: a verb's module, and the\n// real `CliContext`, are reached only through `lazy.ts`'s single `import()` site (DESIGN 1.2 net 3 rule g, DESIGN\n// 1.3 \"read-only verbs never load core/runtime\") — so `--help` and `--version`, which commander answers itself\n// without ever calling `dispatch`, pay nothing beyond this file and `commander`.\nimport { toErrorInfo } from '@cohorte/base';\nimport { Command, CommanderError } from 'commander';\nimport {\n type CliContext,\n CONTROLLER_EXIT_CODES,\n type CommandArgs,\n EXIT_CODE_BY_CLASS,\n formatExitCodesHelp,\n VERBS,\n type VerbSpec,\n} from './contract/index.ts';\nimport { loadCliContext, loadCommandModule } from './lazy.ts';\n\n/** Mirrors `apps/cli/package.json` \"version\"; `apps/cli/test/registry/version.test.ts` reads that file and fails\n * if the two ever drift (a literal keeps `--version` free of any file read on the one-shot start-up path). */\nexport const COHORTE_VERSION = '3.0.0-dev.3';\n\nexport interface RuntimeDeps {\n readonly stdout: NodeJS.WritableStream;\n readonly stderr: NodeJS.WritableStream;\n /** Built lazily: only a verb whose action actually runs calls this (never `--help`/`--version`, DESIGN 1.3). */\n readonly context: () => Promise<CliContext>;\n}\n\nfunction printError(deps: RuntimeDeps, info: ReturnType<typeof toErrorInfo>): void {\n // spec 21: \"cause / impact / run / next action / exit code\"\n deps.stderr.write(`error: ${info.code}: ${info.message}\\n`);\n deps.stderr.write(`impact: ${info.impact}\\n`);\n deps.stderr.write(`next action: ${info.remediation}\\n`);\n}\n\n/** Loads the verb's module, builds its `CliContext` and runs it, converting any throw at this one boundary\n * (DESIGN 2.8: \"Every error has ... an exit code\"; the module itself never writes to stdio on error). */\nasync function dispatch(deps: RuntimeDeps, verb: string, args: CommandArgs): Promise<number> {\n try {\n const mod = await loadCommandModule(verb);\n const ctx = await deps.context();\n return await mod.run(ctx, args);\n } catch (error) {\n // DESIGN 2.8: \"Unknown throwables -> `<nearest class>/unexpected`\". A `CohorteError` keeps its own code through\n // `toErrorInfo`, so the Wave-0 stubs still answer `configuration/phase-not-available`; anything else — a\n // TypeError in a filled-in verb, a failed store open, a module that will not load — is reported as what it is.\n const info = toErrorInfo(error, { code: 'configuration/unexpected', class: 'configuration' });\n printError(deps, info);\n return EXIT_CODE_BY_CLASS[info.class];\n }\n}\n\ninterface ExitBox {\n code: number;\n}\n\nfunction addAction(command: Command, deps: RuntimeDeps, exit: ExitBox, verb: VerbSpec, subVerb?: string): void {\n command.allowUnknownOption(true).allowExcessArguments(true);\n // `--json` only where DESIGN 2.3.5 gives the verb a published document (`JSON_OUTPUTS`): registering it on every\n // verb would promise a machine output that no schema backs, and the Wave-4 `--json validates` tests read that map.\n if (verb.json) command.option('--json', 'print the machine-readable document for this verb (DESIGN 2.3.5)');\n command.argument('[args...]', 'verb arguments').action(async (positionals: string[], options: { json?: boolean }) => {\n const args: CommandArgs = {\n positionals,\n options,\n json: Boolean(options.json),\n ...(subVerb === undefined ? {} : { subVerb }),\n };\n exit.code = await dispatch(deps, verb.name, args);\n });\n}\n\n/** Builds the whole commander tree. Exported so a test can assert on `--help` / registration without spawning a\n * process (PLAN U0.10 test list: \"every DESIGN §9 verb is registered exactly once and appears in --help\"). */\nexport function buildProgram(deps: RuntimeDeps, exit: ExitBox): Command {\n const program = new Command('cohorte')\n .description('Cohorte: a durable multi-agent development pipeline with a runtime-independent orchestrator.')\n .version(COHORTE_VERSION, '--version', 'print the Cohorte version')\n .exitOverride()\n .configureOutput({\n writeOut: (str) => deps.stdout.write(str),\n writeErr: (str) => deps.stderr.write(str),\n })\n .addHelpText('after', `\\n${formatExitCodesHelp()}\\n`);\n\n for (const verb of VERBS) {\n const sub = program.command(verb.name, verb.hidden ? { hidden: true } : undefined).description(verb.summary);\n if (verb.subVerbs && verb.subVerbs.length > 0) {\n addAction(sub, deps, exit, verb); // bare `cohorte <verb>` with no sub-verb\n for (const subVerb of verb.subVerbs) {\n addAction(sub.command(subVerb), deps, exit, verb, subVerb);\n }\n } else {\n addAction(sub, deps, exit, verb);\n }\n }\n return program;\n}\n\n/**\n * `CONTROLLER_EXIT_CODES.usage` (2) for anything commander itself refuses (bad flag, unknown command, no command at\n * all), `completed` (0) for the routes where commander did exactly what was asked and then stopped the parse.\n *\n * Keyed off commander's OWN `exitCode`, not off the code NAME: commander raises `commander.help` both for the\n * advertised `help [command]` route (which prints the help and means exit 0) and for a bare `cohorte` with no\n * command (exit 1 there — a usage error), and an allow-list of names got the first case wrong while `--help`,\n * raising `commander.helpDisplayed`, was right. `error.exitCode` already separates the two.\n */\nfunction commanderExitCode(error: CommanderError): number {\n return error.exitCode === 0 ? CONTROLLER_EXIT_CODES.completed : CONTROLLER_EXIT_CODES.usage;\n}\n\n/** Parses `argv` (no leading node/script entries) and runs the matched verb. Never calls `process.exit`: the\n * caller (`main()` below, or a test) owns that decision. */\nexport async function runCli(argv: readonly string[], deps: RuntimeDeps): Promise<number> {\n const exit: ExitBox = { code: CONTROLLER_EXIT_CODES.completed };\n const program = buildProgram(deps, exit);\n try {\n await program.parseAsync(argv, { from: 'user' });\n } catch (error) {\n if (error instanceof CommanderError) return commanderExitCode(error);\n throw error;\n }\n return exit.code;\n}\n\nasync function realContext(): Promise<CliContext> {\n return loadCliContext({\n cwd: process.cwd(),\n env: process.env,\n stdio: { stdout: process.stdout, stderr: process.stderr, stdin: process.stdin },\n });\n}\n\nasync function main(): Promise<void> {\n const deps: RuntimeDeps = { stdout: process.stdout, stderr: process.stderr, context: realContext };\n const code = await runCli(process.argv.slice(2), deps);\n process.exitCode = code;\n}\n\n// `import.meta.main` (node >= 24.2; `apps/cli` engines are `^24.16.0 || >=26.1.0`) and NOT a hand-rolled\n// `import.meta.url === \\`file://${process.argv[1]}\\``: npm installs `bin` as a SYMLINK\n// (`node_modules/.bin/cohorte` -> `../cohorte/dist/cli.mjs`), so the comparison is false for every real install and\n// the published CLI would print nothing and exit 0. It also breaks on any install path with a space or a non-ASCII\n// character (`import.meta.url` is percent-encoded, `argv[1]` is not).\nif (import.meta.main) {\n main().catch((error: unknown) => {\n process.stderr.write(`fatal: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}\\n`);\n process.exitCode = 1;\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":[],"sources":["../../../apps/cli/src/lazy.ts","../../../apps/cli/src/cli.ts"],"sourcesContent":["// apps/cli/src/lazy.ts — the ONLY `import(` site of `apps/cli/src` (DESIGN 1.2 net 3 rule g, DESIGN 1.3, DESIGN\n// 6.3 §\"read-only verbs never load core/runtime\"). `check-layers` refuses `import(` anywhere else under\n// `apps/cli/src/**` (rule g is per FILE, not per occurrence), so a verb module that needs `compose`/`host`/etc.\n// reaches them only through here, which keeps `cli.ts` (and every module reachable from it without going through\n// `lazy.ts`) inside François' 10 s / 4 MiB one-shot budget for a verb that never needs the heavy ports.\nimport type { CliContext, CommandModule } from './contract/index.ts';\n\n/** What `compose/index.ts` (U4.01) exports: assembles the real `CliContext` from process-level inputs. */\nexport interface ComposeInputs {\n readonly cwd: string;\n readonly env: NodeJS.ProcessEnv;\n readonly stdio: {\n readonly stdout: NodeJS.WritableStream;\n readonly stderr: NodeJS.WritableStream;\n readonly stdin: NodeJS.ReadableStream;\n };\n}\n\n/**\n * One LITERAL specifier per verb, closed over a thunk. A computed specifier (`` import(`./commands/${verb}/…`) ``)\n * is invisible to every bundler: rolldown would leave the template in `dist/cli.mjs` and emit no verb chunk, so the\n * SHIPPED cli could not execute a single verb (it would try to load a `.ts` file next to `dist/`). Written out, each\n * specifier is statically analysable: rolldown code-splits one chunk per verb, laziness is preserved, and\n * `apps/cli/test/registry/lazy.test.ts` pins this map against `VERBS` in both directions so a verb added to the\n * registry without a loader — or the reverse — fails Wave 0's own check.\n */\nexport const COMMAND_MODULES: Readonly<Record<string, () => Promise<unknown>>> = Object.freeze({\n init: () => import('./commands/init/index.ts'),\n doctor: () => import('./commands/doctor/index.ts'),\n discover: () => import('./commands/discover/index.ts'),\n run: () => import('./commands/run/index.ts'),\n status: () => import('./commands/status/index.ts'),\n inspect: () => import('./commands/inspect/index.ts'),\n resume: () => import('./commands/resume/index.ts'),\n pause: () => import('./commands/pause/index.ts'),\n cancel: () => import('./commands/cancel/index.ts'),\n shutdown: () => import('./commands/shutdown/index.ts'),\n approve: () => import('./commands/approve/index.ts'),\n deny: () => import('./commands/deny/index.ts'),\n retry: () => import('./commands/retry/index.ts'),\n skip: () => import('./commands/skip/index.ts'),\n logs: () => import('./commands/logs/index.ts'),\n tail: () => import('./commands/tail/index.ts'),\n diff: () => import('./commands/diff/index.ts'),\n review: () => import('./commands/review/index.ts'),\n fix: () => import('./commands/fix/index.ts'),\n ship: () => import('./commands/ship/index.ts'),\n auth: () => import('./commands/auth/index.ts'),\n providers: () => import('./commands/providers/index.ts'),\n models: () => import('./commands/models/index.ts'),\n config: () => import('./commands/config/index.ts'),\n migrate: () => import('./commands/migrate/index.ts'),\n reconcile: () => import('./commands/reconcile/index.ts'),\n spec: () => import('./commands/spec/index.ts'),\n policy: () => import('./commands/policy/index.ts'),\n gc: () => import('./commands/gc/index.ts'),\n update: () => import('./commands/update/index.ts'),\n brainstorm: () => import('./commands/brainstorm/index.ts'),\n 'run-tool': () => import('./commands/run-tool/index.ts'),\n send: () => import('./commands/send/index.ts'),\n __host: () => import('./commands/__host/index.ts'),\n});\n\n/** Loads `commands/<verb>/index.ts` and returns its default export. */\nexport async function loadCommandModule(verb: string): Promise<CommandModule> {\n const load = COMMAND_MODULES[verb];\n if (!load) throw new RangeError(`lazy.ts: no command module registered for verb \"${verb}\"`);\n const loaded = await load();\n const mod = loaded as { default?: CommandModule };\n if (!mod.default || typeof mod.default.run !== 'function') {\n throw new TypeError(`lazy.ts: commands/${verb}/index.ts has no default CommandModule export`);\n }\n return mod.default;\n}\n\n/**\n * The one `import(` of `./compose/index.ts` (DESIGN 1.2 net 3 rule g): `cli.ts` reaches the real `CliContext`\n * only through here, so a read-only verb whose action never runs never pays for it either (DESIGN 1.3).\n */\nexport async function loadCliContext(inputs: ComposeInputs): Promise<CliContext> {\n const loaded: unknown = await import('./compose/index.ts');\n const mod = loaded as { composeCliContext?: (inputs: ComposeInputs) => Promise<CliContext> };\n if (typeof mod.composeCliContext !== 'function') {\n throw new TypeError('lazy.ts: compose/index.ts has no composeCliContext export');\n }\n return mod.composeCliContext(inputs);\n}\n","#!/usr/bin/env node\n// apps/cli/src/cli.ts — DESIGN §9 CLI row: the whole verb registry, built from `contract/verbs.ts` and nothing\n// else (PLAN §3 rule 3 \"cli.ts pre-registers every verb against commands/<verb>/index.ts; ... nobody edits the\n// registry\"). `cli.ts` never imports `core`/`runtime-*`/`security`/`persistence` directly: a verb's module, and the\n// real `CliContext`, are reached only through `lazy.ts`'s single `import()` site (DESIGN 1.2 net 3 rule g, DESIGN\n// 1.3 \"read-only verbs never load core/runtime\") — so `--help` and `--version`, which commander answers itself\n// without ever calling `dispatch`, pay nothing beyond this file and `commander`.\nimport { toErrorInfo } from '@cohorte/base';\nimport { Command, CommanderError } from 'commander';\nimport {\n type CliContext,\n CONTROLLER_EXIT_CODES,\n type CommandArgs,\n EXIT_CODE_BY_CLASS,\n formatExitCodesHelp,\n VERBS,\n type VerbSpec,\n} from './contract/index.ts';\nimport { loadCliContext, loadCommandModule } from './lazy.ts';\n\n/** Mirrors `apps/cli/package.json` \"version\"; `apps/cli/test/registry/version.test.ts` reads that file and fails\n * if the two ever drift (a literal keeps `--version` free of any file read on the one-shot start-up path). */\nexport const COHORTE_VERSION = '3.0.0-dev.5';\n\nexport interface RuntimeDeps {\n readonly stdout: NodeJS.WritableStream;\n readonly stderr: NodeJS.WritableStream;\n /** Built lazily: only a verb whose action actually runs calls this (never `--help`/`--version`, DESIGN 1.3). */\n readonly context: () => Promise<CliContext>;\n}\n\nfunction printError(deps: RuntimeDeps, info: ReturnType<typeof toErrorInfo>): void {\n // spec 21: \"cause / impact / run / next action / exit code\"\n deps.stderr.write(`error: ${info.code}: ${info.message}\\n`);\n deps.stderr.write(`impact: ${info.impact}\\n`);\n deps.stderr.write(`next action: ${info.remediation}\\n`);\n}\n\n/** Loads the verb's module, builds its `CliContext` and runs it, converting any throw at this one boundary\n * (DESIGN 2.8: \"Every error has ... an exit code\"; the module itself never writes to stdio on error). */\nasync function dispatch(deps: RuntimeDeps, verb: string, args: CommandArgs): Promise<number> {\n try {\n const mod = await loadCommandModule(verb);\n const ctx = await deps.context();\n return await mod.run(ctx, args);\n } catch (error) {\n // DESIGN 2.8: \"Unknown throwables -> `<nearest class>/unexpected`\". A `CohorteError` keeps its own code through\n // `toErrorInfo`, so the Wave-0 stubs still answer `configuration/phase-not-available`; anything else — a\n // TypeError in a filled-in verb, a failed store open, a module that will not load — is reported as what it is.\n const info = toErrorInfo(error, { code: 'configuration/unexpected', class: 'configuration' });\n printError(deps, info);\n return EXIT_CODE_BY_CLASS[info.class];\n }\n}\n\ninterface ExitBox {\n code: number;\n}\n\nfunction addAction(command: Command, deps: RuntimeDeps, exit: ExitBox, verb: VerbSpec, subVerb?: string): void {\n command.allowUnknownOption(true).allowExcessArguments(true);\n // `--json` only where DESIGN 2.3.5 gives the verb a published document (`JSON_OUTPUTS`): registering it on every\n // verb would promise a machine output that no schema backs, and the Wave-4 `--json validates` tests read that map.\n if (verb.json) command.option('--json', 'print the machine-readable document for this verb (DESIGN 2.3.5)');\n command.argument('[args...]', 'verb arguments').action(async (positionals: string[], options: { json?: boolean }) => {\n const args: CommandArgs = {\n positionals,\n options,\n json: Boolean(options.json),\n ...(subVerb === undefined ? {} : { subVerb }),\n };\n exit.code = await dispatch(deps, verb.name, args);\n });\n}\n\n/** Builds the whole commander tree. Exported so a test can assert on `--help` / registration without spawning a\n * process (PLAN U0.10 test list: \"every DESIGN §9 verb is registered exactly once and appears in --help\"). */\nexport function buildProgram(deps: RuntimeDeps, exit: ExitBox): Command {\n const program = new Command('cohorte')\n .description('Cohorte: a durable multi-agent development pipeline with a runtime-independent orchestrator.')\n .version(COHORTE_VERSION, '--version', 'print the Cohorte version')\n .exitOverride()\n .configureOutput({\n writeOut: (str) => deps.stdout.write(str),\n writeErr: (str) => deps.stderr.write(str),\n })\n .addHelpText('after', `\\n${formatExitCodesHelp()}\\n`);\n\n for (const verb of VERBS) {\n const sub = program.command(verb.name, verb.hidden ? { hidden: true } : undefined).description(verb.summary);\n if (verb.subVerbs && verb.subVerbs.length > 0) {\n addAction(sub, deps, exit, verb); // bare `cohorte <verb>` with no sub-verb\n for (const subVerb of verb.subVerbs) {\n addAction(sub.command(subVerb), deps, exit, verb, subVerb);\n }\n } else {\n addAction(sub, deps, exit, verb);\n }\n }\n return program;\n}\n\n/**\n * `CONTROLLER_EXIT_CODES.usage` (2) for anything commander itself refuses (bad flag, unknown command, no command at\n * all), `completed` (0) for the routes where commander did exactly what was asked and then stopped the parse.\n *\n * Keyed off commander's OWN `exitCode`, not off the code NAME: commander raises `commander.help` both for the\n * advertised `help [command]` route (which prints the help and means exit 0) and for a bare `cohorte` with no\n * command (exit 1 there — a usage error), and an allow-list of names got the first case wrong while `--help`,\n * raising `commander.helpDisplayed`, was right. `error.exitCode` already separates the two.\n */\nfunction commanderExitCode(error: CommanderError): number {\n return error.exitCode === 0 ? CONTROLLER_EXIT_CODES.completed : CONTROLLER_EXIT_CODES.usage;\n}\n\n/** Parses `argv` (no leading node/script entries) and runs the matched verb. Never calls `process.exit`: the\n * caller (`main()` below, or a test) owns that decision. */\nexport async function runCli(argv: readonly string[], deps: RuntimeDeps): Promise<number> {\n const exit: ExitBox = { code: CONTROLLER_EXIT_CODES.completed };\n const program = buildProgram(deps, exit);\n try {\n await program.parseAsync(argv, { from: 'user' });\n } catch (error) {\n if (error instanceof CommanderError) return commanderExitCode(error);\n throw error;\n }\n return exit.code;\n}\n\nasync function realContext(): Promise<CliContext> {\n return loadCliContext({\n cwd: process.cwd(),\n env: process.env,\n stdio: { stdout: process.stdout, stderr: process.stderr, stdin: process.stdin },\n });\n}\n\nasync function main(): Promise<void> {\n const deps: RuntimeDeps = { stdout: process.stdout, stderr: process.stderr, context: realContext };\n const code = await runCli(process.argv.slice(2), deps);\n process.exitCode = code;\n}\n\n// `import.meta.main` (node >= 24.2; `apps/cli` engines are `^24.16.0 || >=26.1.0`) and NOT a hand-rolled\n// `import.meta.url === \\`file://${process.argv[1]}\\``: npm installs `bin` as a SYMLINK\n// (`node_modules/.bin/cohorte` -> `../cohorte/dist/cli.mjs`), so the comparison is false for every real install and\n// the published CLI would print nothing and exit 0. It also breaks on any install path with a space or a non-ASCII\n// character (`import.meta.url` is percent-encoded, `argv[1]` is not).\nif (import.meta.main) {\n main().catch((error: unknown) => {\n process.stderr.write(`fatal: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}\\n`);\n process.exitCode = 1;\n });\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scan-8Gy_B6kI.mjs","names":[],"sources":["../../../../packages/project-model/src/scan/index.ts"],"sourcesContent":["// Deterministic repository scan: bounded filesystem observations, never guessed semantics.\n\nimport { readdir, readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { Clock } from '@cohorte/base';\nimport type { ProjectModel } from '../contract.ts';\n\nexport interface ScanOptions {\n clock: Clock;\n /** stamped into `provenance.toolVersion` */\n toolVersion: string;\n}\n\nasync function filesUnder(root: string): Promise<string[]> {\n const found: string[] = [];\n const visit = async (dir: string): Promise<void> => {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n if (\n entry.name === '.git' ||\n entry.name === 'node_modules' ||\n entry.name === '.cohorte' ||\n entry.name === '.pi' ||\n entry.name === '.build' ||\n entry.name === 'dist' ||\n entry.name === 'coverage'\n )\n continue;\n const path = join(dir, entry.name);\n if (entry.isDirectory()) await visit(path);\n else if (entry.isFile()) found.push(relative(root, path).split('\\\\').join('/'));\n }\n } catch {\n return;\n }\n };\n await visit(root);\n return found.sort();\n}\n\nfunction field<T>(\n value: T,\n detector: string,\n sources: string[],\n className: ProjectModel['project']['id']['class'] = 'observed',\n) {\n return { value, class: className, provenance: { detector, sources } };\n}\n\nexport async function scanRepository(root: string, options: ScanOptions): Promise<ProjectModel> {\n const files = await filesUnder(root);\n const packagePath = join(root, 'package.json');\n let pkg: {\n name?: string;\n packageManager?: string;\n scripts?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n } = {};\n try {\n pkg = JSON.parse(await readFile(packagePath, 'utf8')) as typeof pkg;\n } catch {\n /* absent or invalid package.json is an observation */\n }\n const ext = new Map<string, string>([\n ['.ts', 'typescript'],\n ['.tsx', 'typescript'],\n ['.js', 'javascript'],\n ['.jsx', 'javascript'],\n ['.py', 'python'],\n ['.go', 'go'],\n ['.rs', 'rust'],\n ['.java', 'java'],\n ]);\n const languages = [\n ...new Set(\n files\n .map((file) => ext.get(file.slice(file.lastIndexOf('.'))))\n .filter((value): value is string => value !== undefined),\n ),\n ].sort();\n const supportedLocks = ['pnpm-lock.yaml', 'package-lock.json', 'yarn.lock', 'bun.lockb'];\n const locks = files.filter((file) => supportedLocks.includes(file));\n const lock = locks.length === 1 ? locks[0] : undefined;\n const packageManager =\n lock === undefined\n ? (pkg.packageManager?.split('@')[0] ?? null)\n : lock === 'pnpm-lock.yaml'\n ? 'pnpm'\n : lock === 'package-lock.json'\n ? 'npm'\n : lock === 'yarn.lock'\n ? 'yarn'\n : 'bun';\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n const frameworks = Object.keys(deps)\n .filter((name) =>\n /^(react|vue|angular|svelte|next|nuxt|express|nestjs|fastify|vite|vitest|jest|playwright)/i.test(name),\n )\n .sort();\n const scripts = pkg.scripts ?? {};\n const commands: Record<string, ReturnType<typeof field<string[]>>> = {};\n for (const name of Object.keys(scripts).sort()) {\n const command = scripts[name];\n if (command !== undefined) commands[name] = field(command.split(/\\s+/u), 'package-json', ['package.json']);\n }\n const testLocations = files.filter((file) => /(^|\\/)(test|tests|__tests__)(\\/|$)|\\.(test|spec)\\./u.test(file));\n const surfaces: ProjectModel['surfaces'] = {};\n const topLevel: string[] = [\n ...new Set(\n files.map((file) => file.split('/')[0]).filter((name): name is string => Boolean(name && !name.startsWith('.'))),\n ),\n ];\n for (const name of topLevel.sort()) {\n const paths = files.filter((file) => file === name || file.startsWith(`${name}/`));\n if (paths.length)\n surfaces[name.replace(/[^A-Za-z0-9_.-]/g, '_')] = { paths: field([`${name}/**`], 'workspace-layout', paths) };\n }\n const id =\n pkg.name?.replace(/^@[^/]+\\//u, '') ??\n (relative(process.cwd(), root).replace(/[^A-Za-z0-9_.-]/g, '_') || 'project');\n const unknowns =\n locks.length > 1\n ? [\n {\n id: 'package-manager',\n question: 'more than one supported lockfile was detected; which package manager is authoritative?',\n candidates: [...locks].sort(),\n sources: [...locks].sort(),\n },\n ]\n : [];\n return {\n schemaVersion: 1,\n project: { id: field(id, 'package-json', ['package.json'], 'human'), root: field(root, 'filesystem', []) },\n stack: {\n languages: field(languages, 'file-extensions', files),\n packageManager: field(packageManager, 'lockfile', lock ? [lock] : []),\n frameworks: field(frameworks, 'package-json', ['package.json']),\n },\n surfaces,\n commands,\n testStrategy: field(\n { runner: scripts.test ? (scripts.test.split(/\\s+/u)[0] ?? null) : null, locations: testLocations },\n 'package-json',\n ['package.json'],\n ),\n deploymentHints: field(\n files.filter((file) => /(^|\\/)(Dockerfile|Procfile|vercel\\.json|fly\\.toml)$/u.test(file)),\n 'file-presence',\n files,\n ),\n ownership: field(\n { codeowners: files.includes('.github/CODEOWNERS') ? '.github/CODEOWNERS' : null },\n 'file-presence',\n ['.github/CODEOWNERS'],\n ),\n risks:\n packageManager === null\n ? [{ id: 'missing-lockfile', severity: 'medium', message: 'no supported lockfile was detected', sources: [] }]\n : [],\n conventions: field(\n files.filter((file) => /(^|\\/)(CONTRIBUTING|conventions)\\.(md|yaml)$/iu.test(file)),\n 'file-presence',\n files,\n ),\n generatedArtifacts: field(['manifest.yaml', 'project.yaml'], 'manifest', ['.cohorte/manifest.yaml']),\n unknowns,\n provenance: { generatedAt: options.clock.now(), toolVersion: options.toolVersion, analysis: 'deterministic' },\n };\n}\n"],"mappings":"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"}
|