@shrkcrft/cli 0.1.0-alpha.7 → 0.1.0-alpha.9

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.
Files changed (46) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/boundaries.command.d.ts.map +1 -1
  3. package/dist/commands/boundaries.command.js +12 -0
  4. package/dist/commands/check.command.d.ts.map +1 -1
  5. package/dist/commands/check.command.js +30 -20
  6. package/dist/commands/command-catalog.d.ts.map +1 -1
  7. package/dist/commands/command-catalog.js +14 -1
  8. package/dist/commands/doctor.command.d.ts.map +1 -1
  9. package/dist/commands/doctor.command.js +7 -8
  10. package/dist/commands/help.command.d.ts.map +1 -1
  11. package/dist/commands/help.command.js +8 -6
  12. package/dist/commands/init.command.d.ts.map +1 -1
  13. package/dist/commands/init.command.js +13 -37
  14. package/dist/commands/mcp.command.d.ts.map +1 -1
  15. package/dist/commands/mcp.command.js +131 -2
  16. package/dist/commands/onboard.command.d.ts.map +1 -1
  17. package/dist/commands/onboard.command.js +15 -3
  18. package/dist/commands/packs-new.d.ts.map +1 -1
  19. package/dist/commands/packs-new.js +10 -3
  20. package/dist/commands/packs.command.d.ts.map +1 -1
  21. package/dist/commands/packs.command.js +17 -3
  22. package/dist/commands/review.command.d.ts.map +1 -1
  23. package/dist/commands/review.command.js +28 -2
  24. package/dist/init/init-templates.d.ts.map +1 -1
  25. package/dist/init/init-templates.js +113 -133
  26. package/dist/main.d.ts +1 -1
  27. package/dist/main.d.ts.map +1 -1
  28. package/dist/main.js +35 -13
  29. package/dist/output/failure-hints.d.ts +9 -1
  30. package/dist/output/failure-hints.d.ts.map +1 -1
  31. package/dist/output/failure-hints.js +8 -2
  32. package/dist/output/watch-loop.d.ts +1 -9
  33. package/dist/output/watch-loop.d.ts.map +1 -1
  34. package/dist/output/watch-loop.js +3 -13
  35. package/dist/schemas/json-schemas.d.ts +36 -36
  36. package/dist/schemas/json-schemas.js +36 -36
  37. package/dist/surface/about.d.ts.map +1 -1
  38. package/dist/surface/about.js +15 -37
  39. package/dist/surface/no-args-landing.d.ts.map +1 -1
  40. package/dist/surface/no-args-landing.js +13 -9
  41. package/dist/surface/surface-config-writer.d.ts.map +1 -1
  42. package/dist/surface/surface-config-writer.js +11 -23
  43. package/package.json +25 -26
  44. package/dist/init/paths-advisory.d.ts +0 -20
  45. package/dist/init/paths-advisory.d.ts.map +0 -1
  46. package/dist/init/paths-advisory.js +0 -88
@@ -8,46 +8,24 @@ import { SHARKCRAFT_VERSION } from '@shrkcrft/shared';
8
8
  * `docs/`; this is the in-binary summary.
9
9
  */
