@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.
- package/README.md +1 -1
- package/dist/commands/boundaries.command.d.ts.map +1 -1
- package/dist/commands/boundaries.command.js +12 -0
- package/dist/commands/check.command.d.ts.map +1 -1
- package/dist/commands/check.command.js +30 -20
- package/dist/commands/command-catalog.d.ts.map +1 -1
- package/dist/commands/command-catalog.js +14 -1
- package/dist/commands/doctor.command.d.ts.map +1 -1
- package/dist/commands/doctor.command.js +7 -8
- package/dist/commands/help.command.d.ts.map +1 -1
- package/dist/commands/help.command.js +8 -6
- package/dist/commands/init.command.d.ts.map +1 -1
- package/dist/commands/init.command.js +13 -37
- package/dist/commands/mcp.command.d.ts.map +1 -1
- package/dist/commands/mcp.command.js +131 -2
- package/dist/commands/onboard.command.d.ts.map +1 -1
- package/dist/commands/onboard.command.js +15 -3
- package/dist/commands/packs-new.d.ts.map +1 -1
- package/dist/commands/packs-new.js +10 -3
- package/dist/commands/packs.command.d.ts.map +1 -1
- package/dist/commands/packs.command.js +17 -3
- package/dist/commands/review.command.d.ts.map +1 -1
- package/dist/commands/review.command.js +28 -2
- package/dist/init/init-templates.d.ts.map +1 -1
- package/dist/init/init-templates.js +113 -133
- package/dist/main.d.ts +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +35 -13
- package/dist/output/failure-hints.d.ts +9 -1
- package/dist/output/failure-hints.d.ts.map +1 -1
- package/dist/output/failure-hints.js +8 -2
- package/dist/output/watch-loop.d.ts +1 -9
- package/dist/output/watch-loop.d.ts.map +1 -1
- package/dist/output/watch-loop.js +3 -13
- package/dist/schemas/json-schemas.d.ts +36 -36
- package/dist/schemas/json-schemas.js +36 -36
- package/dist/surface/about.d.ts.map +1 -1
- package/dist/surface/about.js +15 -37
- package/dist/surface/no-args-landing.d.ts.map +1 -1
- package/dist/surface/no-args-landing.js +13 -9
- package/dist/surface/surface-config-writer.d.ts.map +1 -1
- package/dist/surface/surface-config-writer.js +11 -23
- package/package.json +25 -26
- package/dist/init/paths-advisory.d.ts +0 -20
- package/dist/init/paths-advisory.d.ts.map +0 -1
- package/dist/init/paths-advisory.js +0 -88
package/dist/surface/about.js
CHANGED
|
@@ -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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
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,
|
|
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} —
|
|
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('
|
|
25
|
-
lines.push(' shrk
|
|
26
|
-
lines.push('
|
|
27
|
-
lines.push(' shrk
|
|
28
|
-
lines.push('
|
|
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('
|
|
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;
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
//
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
//
|
|
130
|
-
|
|
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.
|
|
4
|
-
"description": "SharkCraft CLI (`shrk`):
|
|
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.
|
|
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/
|
|
27
|
+
"url": "git+https://github.com/sharkcraft/sharkcraft.git",
|
|
29
28
|
"directory": "packages/cli"
|
|
30
29
|
},
|
|
31
|
-
"homepage": "https://github.com/
|
|
30
|
+
"homepage": "https://github.com/sharkcraft/sharkcraft",
|
|
32
31
|
"bugs": {
|
|
33
|
-
"url": "https://github.com/
|
|
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.
|
|
51
|
-
"@shrkcrft/config": "^0.1.0-alpha.
|
|
52
|
-
"@shrkcrft/workspace": "^0.1.0-alpha.
|
|
53
|
-
"@shrkcrft/knowledge": "^0.1.0-alpha.
|
|
54
|
-
"@shrkcrft/context": "^0.1.0-alpha.
|
|
55
|
-
"@shrkcrft/rules": "^0.1.0-alpha.
|
|
56
|
-
"@shrkcrft/paths": "^0.1.0-alpha.
|
|
57
|
-
"@shrkcrft/templates": "^0.1.0-alpha.
|
|
58
|
-
"@shrkcrft/plugin-api": "^0.1.0-alpha.
|
|
59
|
-
"@shrkcrft/dashboard-api": "^0.1.0-alpha.
|
|
60
|
-
"@shrkcrft/pipelines": "^0.1.0-alpha.
|
|
61
|
-
"@shrkcrft/presets": "^0.1.0-alpha.
|
|
62
|
-
"@shrkcrft/boundaries": "^0.1.0-alpha.
|
|
63
|
-
"@shrkcrft/generator": "^0.1.0-alpha.
|
|
64
|
-
"@shrkcrft/importer": "^0.1.0-alpha.
|
|
65
|
-
"@shrkcrft/inspector": "^0.1.0-alpha.
|
|
66
|
-
"@shrkcrft/ai": "^0.1.0-alpha.
|
|
67
|
-
"@shrkcrft/shared": "^0.1.0-alpha.
|
|
68
|
-
"@shrkcrft/mcp-server": "^0.1.0-alpha.
|
|
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
|
-
}
|