10
10
  export function renderAbout() {
11
- return `SharkCraft v${SHARKCRAFT_VERSION}
11
+ return `SharkCraft v${SHARKCRAFT_VERSION} — the safety layer beneath your AI coding agent.
12
12
 
13
- What it is
14
- A deterministic, local-first toolkit that gives AI coding agents
15
- durable project context. Ships as a CLI (\`shrk\`) the only write
16
- path plus a read-only MCP server, plus a library of structured
17
- assets (knowledge, rules, paths, templates, pipelines, presets,
18
- boundaries).
13
+ Three structural guarantees (not prompts):
14
+ - MCP is read-only. Agents cannot write through it.
15
+ - Writes flow through signed plans. \`shrk apply --verify-signature\`
16
+ refuses on divergence.
17
+ - Boundaries are mechanical. \`shrk check boundaries --changed-only\`
18
+ fails only on violations the current diff introduced.
19
19
 
20
- What it is NOT
21
- There is no AI inside the engine. Every output is a pure function
22
- of the workspace + the asset registries. The agent uses the engine;
23
- the engine never calls a model.
20
+ On top of that: typed rules, paths, templates, pipelines, presets — so
21
+ the agent hallucinates less inside the bounds the safety surface enforces.
22
+ No AI inside the engine; every output is a pure function of the workspace.
24
23
 
25
- The safety contract
26
- - All write paths are preview-first. \`--apply\` is opt-in, scoped,
27
- and idempotent.
28
- - MCP is read-only. Every MCP tool returns data + a next-command
29
- hint; the human runs the CLI for any write.
30
- - Apply requires \`--verify-signature\` for signed plans, refuses
31
- on divergence unless \`--allow-divergent\`.
24
+ Try:
25
+ shrk check boundaries --changed-only --since main
26
+ shrk review packet --v3 --since main
27
+ shrk mcp install claude-code
32
28
 
33
- Calibration to project size
34
- Surface tiers (\`shrk surface list\`):
35
- - core always on
36
- - extended visible in --help, callable
37
- - experimental hidden until enabled (\`shrk surface enable\`)
38
- Project shape (\`shrk doctor\`) drives the default surface for a
39
- fresh repo.
40
-
41
- Where to read more
42
- docs/overview.md what SharkCraft is and isn't
43
- docs/philosophy.md the non-negotiable design rules
44
- docs/surface-tiers.md the tier model
45
- docs/safety-model.md plan / review / apply contract
46
-
47
- Quick start
48
- shrk doctor health check
49
- shrk task "<what>" full task packet (rules + templates + commands)
50
- shrk recommend "<what>" what command should I reach for?
51
- shrk surface list what is available in this repo
29
+ Docs: overview.md · safety-model.md · INDEX.md · demo.md
52
30
  `;
53
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"no-args-landing.d.ts","sourceRoot":"","sources":["../../src/surface/no-args-landing.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BtE"}
1
+ {"version":3,"file":"no-args-landing.d.ts","sourceRoot":"","sources":["../../src/surface/no-args-landing.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiCtE"}
@@ -8,7 +8,7 @@ import { buildSurfaceSummary } from "./surface-summary.js";
8
8
  */
9
9
  export async function renderNoArgsLanding(cwd) {
10
10
  const lines = [];
11
- lines.push(`shrk v${SHARKCRAFT_VERSION} — deterministic context for AI coding agents.`);
11
+ lines.push(`shrk v${SHARKCRAFT_VERSION} — the safety layer beneath your AI coding agent.`);
12
12
  lines.push('');
13
13
  let totals = '';
14
14
  try {
@@ -21,16 +21,20 @@ export async function renderNoArgsLanding(cwd) {
21
21
  }
22
22
  lines.push(totals);
23
23
  lines.push('');
24
- lines.push('Most useful next:');
25
- lines.push(' shrk doctor health check');
26
- lines.push(' shrk task "<what>" full packet for a task');
27
- lines.push(' shrk recommend "<what>" what should I do?');
28
- lines.push(' shrk surface list what is available in this repo');
24
+ lines.push('Prove it in 60 seconds:');
25
+ lines.push(' shrk check boundaries --changed-only --since main');
26
+ lines.push(' fail only on violations the diff introduced');
27
+ lines.push(' shrk review packet --v3 --since main');
28
+ lines.push(' structured packet for an AI PR reviewer');
29
+ lines.push(' shrk apply --verify-signature <plan.json>');
30
+ lines.push(' signed-plan write — refuses on divergence');
29
31
  lines.push('');
30
- lines.push('See:');
32
+ lines.push('Orient:');
33
+ lines.push(' shrk doctor health check + AI-readiness score');
34
+ lines.push(' shrk recommend "<task>" what command should I reach for?');
35
+ lines.push(' shrk surface list what is available in this repo');
36
+ lines.push(' shrk --about the safety contract in one screen');
31
37
  lines.push(' shrk --help every visible command');
32
- lines.push(' shrk surface explain <cmd> why a command is/is not visible');
33
- lines.push(' shrk --about what shrk is and is not');
34
38
  lines.push('');
35
39
  return lines.join('\n');
36
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"surface-config-writer.d.ts","sourceRoot":"","sources":["../../src/surface/surface-config-writer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,oBAAoB;IACpB,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB;IACjB,SAAS,EAAE,KAAK,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACrC,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACrC,iDAAiD;IACjD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,KAAK,EAAE,SAAS,kBAAkB,EAAE,GACnC,kBAAkB,CA0BpB;AAOD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,kBAAkB,GACvB,yBAAyB,CAe3B;AAoBD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAO,GAAG,MAAM,CAsBjF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,CA6BtF;AAED,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE/D"}
1
+ {"version":3,"file":"surface-config-writer.d.ts","sourceRoot":"","sources":["../../src/surface/surface-config-writer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,oBAAoB;IACpB,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB;IACjB,SAAS,EAAE,KAAK,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACrC,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACrC,iDAAiD;IACjD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,KAAK,EAAE,SAAS,kBAAkB,EAAE,GACnC,kBAAkB,CA0BpB;AAOD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,kBAAkB,GACvB,yBAAyB,CAe3B;AAmBD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAO,GAAG,MAAM,CAsBjF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,CAgBtF;AAED,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE/D"}
@@ -72,11 +72,10 @@ function fileExists(p) {
72
72
  return false;
73
73
  }
74
74
  }
75
- // Plain default export no @shrkcrft/* import required. The config
76
- // loader (packages/config/src/config-loader.ts) validates by shape, so a
77
- // literal object works the same as a `defineSharkCraftConfig()` call.
78
- const DEFAULT_CONFIG_BODY = `export default {
79
- };
75
+ const DEFAULT_CONFIG_BODY = `import { defineSharkCraftConfig } from '@shrkcrft/config';
76
+
77
+ export default defineSharkCraftConfig({
78
+ });
80
79
  `;
81
80
  const SURFACE_BLOCK_REGEX = /(^\s*surface\s*:\s*\{[\s\S]*?\}\s*,?\s*\n)/m;
82
81
  /**
@@ -121,25 +120,14 @@ export function applySurfaceTextEdit(original, surface) {
121
120
  if (SURFACE_BLOCK_REGEX.test(original)) {
122
121
  return original.replace(SURFACE_BLOCK_REGEX, block);
123
122
  }
124
- // (A) `defineSharkCraftConfig({ ... })` style insert before the `})`.
125
- const closeFn = /(\n)(\}\)\s*;?\s*)$/m;
126
- if (closeFn.test(original)) {
127
- return original.replace(closeFn, `\n${block}$2`);
123
+ // Insert before the closing `})` / `});` of the config object.
124
+ // Prefer the last `})` so nested objects don't trip us up.
125
+ const closeRegex = /(\n)(\}\)\s*;?\s*)$/m;
126
+ if (closeRegex.test(original)) {
127
+ return original.replace(closeRegex, `\n${block}$2`);
128
128
  }
129
- // (B) `const config = { ... };\nexport default config;` plain style —
130
- // insert before the `};` that closes the literal.
131
- const closePlain = /(\n)(\};?\s*\nexport\s+default\s+\w+\s*;?\s*\n*)$/m;
132
- if (closePlain.test(original)) {
133
- return original.replace(closePlain, `\n${block}$2`);
134
- }
135
- // (C) `export default { ... };` direct style — insert before the `};`.
136
- const closeDirect = /(\n)(\};?\s*\n*)$/m;
137
- if (closeDirect.test(original)) {
138
- return original.replace(closeDirect, `\n${block}$2`);
139
- }
140
- // Fallback: append at end with a plain default-exported config (no
141
- // `@shrkcrft/*` import required).
142
- return `${original}\n${DEFAULT_CONFIG_BODY.replace('};', `${block}};`)}`;
129
+ // Fallback: append at end with a defineSharkCraftConfig wrapper.
130
+ return `${original}\n${DEFAULT_CONFIG_BODY.replace('})', `${block}})`)}`;
143
131
  }
144
132
  /** Default config file path for a project. */
145
133
  export function defaultConfigFile(sharkcraftDir) {
package/package.json CHANGED
@@ -1,16 +1,15 @@
1
1
  {
2
2
  "name": "@shrkcrft/cli",
3
- "version": "0.1.0-alpha.7",
4
- "description": "SharkCraft CLI (`shrk`): structured project intelligence for AI coding agents.",
3
+ "version": "0.1.0-alpha.9",
4
+ "description": "SharkCraft CLI (`shrk`): the safety layer beneath your AI coding agent.",
5
5
  "license": "MIT",
6
6
  "author": "SharkCraft contributors",
7
7
  "type": "module",
8
8
  "main": "./dist/index.js",
9
- "types": "./dist/index.d.d.ts",
9
+ "types": "./dist/index.d.ts",
10
10
  "exports": {
11
11
  ".": {
12
12
  "types": "./dist/index.d.ts",
13
- "bun": "./src/index.ts",
14
13
  "import": "./dist/index.js",
15
14
  "default": "./dist/index.js"
16
15
  }
@@ -25,12 +24,12 @@
25
24
  ],
26
25
  "repository": {
27
26
  "type": "git",
28
- "url": "git+https://github.com/shrkcrft/sharkcraft.git",
27
+ "url": "git+https://github.com/sharkcraft/sharkcraft.git",
29
28
  "directory": "packages/cli"
30
29
  },
31
- "homepage": "https://github.com/shrkcrft/sharkcraft",
30
+ "homepage": "https://github.com/sharkcraft/sharkcraft",
32
31
  "bugs": {
33
- "url": "https://github.com/shrkcrft/sharkcraft/issues"
32
+ "url": "https://github.com/sharkcraft/sharkcraft/issues"
34
33
  },
35
34
  "keywords": [
36
35
  "sharkcraft",
@@ -47,25 +46,25 @@
47
46
  "typecheck": "tsc --noEmit -p tsconfig.json"
48
47
  },
49
48
  "dependencies": {
50
- "@shrkcrft/core": "^0.1.0-alpha.7",
51
- "@shrkcrft/config": "^0.1.0-alpha.7",
52
- "@shrkcrft/workspace": "^0.1.0-alpha.7",
53
- "@shrkcrft/knowledge": "^0.1.0-alpha.7",
54
- "@shrkcrft/context": "^0.1.0-alpha.7",
55
- "@shrkcrft/rules": "^0.1.0-alpha.7",
56
- "@shrkcrft/paths": "^0.1.0-alpha.7",
57
- "@shrkcrft/templates": "^0.1.0-alpha.7",
58
- "@shrkcrft/plugin-api": "^0.1.0-alpha.7",
59
- "@shrkcrft/dashboard-api": "^0.1.0-alpha.7",
60
- "@shrkcrft/pipelines": "^0.1.0-alpha.7",
61
- "@shrkcrft/presets": "^0.1.0-alpha.7",
62
- "@shrkcrft/boundaries": "^0.1.0-alpha.7",
63
- "@shrkcrft/generator": "^0.1.0-alpha.7",
64
- "@shrkcrft/importer": "^0.1.0-alpha.7",
65
- "@shrkcrft/inspector": "^0.1.0-alpha.7",
66
- "@shrkcrft/ai": "^0.1.0-alpha.7",
67
- "@shrkcrft/shared": "^0.1.0-alpha.7",
68
- "@shrkcrft/mcp-server": "^0.1.0-alpha.7"
49
+ "@shrkcrft/core": "^0.1.0-alpha.9",
50
+ "@shrkcrft/config": "^0.1.0-alpha.9",
51
+ "@shrkcrft/workspace": "^0.1.0-alpha.9",
52
+ "@shrkcrft/knowledge": "^0.1.0-alpha.9",
53
+ "@shrkcrft/context": "^0.1.0-alpha.9",
54
+ "@shrkcrft/rules": "^0.1.0-alpha.9",
55
+ "@shrkcrft/paths": "^0.1.0-alpha.9",
56
+ "@shrkcrft/templates": "^0.1.0-alpha.9",
57
+ "@shrkcrft/plugin-api": "^0.1.0-alpha.9",
58
+ "@shrkcrft/dashboard-api": "^0.1.0-alpha.9",
59
+ "@shrkcrft/pipelines": "^0.1.0-alpha.9",
60
+ "@shrkcrft/presets": "^0.1.0-alpha.9",
61
+ "@shrkcrft/boundaries": "^0.1.0-alpha.9",
62
+ "@shrkcrft/generator": "^0.1.0-alpha.9",
63
+ "@shrkcrft/importer": "^0.1.0-alpha.9",
64
+ "@shrkcrft/inspector": "^0.1.0-alpha.9",
65
+ "@shrkcrft/ai": "^0.1.0-alpha.9",
66
+ "@shrkcrft/shared": "^0.1.0-alpha.9",
67
+ "@shrkcrft/mcp-server": "^0.1.0-alpha.9"
69
68
  },
70
69
  "publishConfig": {
71
70
  "access": "public"
@@ -1,20 +0,0 @@
1
- export interface IPathsAdvisory {
2
- missingPaths: readonly string[];
3
- existingPaths: readonly string[];
4
- /** True when an advisory comment was prepended to the file. */
5
- annotated: boolean;
6
- pathsFile: string;
7
- }
8
- /**
9
- * Scan the generated `sharkcraft/paths.ts` for `path: '<x>'` references
10
- * and check each `<x>` against the live workspace. When any path is
11
- * missing, prepend a clearly-labeled comment block listing the missing
12
- * paths so the user knows which defaults to adjust.
13
- *
14
- * Idempotent — if the file already starts with the advisory marker,
15
- * it is left untouched. Non-destructive — never edits, comments, or
16
- * removes the original entries. The user is expected to revise them
17
- * based on the advisory + `shrk onboard --dry-run` output.
18
- */
19
- export declare function annotatePathsAgainstDisk(cwd: string, sharkcraftDir: string): IPathsAdvisory;
20
- //# sourceMappingURL=paths-advisory.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"paths-advisory.d.ts","sourceRoot":"","sources":["../../src/init/paths-advisory.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,GACpB,cAAc,CAwChB"}
@@ -1,88 +0,0 @@
1
- import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
- import * as nodePath from 'node:path';
3
- const ADVISORY_MARKER = '// ⚠️ Workspace-shape advisory (added by `shrk init`):';
4
- /**
5
- * Scan the generated `sharkcraft/paths.ts` for `path: '<x>'` references
6
- * and check each `<x>` against the live workspace. When any path is
7
- * missing, prepend a clearly-labeled comment block listing the missing
8
- * paths so the user knows which defaults to adjust.
9
- *
10
- * Idempotent — if the file already starts with the advisory marker,
11
- * it is left untouched. Non-destructive — never edits, comments, or
12
- * removes the original entries. The user is expected to revise them
13
- * based on the advisory + `shrk onboard --dry-run` output.
14
- */
15
- export function annotatePathsAgainstDisk(cwd, sharkcraftDir) {
16
- const pathsFile = nodePath.join(sharkcraftDir, 'paths.ts');
17
- if (!existsSync(pathsFile)) {
18
- return { missingPaths: [], existingPaths: [], annotated: false, pathsFile };
19
- }
20
- const original = readFileSync(pathsFile, 'utf8');
21
- if (original.startsWith(ADVISORY_MARKER)) {
22
- // Already annotated. Re-derive sets for caller diagnostics.
23
- return classifyOnly(cwd, pathsFile, original);
24
- }
25
- const { existing, missing } = classifyPathReferences(cwd, original);
26
- if (missing.length === 0) {
27
- return {
28
- missingPaths: [],
29
- existingPaths: existing,
30
- annotated: false,
31
- pathsFile,
32
- };
33
- }
34
- const lines = [
35
- ADVISORY_MARKER,
36
- '//',
37
- '// The following paths referenced below do NOT exist in this repository:',
38
- ...missing.map((p) => `// - ${p}`),
39
- '//',
40
- '// They are conservative defaults from the chosen preset. Adjust them to',
41
- '// match your actual layout. Run `shrk onboard --dry-run` to see what',
42
- '// the inference engine detects from your workspace.',
43
- '//',
44
- '',
45
- ];
46
- writeFileSync(pathsFile, lines.join('\n') + original, 'utf8');
47
- return {
48
- missingPaths: missing,
49
- existingPaths: existing,
50
- annotated: true,
51
- pathsFile,
52
- };
53
- }
54
- function classifyOnly(cwd, pathsFile, original) {
55
- const { existing, missing } = classifyPathReferences(cwd, original);
56
- return {
57
- missingPaths: missing,
58
- existingPaths: existing,
59
- annotated: false,
60
- pathsFile,
61
- };
62
- }
63
- function classifyPathReferences(cwd, source) {
64
- // Match `path: '<x>'` / `path: "<x>"`. Ignore obvious code-context
65
- // references (e.g. inside template literals); we only consume the
66
- // first plain-string occurrence per entry.
67
- const re = /\bpath\s*:\s*['"]([^'"\n]+)['"]/g;
68
- const seen = new Set();
69
- let m;
70
- while ((m = re.exec(source)) !== null) {
71
- if (m[1])
72
- seen.add(m[1]);
73
- }
74
- const existing = [];
75
- const missing = [];
76
- for (const p of [...seen].sort()) {
77
- if (isReachable(cwd, p))
78
- existing.push(p);
79
- else
80
- missing.push(p);
81
- }
82
- return { existing, missing };
83
- }
84
- function isReachable(cwd, p) {
85
- // Absolute or rooted-relative — resolve as-is.
86
- const full = nodePath.isAbsolute(p) ? p : nodePath.resolve(cwd, p);
87
- return existsSync(full);
88
- }