@specship/specship-win32-arm64 0.25.0 → 0.28.0
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/bin/specship.cmd +31 -1
- package/lib/dist/activation/cheatsheet.d.ts +17 -1
- package/lib/dist/activation/cheatsheet.d.ts.map +1 -1
- package/lib/dist/activation/cheatsheet.js +47 -3
- package/lib/dist/activation/cheatsheet.js.map +1 -1
- package/lib/dist/activation/hook-output.d.ts +80 -0
- package/lib/dist/activation/hook-output.d.ts.map +1 -0
- package/lib/dist/activation/hook-output.js +103 -0
- package/lib/dist/activation/hook-output.js.map +1 -0
- package/lib/dist/activation/search-intercept.d.ts +60 -29
- package/lib/dist/activation/search-intercept.d.ts.map +1 -1
- package/lib/dist/activation/search-intercept.js +159 -55
- package/lib/dist/activation/search-intercept.js.map +1 -1
- package/lib/dist/activation/steering.d.ts +8 -10
- package/lib/dist/activation/steering.d.ts.map +1 -1
- package/lib/dist/activation/steering.js +21 -6
- package/lib/dist/activation/steering.js.map +1 -1
- package/lib/dist/behaviour/behaviour-surface.d.ts +47 -0
- package/lib/dist/behaviour/behaviour-surface.d.ts.map +1 -1
- package/lib/dist/behaviour/behaviour-surface.js +108 -2
- package/lib/dist/behaviour/behaviour-surface.js.map +1 -1
- package/lib/dist/bin/node-version-check.d.ts +22 -7
- package/lib/dist/bin/node-version-check.d.ts.map +1 -1
- package/lib/dist/bin/node-version-check.js +39 -9
- package/lib/dist/bin/node-version-check.js.map +1 -1
- package/lib/dist/bin/specship.js +762 -81
- package/lib/dist/bin/specship.js.map +1 -1
- package/lib/dist/commands/specship/learn.md +22 -0
- package/lib/dist/commands/specship/spec.md +12 -0
- package/lib/dist/db/sqlite-adapter.d.ts +7 -5
- package/lib/dist/db/sqlite-adapter.d.ts.map +1 -1
- package/lib/dist/db/sqlite-adapter.js +11 -9
- package/lib/dist/db/sqlite-adapter.js.map +1 -1
- package/lib/dist/enforce/changed-files.d.ts +11 -0
- package/lib/dist/enforce/changed-files.d.ts.map +1 -1
- package/lib/dist/enforce/changed-files.js +42 -0
- package/lib/dist/enforce/changed-files.js.map +1 -1
- package/lib/dist/enforce/enforce.d.ts +25 -1
- package/lib/dist/enforce/enforce.d.ts.map +1 -1
- package/lib/dist/enforce/enforce.js +58 -3
- package/lib/dist/enforce/enforce.js.map +1 -1
- package/lib/dist/enforce/mutation.d.ts +46 -0
- package/lib/dist/enforce/mutation.d.ts.map +1 -0
- package/lib/dist/enforce/mutation.js +104 -0
- package/lib/dist/enforce/mutation.js.map +1 -0
- package/lib/dist/enforce/suppressions.d.ts +33 -0
- package/lib/dist/enforce/suppressions.d.ts.map +1 -0
- package/lib/dist/enforce/suppressions.js +159 -0
- package/lib/dist/enforce/suppressions.js.map +1 -0
- package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
- package/lib/dist/extraction/specs/markdown-spec-extractor.js +16 -2
- package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
- package/lib/dist/graph/spec-coverage.d.ts +57 -1
- package/lib/dist/graph/spec-coverage.d.ts.map +1 -1
- package/lib/dist/graph/spec-coverage.js +129 -5
- package/lib/dist/graph/spec-coverage.js.map +1 -1
- package/lib/dist/health/smoke-check.js +2 -2
- package/lib/dist/health/smoke-check.js.map +1 -1
- package/lib/dist/index.d.ts +8 -3
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +65 -9
- package/lib/dist/index.js.map +1 -1
- package/lib/dist/installer/gemini-commands.d.ts +107 -0
- package/lib/dist/installer/gemini-commands.d.ts.map +1 -0
- package/lib/dist/installer/gemini-commands.js +264 -0
- package/lib/dist/installer/gemini-commands.js.map +1 -0
- package/lib/dist/installer/index.d.ts +23 -1
- package/lib/dist/installer/index.d.ts.map +1 -1
- package/lib/dist/installer/index.js +22 -3
- package/lib/dist/installer/index.js.map +1 -1
- package/lib/dist/installer/install-defaults.d.ts +19 -0
- package/lib/dist/installer/install-defaults.d.ts.map +1 -1
- package/lib/dist/installer/install-defaults.js +28 -0
- package/lib/dist/installer/install-defaults.js.map +1 -1
- package/lib/dist/installer/instructions-template.d.ts +22 -0
- package/lib/dist/installer/instructions-template.d.ts.map +1 -1
- package/lib/dist/installer/instructions-template.js +37 -1
- package/lib/dist/installer/instructions-template.js.map +1 -1
- package/lib/dist/installer/targets/claude.d.ts +4 -0
- package/lib/dist/installer/targets/claude.d.ts.map +1 -1
- package/lib/dist/installer/targets/claude.js +8 -25
- package/lib/dist/installer/targets/claude.js.map +1 -1
- package/lib/dist/installer/targets/gemini.d.ts +85 -12
- package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
- package/lib/dist/installer/targets/gemini.js +527 -30
- package/lib/dist/installer/targets/gemini.js.map +1 -1
- package/lib/dist/installer/targets/shared.d.ts +13 -0
- package/lib/dist/installer/targets/shared.d.ts.map +1 -1
- package/lib/dist/installer/targets/shared.js +18 -0
- package/lib/dist/installer/targets/shared.js.map +1 -1
- package/lib/dist/installer/targets/types.d.ts +12 -0
- package/lib/dist/installer/targets/types.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.d.ts +71 -4
- package/lib/dist/jira/auto-publish.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.js +186 -17
- package/lib/dist/jira/auto-publish.js.map +1 -1
- package/lib/dist/jira/reconcile.d.ts +24 -1
- package/lib/dist/jira/reconcile.d.ts.map +1 -1
- package/lib/dist/jira/reconcile.js +46 -2
- package/lib/dist/jira/reconcile.js.map +1 -1
- package/lib/dist/jira/repo-config.d.ts +9 -0
- package/lib/dist/jira/repo-config.d.ts.map +1 -1
- package/lib/dist/jira/repo-config.js +11 -0
- package/lib/dist/jira/repo-config.js.map +1 -1
- package/lib/dist/jira/types.d.ts +7 -0
- package/lib/dist/jira/types.d.ts.map +1 -1
- package/lib/dist/jira/types.js.map +1 -1
- package/lib/dist/knowledge/enforce.d.ts +75 -0
- package/lib/dist/knowledge/enforce.d.ts.map +1 -0
- package/lib/dist/knowledge/enforce.js +250 -0
- package/lib/dist/knowledge/enforce.js.map +1 -0
- package/lib/dist/knowledge/facts.d.ts +33 -0
- package/lib/dist/knowledge/facts.d.ts.map +1 -0
- package/lib/dist/knowledge/facts.js +117 -0
- package/lib/dist/knowledge/facts.js.map +1 -0
- package/lib/dist/knowledge/proposals.d.ts +88 -0
- package/lib/dist/knowledge/proposals.d.ts.map +1 -0
- package/lib/dist/knowledge/proposals.js +360 -0
- package/lib/dist/knowledge/proposals.js.map +1 -0
- package/lib/dist/knowledge/stale.d.ts +64 -0
- package/lib/dist/knowledge/stale.d.ts.map +1 -0
- package/lib/dist/knowledge/stale.js +174 -0
- package/lib/dist/knowledge/stale.js.map +1 -0
- package/lib/dist/mcp/gemini-session.d.ts +50 -0
- package/lib/dist/mcp/gemini-session.d.ts.map +1 -0
- package/lib/dist/mcp/gemini-session.js +159 -0
- package/lib/dist/mcp/gemini-session.js.map +1 -0
- package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
- package/lib/dist/mcp/jira-tools.js +25 -0
- package/lib/dist/mcp/jira-tools.js.map +1 -1
- package/lib/dist/mcp/model-context.d.ts +22 -9
- package/lib/dist/mcp/model-context.d.ts.map +1 -1
- package/lib/dist/mcp/model-context.js +35 -13
- package/lib/dist/mcp/model-context.js.map +1 -1
- package/lib/dist/mcp/proxy.js +1 -1
- package/lib/dist/mcp/proxy.js.map +1 -1
- package/lib/dist/mcp/server-instructions.d.ts +16 -15
- package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
- package/lib/dist/mcp/server-instructions.js +67 -1
- package/lib/dist/mcp/server-instructions.js.map +1 -1
- package/lib/dist/mcp/session.js +1 -1
- package/lib/dist/mcp/session.js.map +1 -1
- package/lib/dist/mcp/spec-tools.d.ts +9 -1
- package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
- package/lib/dist/mcp/spec-tools.js +69 -21
- package/lib/dist/mcp/spec-tools.js.map +1 -1
- package/lib/dist/mcp/tools.d.ts +37 -1
- package/lib/dist/mcp/tools.d.ts.map +1 -1
- package/lib/dist/mcp/tools.js +120 -9
- package/lib/dist/mcp/tools.js.map +1 -1
- package/lib/dist/pulse/pulse.d.ts +93 -0
- package/lib/dist/pulse/pulse.d.ts.map +1 -0
- package/lib/dist/pulse/pulse.js +401 -0
- package/lib/dist/pulse/pulse.js.map +1 -0
- package/lib/dist/reflect/apply.d.ts.map +1 -1
- package/lib/dist/reflect/apply.js +38 -3
- package/lib/dist/reflect/apply.js.map +1 -1
- package/lib/dist/reflect/auto-sweep.d.ts +26 -0
- package/lib/dist/reflect/auto-sweep.d.ts.map +1 -0
- package/lib/dist/reflect/auto-sweep.js +90 -0
- package/lib/dist/reflect/auto-sweep.js.map +1 -0
- package/lib/dist/reflect/cli.d.ts +62 -0
- package/lib/dist/reflect/cli.d.ts.map +1 -0
- package/lib/dist/reflect/cli.js +163 -0
- package/lib/dist/reflect/cli.js.map +1 -0
- package/lib/dist/reflect/miner.d.ts.map +1 -1
- package/lib/dist/reflect/miner.js +119 -0
- package/lib/dist/reflect/miner.js.map +1 -1
- package/lib/dist/reflect/sweep.d.ts +1 -0
- package/lib/dist/reflect/sweep.d.ts.map +1 -1
- package/lib/dist/reflect/sweep.js +62 -13
- package/lib/dist/reflect/sweep.js.map +1 -1
- package/lib/dist/reflect/targets.d.ts +2 -0
- package/lib/dist/reflect/targets.d.ts.map +1 -1
- package/lib/dist/reflect/targets.js +33 -0
- package/lib/dist/reflect/targets.js.map +1 -1
- package/lib/dist/reflect/types.d.ts +19 -2
- package/lib/dist/reflect/types.d.ts.map +1 -1
- package/lib/dist/resolution/test-title-links.d.ts.map +1 -1
- package/lib/dist/resolution/test-title-links.js +3 -14
- package/lib/dist/resolution/test-title-links.js.map +1 -1
- package/lib/dist/server/routes/claude.js +15 -7
- package/lib/dist/server/routes/knowledge.js +118 -0
- package/lib/dist/server/server.js +2 -0
- package/lib/dist/spec-lint/lint.d.ts +1 -1
- package/lib/dist/spec-lint/lint.d.ts.map +1 -1
- package/lib/dist/spec-lint/lint.js +63 -2
- package/lib/dist/spec-lint/lint.js.map +1 -1
- package/lib/dist/spec-quality/criterion-ids.d.ts +13 -0
- package/lib/dist/spec-quality/criterion-ids.d.ts.map +1 -0
- package/lib/dist/spec-quality/criterion-ids.js +38 -0
- package/lib/dist/spec-quality/criterion-ids.js.map +1 -0
- package/lib/dist/spec-quality/evidence-kind.d.ts +54 -0
- package/lib/dist/spec-quality/evidence-kind.d.ts.map +1 -0
- package/lib/dist/spec-quality/evidence-kind.js +183 -0
- package/lib/dist/spec-quality/evidence-kind.js.map +1 -0
- package/lib/dist/spec-quality/link-persist.d.ts +65 -0
- package/lib/dist/spec-quality/link-persist.d.ts.map +1 -0
- package/lib/dist/spec-quality/link-persist.js +249 -0
- package/lib/dist/spec-quality/link-persist.js.map +1 -0
- package/lib/dist/spec-quality/plan-scope.d.ts +38 -0
- package/lib/dist/spec-quality/plan-scope.d.ts.map +1 -0
- package/lib/dist/spec-quality/plan-scope.js +129 -0
- package/lib/dist/spec-quality/plan-scope.js.map +1 -0
- package/lib/dist/spec-quality/postcheck.d.ts +85 -0
- package/lib/dist/spec-quality/postcheck.d.ts.map +1 -0
- package/lib/dist/spec-quality/postcheck.js +390 -0
- package/lib/dist/spec-quality/postcheck.js.map +1 -0
- package/lib/dist/spec-quality/readiness.d.ts +72 -0
- package/lib/dist/spec-quality/readiness.d.ts.map +1 -0
- package/lib/dist/spec-quality/readiness.js +226 -0
- package/lib/dist/spec-quality/readiness.js.map +1 -0
- package/lib/dist/workflows/agents/claude.d.ts +16 -0
- package/lib/dist/workflows/agents/claude.d.ts.map +1 -0
- package/lib/dist/workflows/agents/claude.js +82 -0
- package/lib/dist/workflows/agents/claude.js.map +1 -0
- package/lib/dist/workflows/agents/gemini.d.ts +21 -0
- package/lib/dist/workflows/agents/gemini.d.ts.map +1 -0
- package/lib/dist/workflows/agents/gemini.js +124 -0
- package/lib/dist/workflows/agents/gemini.js.map +1 -0
- package/lib/dist/workflows/agents/index.d.ts +28 -0
- package/lib/dist/workflows/agents/index.d.ts.map +1 -0
- package/lib/dist/workflows/agents/index.js +104 -0
- package/lib/dist/workflows/agents/index.js.map +1 -0
- package/lib/dist/workflows/agents/types.d.ts +55 -0
- package/lib/dist/workflows/agents/types.d.ts.map +1 -0
- package/lib/dist/workflows/agents/types.js +46 -0
- package/lib/dist/workflows/agents/types.js.map +1 -0
- package/lib/dist/workflows/batch.d.ts +63 -0
- package/lib/dist/workflows/batch.d.ts.map +1 -0
- package/lib/dist/workflows/batch.js +151 -0
- package/lib/dist/workflows/batch.js.map +1 -0
- package/lib/dist/workflows/defaults/claude-design-implement.yaml +3 -4
- package/lib/dist/workflows/defaults/spec-author.yaml +11 -9
- package/lib/dist/workflows/defaults/spec-implement-mixed.yaml +21 -436
- package/lib/dist/workflows/defaults/spec-implement.yaml +465 -46
- package/lib/dist/workflows/discovery.d.ts +13 -0
- package/lib/dist/workflows/discovery.d.ts.map +1 -1
- package/lib/dist/workflows/discovery.js +79 -17
- package/lib/dist/workflows/discovery.js.map +1 -1
- package/lib/dist/workflows/executor.d.ts +18 -0
- package/lib/dist/workflows/executor.d.ts.map +1 -1
- package/lib/dist/workflows/executor.js +130 -33
- package/lib/dist/workflows/executor.js.map +1 -1
- package/lib/dist/workflows/gc.d.ts +50 -0
- package/lib/dist/workflows/gc.d.ts.map +1 -0
- package/lib/dist/workflows/gc.js +120 -0
- package/lib/dist/workflows/gc.js.map +1 -0
- package/lib/dist/workflows/merge-queue.d.ts +64 -0
- package/lib/dist/workflows/merge-queue.d.ts.map +1 -0
- package/lib/dist/workflows/merge-queue.js +162 -0
- package/lib/dist/workflows/merge-queue.js.map +1 -0
- package/lib/dist/workflows/runners/approval.d.ts +1 -1
- package/lib/dist/workflows/runners/approval.d.ts.map +1 -1
- package/lib/dist/workflows/runners/approval.js +11 -2
- package/lib/dist/workflows/runners/approval.js.map +1 -1
- package/lib/dist/workflows/runners/bash.d.ts +15 -0
- package/lib/dist/workflows/runners/bash.d.ts.map +1 -1
- package/lib/dist/workflows/runners/bash.js +50 -1
- package/lib/dist/workflows/runners/bash.js.map +1 -1
- package/lib/dist/workflows/runners/prompt.d.ts +16 -41
- package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
- package/lib/dist/workflows/runners/prompt.js +55 -120
- package/lib/dist/workflows/runners/prompt.js.map +1 -1
- package/lib/dist/workflows/runners/types.d.ts +12 -0
- package/lib/dist/workflows/runners/types.d.ts.map +1 -1
- package/lib/dist/workflows/schemas/workflow.d.ts +17 -0
- package/lib/dist/workflows/schemas/workflow.d.ts.map +1 -1
- package/lib/dist/workflows/schemas/workflow.js +27 -0
- package/lib/dist/workflows/schemas/workflow.js.map +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +2 -2
- package/package.json +5 -3
- package/node.exe +0 -4
package/bin/specship.cmd
CHANGED
|
@@ -1 +1,31 @@
|
|
|
1
|
-
@
|
|
1
|
+
@echo off
|
|
2
|
+
setlocal
|
|
3
|
+
set "NODE="
|
|
4
|
+
for /f "delims=" %%i in ('where node 2^>nul') do if not defined NODE set "NODE=%%i"
|
|
5
|
+
if not defined NODE (
|
|
6
|
+
echo specship: Node.js is required ^(^>^= 22.5.0, ^< 25.0.0^) but no 'node' was found on PATH.>&2
|
|
7
|
+
echo specship: install it from https://nodejs.org>&2
|
|
8
|
+
exit /b 1
|
|
9
|
+
)
|
|
10
|
+
set "NODEVER="
|
|
11
|
+
rem Query the version through PATH (`node`, not "%NODE%") so a Program Files
|
|
12
|
+
rem path with spaces doesn't hit cmd's nested-quote parsing — `where node`
|
|
13
|
+
rem already proved PATH resolves to this same executable.
|
|
14
|
+
for /f "delims=" %%v in ('node -v 2^>nul') do set "NODEVER=%%v"
|
|
15
|
+
set "NMAJ="
|
|
16
|
+
set "NMIN="
|
|
17
|
+
for /f "tokens=1,2 delims=v." %%a in ("%NODEVER%") do (
|
|
18
|
+
set "NMAJ=%%a"
|
|
19
|
+
set "NMIN=%%b"
|
|
20
|
+
)
|
|
21
|
+
if not defined NMAJ goto :badnode
|
|
22
|
+
if %NMAJ% LSS 22 goto :badnode
|
|
23
|
+
if %NMAJ% GEQ 25 goto :badnode
|
|
24
|
+
if %NMAJ% EQU 22 if %NMIN% LSS 5 goto :badnode
|
|
25
|
+
rem --liftoff-only: avoid the V8 turboshaft WASM Zone OOM (issues #293/#298).
|
|
26
|
+
"%NODE%" --liftoff-only "%~dp0..\lib\dist\bin\specship.js" %*
|
|
27
|
+
exit /b %ERRORLEVEL%
|
|
28
|
+
:badnode
|
|
29
|
+
echo specship: Node.js ^>^= 22.5.0 and ^< 25.0.0 is required (found %NODEVER% at %NODE%).>&2
|
|
30
|
+
echo specship: install a supported version from https://nodejs.org>&2
|
|
31
|
+
exit /b 1
|
|
@@ -27,7 +27,23 @@ export declare const CHEATSHEET_TEXT: string;
|
|
|
27
27
|
* out via `SPECSHIP_NO_CHEATSHEET` (REQ-CHEAT-004.A1). An unset or empty
|
|
28
28
|
* variable prints normally (REQ-CHEAT-004.A2).
|
|
29
29
|
*/
|
|
30
|
-
export declare function buildCheatsheetPayload(env?: NodeJS.ProcessEnv): {
|
|
30
|
+
export declare function buildCheatsheetPayload(env?: NodeJS.ProcessEnv, extras?: CheatsheetExtras): {
|
|
31
31
|
systemMessage: string;
|
|
32
32
|
} | null;
|
|
33
|
+
/** Optional learned-state extras the CLI resolves before rendering. */
|
|
34
|
+
export interface CheatsheetExtras {
|
|
35
|
+
/** Raw content of .specship/conventions.md (null/empty → no section). */
|
|
36
|
+
conventions?: string | null;
|
|
37
|
+
/** Count of open reflection proposals (0/undefined → no line). */
|
|
38
|
+
openProposals?: number;
|
|
39
|
+
}
|
|
40
|
+
/** Max convention bullets injected per session (REQ-ALEARN-002.A2). */
|
|
41
|
+
export declare const CONVENTIONS_BUDGET_LINES = 8;
|
|
42
|
+
/**
|
|
43
|
+
* Render the confirmed conventions as a budget-bounded cheatsheet section
|
|
44
|
+
* (REQ-ALEARN-002). Rules are the `## <title>` lines of the SpecShip-written
|
|
45
|
+
* marker blocks plus their first body line; over budget, the rest collapse
|
|
46
|
+
* into a "+N more" pointer. No blocks → empty string (nothing injected).
|
|
47
|
+
*/
|
|
48
|
+
export declare function renderConventionsSection(content: string, budget: number): string;
|
|
33
49
|
//# sourceMappingURL=cheatsheet.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cheatsheet.d.ts","sourceRoot":"","sources":["../../src/activation/cheatsheet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,eAAe,QAqBhB,CAAC;AAEb;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,GAAE,MAAM,CAAC,UAAwB,
|
|
1
|
+
{"version":3,"file":"cheatsheet.d.ts","sourceRoot":"","sources":["../../src/activation/cheatsheet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,eAAe,QAqBhB,CAAC;AAEb;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,MAAM,GAAE,gBAAqB,GAC5B;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAkBlC;AAED,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,uEAAuE;AACvE,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAmBhF"}
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
* and the `SPECSHIP_NO_CHEATSHEET` opt-out below, not by this module.
|
|
16
16
|
*/
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.CHEATSHEET_TEXT = void 0;
|
|
18
|
+
exports.CONVENTIONS_BUDGET_LINES = exports.CHEATSHEET_TEXT = void 0;
|
|
19
19
|
exports.buildCheatsheetPayload = buildCheatsheetPayload;
|
|
20
|
+
exports.renderConventionsSection = renderConventionsSection;
|
|
20
21
|
/**
|
|
21
22
|
* The cheat-sheet rendered to the user. Names only user-facing commands, tools,
|
|
22
23
|
* and env vars — no internal file paths, symbol names, or benchmark figures
|
|
@@ -52,9 +53,52 @@ exports.CHEATSHEET_TEXT = [
|
|
|
52
53
|
* out via `SPECSHIP_NO_CHEATSHEET` (REQ-CHEAT-004.A1). An unset or empty
|
|
53
54
|
* variable prints normally (REQ-CHEAT-004.A2).
|
|
54
55
|
*/
|
|
55
|
-
function buildCheatsheetPayload(env = process.env) {
|
|
56
|
+
function buildCheatsheetPayload(env = process.env, extras = {}) {
|
|
56
57
|
if (env.SPECSHIP_NO_CHEATSHEET)
|
|
57
58
|
return null;
|
|
58
|
-
|
|
59
|
+
const parts = [exports.CHEATSHEET_TEXT];
|
|
60
|
+
// Learned project conventions (REQ-ALEARN-002): absent/empty file → output
|
|
61
|
+
// is byte-identical to the base cheatsheet (A1).
|
|
62
|
+
if (extras.conventions) {
|
|
63
|
+
const section = renderConventionsSection(extras.conventions, exports.CONVENTIONS_BUDGET_LINES);
|
|
64
|
+
if (section)
|
|
65
|
+
parts.push('', section);
|
|
66
|
+
}
|
|
67
|
+
// Open learned proposals awaiting review (REQ-ALEARN-004.A2): one line,
|
|
68
|
+
// only when the count is positive.
|
|
69
|
+
if (extras.openProposals && extras.openProposals > 0) {
|
|
70
|
+
parts.push('', `🧠 ${extras.openProposals} learned proposal(s) awaiting review — run \`specship reflect\` to review them.`);
|
|
71
|
+
}
|
|
72
|
+
return { systemMessage: parts.join('\n') };
|
|
73
|
+
}
|
|
74
|
+
/** Max convention bullets injected per session (REQ-ALEARN-002.A2). */
|
|
75
|
+
exports.CONVENTIONS_BUDGET_LINES = 8;
|
|
76
|
+
/**
|
|
77
|
+
* Render the confirmed conventions as a budget-bounded cheatsheet section
|
|
78
|
+
* (REQ-ALEARN-002). Rules are the `## <title>` lines of the SpecShip-written
|
|
79
|
+
* marker blocks plus their first body line; over budget, the rest collapse
|
|
80
|
+
* into a "+N more" pointer. No blocks → empty string (nothing injected).
|
|
81
|
+
*/
|
|
82
|
+
function renderConventionsSection(content, budget) {
|
|
83
|
+
const rules = [];
|
|
84
|
+
const re = /<!-- SPECSHIP_LEARNING:[^>]+ -->\n## ([^\n]+)\n+([^\n<]*)/g;
|
|
85
|
+
let m;
|
|
86
|
+
while ((m = re.exec(content)) !== null) {
|
|
87
|
+
const title = (m[1] ?? '').replace(/^Convention:\s*/i, '').trim();
|
|
88
|
+
const body = (m[2] ?? '').trim();
|
|
89
|
+
// The body line is the rule; the title is a summary of it. Prefer the
|
|
90
|
+
// body (the user's own words), fall back to the title.
|
|
91
|
+
rules.push(body || title);
|
|
92
|
+
}
|
|
93
|
+
if (rules.length === 0)
|
|
94
|
+
return '';
|
|
95
|
+
const shown = rules.slice(0, budget);
|
|
96
|
+
const lines = ['Project conventions (learned — .specship/conventions.md):'];
|
|
97
|
+
for (const r of shown)
|
|
98
|
+
lines.push(`• ${r.length > 100 ? r.slice(0, 97) + '…' : r}`);
|
|
99
|
+
if (rules.length > shown.length) {
|
|
100
|
+
lines.push(` +${rules.length - shown.length} more — see .specship/conventions.md`);
|
|
101
|
+
}
|
|
102
|
+
return lines.join('\n');
|
|
59
103
|
}
|
|
60
104
|
//# sourceMappingURL=cheatsheet.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cheatsheet.js","sourceRoot":"","sources":["../../src/activation/cheatsheet.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAsCH,
|
|
1
|
+
{"version":3,"file":"cheatsheet.js","sourceRoot":"","sources":["../../src/activation/cheatsheet.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAsCH,wDAqBC;AAmBD,4DAmBC;AA/FD;;;;;GAKG;AACU,QAAA,eAAe,GAAG;IAC7B,2EAA2E;IAC3E,EAAE;IACF,kCAAkC;IAClC,+EAA+E;IAC/E,sFAAsF;IACtF,+EAA+E;IAC/E,qFAAqF;IACrF,EAAE;IACF,+BAA+B;IAC/B,mFAAmF;IACnF,mFAAmF;IACnF,8EAA8E;IAC9E,EAAE;IACF,+EAA+E;IAC/E,kFAAkF;IAClF,kFAAkF;IAClF,sDAAsD;IACtD,uFAAuF;IACvF,EAAE;IACF,oFAAoF;CACrF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;;;;GAMG;AACH,SAAgB,sBAAsB,CACpC,MAAyB,OAAO,CAAC,GAAG,EACpC,SAA2B,EAAE;IAE7B,IAAI,GAAG,CAAC,sBAAsB;QAAE,OAAO,IAAI,CAAC;IAC5C,MAAM,KAAK,GAAG,CAAC,uBAAe,CAAC,CAAC;IAChC,2EAA2E;IAC3E,iDAAiD;IACjD,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,wBAAwB,CAAC,MAAM,CAAC,WAAW,EAAE,gCAAwB,CAAC,CAAC;QACvF,IAAI,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,wEAAwE;IACxE,mCAAmC;IACnC,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;QACrD,KAAK,CAAC,IAAI,CACR,EAAE,EACF,MAAM,MAAM,CAAC,aAAa,iFAAiF,CAC5G,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC7C,CAAC;AAUD,uEAAuE;AAC1D,QAAA,wBAAwB,GAAG,CAAC,CAAC;AAE1C;;;;;GAKG;AACH,SAAgB,wBAAwB,CAAC,OAAe,EAAE,MAAc;IACtE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,EAAE,GAAG,4DAA4D,CAAC;IACxE,IAAI,CAAyB,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACjC,sEAAsE;QACtE,uDAAuD;QACvD,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,CAAC,2DAA2D,CAAC,CAAC;IAC5E,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpF,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,sCAAsC,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for hook commands (`steer-nudge`, `spec-nudge`,
|
|
3
|
+
* `search-intercept`) that read a hook payload from stdin and emit a
|
|
4
|
+
* `hookSpecificOutput.additionalContext` line.
|
|
5
|
+
*
|
|
6
|
+
* The `hook_event_name` field is echoed back from the payload rather than
|
|
7
|
+
* hard-coded so the same CLI command serves Claude Code's event names
|
|
8
|
+
* (`UserPromptSubmit`, `PreToolUse`) AND Gemini CLI's (`BeforeAgent`,
|
|
9
|
+
* `BeforeTool`) — the installer wires them to the same binaries and the
|
|
10
|
+
* payload tells the command which host called it (REQ-GEMINI-010).
|
|
11
|
+
*/
|
|
12
|
+
export interface HookPayload {
|
|
13
|
+
prompt: string;
|
|
14
|
+
cwd: string | null;
|
|
15
|
+
sessionId: string | null;
|
|
16
|
+
transcriptPath: string | null;
|
|
17
|
+
hookEventName: string | null;
|
|
18
|
+
}
|
|
19
|
+
export declare function parseHookPayload(raw: string): HookPayload;
|
|
20
|
+
/**
|
|
21
|
+
* Build a `hookSpecificOutput.additionalContext` JSON line. `eventName` is
|
|
22
|
+
* echoed from the payload when present (so Gemini's `BeforeAgent` /
|
|
23
|
+
* `BeforeTool` names round-trip) and falls back to `fallbackEventName` only
|
|
24
|
+
* when the payload carries none.
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildHookAdditionalContext(additionalContext: string, eventName: string | null, fallbackEventName: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* A blocking decision for a host whose before-tool hook reads a TOP-LEVEL
|
|
29
|
+
* `decision` (Gemini CLI 0.28.0 `BeforeToolHookOutput.isBlockingDecision`
|
|
30
|
+
* checks `this.decision === 'block' || 'deny'`; nested under
|
|
31
|
+
* `hookSpecificOutput` it is ignored). Only emitted for hosts whose traits
|
|
32
|
+
* report `supportsBeforeToolDeny`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildHookDenyDecision(reason: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Host-shaped traits derived from a hook payload — the one place that peeks
|
|
37
|
+
* at `hook_event_name` to decide whether we're serving Claude Code or Gemini
|
|
38
|
+
* CLI. Shared code (`search-intercept`, `bin/specship`) consumes the traits
|
|
39
|
+
* and never event-name-sniffs itself, keeping it host-agnostic per the
|
|
40
|
+
* project's agent-agnostic rule.
|
|
41
|
+
*
|
|
42
|
+
* - `specshipToolMarkers` — substrings naming a specship tool_use record.
|
|
43
|
+
* Claude exposes our server as `mcp__specship__<tool>`; Gemini shows
|
|
44
|
+
* the model the bare tool name (`specship_explore`), qualifying it as
|
|
45
|
+
* `specship__<tool>` only on a name collision.
|
|
46
|
+
* - `transcriptFormat` — Claude writes JSONL (one record per line); Gemini's
|
|
47
|
+
* `ChatRecordingService` writes one pretty-printed JSON doc with
|
|
48
|
+
* `messages[].toolCalls[].name`.
|
|
49
|
+
* - `supportsBeforeToolDeny` — whether the host reads a top-level
|
|
50
|
+
* `{decision:'deny'}` on its BeforeTool-equivalent. Gemini 0.28.0+
|
|
51
|
+
* `BeforeToolHookOutput.isBlockingDecision` does; Claude's PreToolUse
|
|
52
|
+
* uses a different shape so we never emit deny for Claude.
|
|
53
|
+
*/
|
|
54
|
+
export interface HostTraits {
|
|
55
|
+
specshipToolMarkers: string[];
|
|
56
|
+
transcriptFormat: 'jsonl' | 'single-json';
|
|
57
|
+
supportsBeforeToolDeny: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Prefix the host puts in front of a SpecShip tool name when the model
|
|
60
|
+
* calls it (AGENTADAPT-DOC, REQ-AGENTADAPT-001): agent-facing text renders
|
|
61
|
+
* `${toolPrefix}specship_explore` so each host sees its own tool name.
|
|
62
|
+
*/
|
|
63
|
+
toolPrefix: string;
|
|
64
|
+
/** Event names to answer with when the payload names none (REQ-AGENTADAPT-002). */
|
|
65
|
+
fallbackPromptEvent: string;
|
|
66
|
+
fallbackToolEvent: string;
|
|
67
|
+
/** The host's own built-in search tools a strict interceptor may redirect. */
|
|
68
|
+
denyEligibleTools: readonly string[];
|
|
69
|
+
/** The host's shell tool, whose `command` the interceptor classifies. */
|
|
70
|
+
shellTool: string | null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Claude Code — also the legacy default for payloads that name no event, so
|
|
74
|
+
* every pre-adapter install keeps its exact behaviour (REQ-AGENTADAPT-002.A2).
|
|
75
|
+
*/
|
|
76
|
+
export declare const CLAUDE_CODE_TRAITS: HostTraits;
|
|
77
|
+
/** Gemini CLI (verified against 0.28.0). */
|
|
78
|
+
export declare const GEMINI_CLI_TRAITS: HostTraits;
|
|
79
|
+
export declare function deriveHostTraits(payload: HookPayload): HostTraits;
|
|
80
|
+
//# sourceMappingURL=hook-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-output.d.ts","sourceRoot":"","sources":["../../src/activation/hook-output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CA4BzD;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,iBAAiB,EAAE,MAAM,EACzB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,iBAAiB,EAAE,MAAM,GACxB,MAAM,CAMR;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,UAAU;IACzB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,gBAAgB,EAAE,OAAO,GAAG,aAAa,CAAC;IAC1C,sBAAsB,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,yEAAyE;IACzE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,UAShC,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,iBAAiB,EAAE,UAS/B,CAAC;AAIF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAKjE"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared helpers for hook commands (`steer-nudge`, `spec-nudge`,
|
|
4
|
+
* `search-intercept`) that read a hook payload from stdin and emit a
|
|
5
|
+
* `hookSpecificOutput.additionalContext` line.
|
|
6
|
+
*
|
|
7
|
+
* The `hook_event_name` field is echoed back from the payload rather than
|
|
8
|
+
* hard-coded so the same CLI command serves Claude Code's event names
|
|
9
|
+
* (`UserPromptSubmit`, `PreToolUse`) AND Gemini CLI's (`BeforeAgent`,
|
|
10
|
+
* `BeforeTool`) — the installer wires them to the same binaries and the
|
|
11
|
+
* payload tells the command which host called it (REQ-GEMINI-010).
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.GEMINI_CLI_TRAITS = exports.CLAUDE_CODE_TRAITS = void 0;
|
|
15
|
+
exports.parseHookPayload = parseHookPayload;
|
|
16
|
+
exports.buildHookAdditionalContext = buildHookAdditionalContext;
|
|
17
|
+
exports.buildHookDenyDecision = buildHookDenyDecision;
|
|
18
|
+
exports.deriveHostTraits = deriveHostTraits;
|
|
19
|
+
function parseHookPayload(raw) {
|
|
20
|
+
const empty = {
|
|
21
|
+
prompt: '',
|
|
22
|
+
cwd: null,
|
|
23
|
+
sessionId: null,
|
|
24
|
+
transcriptPath: null,
|
|
25
|
+
hookEventName: null,
|
|
26
|
+
};
|
|
27
|
+
const trimmed = raw.trim();
|
|
28
|
+
if (!trimmed)
|
|
29
|
+
return empty;
|
|
30
|
+
let parsed;
|
|
31
|
+
try {
|
|
32
|
+
parsed = JSON.parse(trimmed);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Not JSON — treat the raw text as the prompt body.
|
|
36
|
+
return { ...empty, prompt: trimmed };
|
|
37
|
+
}
|
|
38
|
+
if (!parsed || typeof parsed !== 'object')
|
|
39
|
+
return empty;
|
|
40
|
+
const p = parsed;
|
|
41
|
+
const str = (v) => typeof v === 'string' && v.length > 0 ? v : null;
|
|
42
|
+
return {
|
|
43
|
+
prompt: typeof p.prompt === 'string' ? p.prompt : '',
|
|
44
|
+
cwd: str(p.cwd),
|
|
45
|
+
sessionId: str(p.session_id),
|
|
46
|
+
transcriptPath: str(p.transcript_path),
|
|
47
|
+
hookEventName: str(p.hook_event_name),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build a `hookSpecificOutput.additionalContext` JSON line. `eventName` is
|
|
52
|
+
* echoed from the payload when present (so Gemini's `BeforeAgent` /
|
|
53
|
+
* `BeforeTool` names round-trip) and falls back to `fallbackEventName` only
|
|
54
|
+
* when the payload carries none.
|
|
55
|
+
*/
|
|
56
|
+
function buildHookAdditionalContext(additionalContext, eventName, fallbackEventName) {
|
|
57
|
+
const hookEventName = eventName ?? fallbackEventName;
|
|
58
|
+
return (JSON.stringify({ hookSpecificOutput: { hookEventName, additionalContext } }) +
|
|
59
|
+
'\n');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A blocking decision for a host whose before-tool hook reads a TOP-LEVEL
|
|
63
|
+
* `decision` (Gemini CLI 0.28.0 `BeforeToolHookOutput.isBlockingDecision`
|
|
64
|
+
* checks `this.decision === 'block' || 'deny'`; nested under
|
|
65
|
+
* `hookSpecificOutput` it is ignored). Only emitted for hosts whose traits
|
|
66
|
+
* report `supportsBeforeToolDeny`.
|
|
67
|
+
*/
|
|
68
|
+
function buildHookDenyDecision(reason) {
|
|
69
|
+
return JSON.stringify({ decision: 'deny', reason }) + '\n';
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Claude Code — also the legacy default for payloads that name no event, so
|
|
73
|
+
* every pre-adapter install keeps its exact behaviour (REQ-AGENTADAPT-002.A2).
|
|
74
|
+
*/
|
|
75
|
+
exports.CLAUDE_CODE_TRAITS = {
|
|
76
|
+
specshipToolMarkers: ['"name":"mcp__specship__'],
|
|
77
|
+
transcriptFormat: 'jsonl',
|
|
78
|
+
supportsBeforeToolDeny: false,
|
|
79
|
+
toolPrefix: 'mcp__specship__',
|
|
80
|
+
fallbackPromptEvent: 'UserPromptSubmit',
|
|
81
|
+
fallbackToolEvent: 'PreToolUse',
|
|
82
|
+
denyEligibleTools: [],
|
|
83
|
+
shellTool: null,
|
|
84
|
+
};
|
|
85
|
+
/** Gemini CLI (verified against 0.28.0). */
|
|
86
|
+
exports.GEMINI_CLI_TRAITS = {
|
|
87
|
+
specshipToolMarkers: ['"name":"specship_', '"name": "specship_'],
|
|
88
|
+
transcriptFormat: 'single-json',
|
|
89
|
+
supportsBeforeToolDeny: true,
|
|
90
|
+
toolPrefix: '',
|
|
91
|
+
fallbackPromptEvent: 'BeforeAgent',
|
|
92
|
+
fallbackToolEvent: 'BeforeTool',
|
|
93
|
+
denyEligibleTools: ['grep_search', 'glob'],
|
|
94
|
+
shellTool: 'run_shell_command',
|
|
95
|
+
};
|
|
96
|
+
const GEMINI_EVENTS = new Set(['BeforeAgent', 'BeforeTool', 'AfterTool']);
|
|
97
|
+
function deriveHostTraits(payload) {
|
|
98
|
+
if (payload.hookEventName && GEMINI_EVENTS.has(payload.hookEventName)) {
|
|
99
|
+
return exports.GEMINI_CLI_TRAITS;
|
|
100
|
+
}
|
|
101
|
+
return exports.CLAUDE_CODE_TRAITS;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=hook-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-output.js","sourceRoot":"","sources":["../../src/activation/hook-output.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Point-of-use search interceptor (STEER-HOOK-DOC, REQ-STEER-004/005
|
|
2
|
+
* Point-of-use search interceptor (STEER-HOOK-DOC, REQ-STEER-004/005,
|
|
3
|
+
* REQ-GEMINI-011).
|
|
3
4
|
*
|
|
4
5
|
* The prompt-level nudge (steering.ts) fires once, at prompt submit, and its
|
|
5
6
|
* pull decays across a long turn — the observed failure is a search-shaped
|
|
6
7
|
* tool call made many tool-calls after the nudge. This module is the decision
|
|
7
|
-
* logic for the
|
|
8
|
-
* (
|
|
9
|
-
* the wrong
|
|
8
|
+
* logic for the hook the installer writes on each host's search tools
|
|
9
|
+
* (Claude: PreToolUse on Grep/Glob; Gemini: BeforeTool on grep_search / glob /
|
|
10
|
+
* run_shell_command): deliver the same guidance at the moment of the wrong
|
|
11
|
+
* choice.
|
|
10
12
|
*
|
|
11
|
-
* Two
|
|
13
|
+
* Two modes exist:
|
|
12
14
|
*
|
|
13
|
-
* - ADVISORY (REQ-STEER-004):
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* search
|
|
20
|
-
*
|
|
15
|
+
* - ADVISORY (default, both hosts, REQ-STEER-004/005): emit a one-line
|
|
16
|
+
* `additionalContext` redirect. At most once per session, silent once the
|
|
17
|
+
* session has used specship. The search still runs.
|
|
18
|
+
* - STRICT (Gemini-only opt-in, REQ-GEMINI-011): for a built-in search tool
|
|
19
|
+
* (`grep_search`, `glob`) in an indexed project, emit a top-level
|
|
20
|
+
* `{decision:'deny'}` with a reason naming `specship_explore`. A
|
|
21
|
+
* search-shaped `run_shell_command` NEVER denies — Gemini's hook runs
|
|
22
|
+
* after the user's shell confirmation, so denying it would make the user
|
|
23
|
+
* approve a command and then see it blocked. Parse-failure / unindexed
|
|
24
|
+
* project / already-using-specship → ALLOW.
|
|
25
|
+
*
|
|
26
|
+
* Shared code stays agent-agnostic: this file never sniffs `hook_event_name`
|
|
27
|
+
* or tool-name prefixes. The caller (bin/specship) hands in host traits
|
|
28
|
+
* derived in the hook I/O adapter (`activation/hook-output.ts`).
|
|
21
29
|
*/
|
|
22
30
|
/**
|
|
23
31
|
* The one redirect line. Explicitly advisory ("your search still runs") so
|
|
@@ -26,10 +34,19 @@
|
|
|
26
34
|
export declare const SEARCH_INTERCEPT_TEXT: string;
|
|
27
35
|
/** Per-session tracking file, kept inside the project's own `.specship/`. */
|
|
28
36
|
export declare function interceptStatePath(projectRoot: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Classify a shell command string for intercept purposes. We ONLY look at the
|
|
39
|
+
* first pipeline segment: `npm test | grep FAIL` uses grep as a FILTER on
|
|
40
|
+
* another command's output and must not be nudged, while `rg "renderScene"
|
|
41
|
+
* src/` is the lookup we care about. Read-shaped programs (`cat`, `head`,
|
|
42
|
+
* `tail`, `sed -n`, …) are never classified `search` — reading a config or
|
|
43
|
+
* log is legitimate.
|
|
44
|
+
*/
|
|
45
|
+
export declare function classifyShellCommand(cmd: string): 'search' | 'other';
|
|
29
46
|
export interface SearchInterceptInput {
|
|
30
47
|
/** Project the intercepted call belongs to (the hook payload's `cwd`). */
|
|
31
48
|
cwd: string;
|
|
32
|
-
/**
|
|
49
|
+
/** Host session id from the hook payload; null → untrackable, stay silent. */
|
|
33
50
|
sessionId: string | null;
|
|
34
51
|
/** Session transcript path from the hook payload, when present. */
|
|
35
52
|
transcriptPath: string | null;
|
|
@@ -37,23 +54,37 @@ export interface SearchInterceptInput {
|
|
|
37
54
|
homedir?: string;
|
|
38
55
|
/** Injectable clock for tests. */
|
|
39
56
|
now?: Date;
|
|
57
|
+
/** Transcript substrings signaling specship tool_use. Default: Claude form. */
|
|
58
|
+
specshipToolMarkers?: string[];
|
|
59
|
+
/** Transcript file format. Default: Claude JSONL. */
|
|
60
|
+
transcriptFormat?: 'jsonl' | 'single-json';
|
|
61
|
+
/** Strict mode (host supports a BeforeTool deny AND user opted in). */
|
|
62
|
+
strict?: boolean;
|
|
63
|
+
/** Whether the intercepted tool is a built-in search eligible for deny. */
|
|
64
|
+
denyEligible?: boolean;
|
|
65
|
+
/** When the intercepted tool is a shell runner, the raw command string. */
|
|
66
|
+
shellCommand?: string | null;
|
|
67
|
+
/** Search pattern/needle to echo in the deny reason, when known. */
|
|
68
|
+
searchPattern?: string | null;
|
|
40
69
|
}
|
|
70
|
+
export type SearchInterceptResult = {
|
|
71
|
+
additionalContext: string;
|
|
72
|
+
} | {
|
|
73
|
+
decision: 'deny';
|
|
74
|
+
reason: string;
|
|
75
|
+
} | null;
|
|
41
76
|
/**
|
|
42
|
-
* Decide
|
|
43
|
-
*
|
|
44
|
-
* Silence gates, in order (all REQ-STEER-004.A3 / REQ-STEER-005):
|
|
45
|
-
* 1. `SPECSHIP_NO_STEERING=1` (env > project > install settings) — same
|
|
46
|
-
* opt-out as the prompt nudge.
|
|
47
|
-
* 2. No `.specship/` directory at cwd — uninitialized projects get zero
|
|
48
|
-
* noise.
|
|
49
|
-
* 3. No session id — nothing to key the once-per-session guarantee on, so
|
|
50
|
-
* silence beats repeat-firing.
|
|
51
|
-
* 4. The session is already recorded — it fired before, or was seen using
|
|
52
|
-
* specship.
|
|
53
|
-
* 5. The transcript shows specship use — the agent doesn't need redirecting;
|
|
54
|
-
* record the session so later calls skip the scan.
|
|
77
|
+
* Decide what to emit for one intercepted search call.
|
|
55
78
|
*
|
|
56
|
-
*
|
|
79
|
+
* Order:
|
|
80
|
+
* 1. `SPECSHIP_NO_STEERING=1` → ALLOW (silent).
|
|
81
|
+
* 2. No `.specship/` at cwd → ALLOW.
|
|
82
|
+
* 3. Shell runner: classify; `other` → ALLOW; `search` → advisory path
|
|
83
|
+
* only (never deny, REQ-GEMINI-011.A3).
|
|
84
|
+
* 4. Strict + denyEligible: parse transcript; `used` or `parse-failure` or
|
|
85
|
+
* no transcript path → ALLOW; `not-used` → DENY with reason.
|
|
86
|
+
* 5. Otherwise advisory: once-per-session, silent in sessions already using
|
|
87
|
+
* specship (REQ-STEER-005).
|
|
57
88
|
*/
|
|
58
|
-
export declare function buildSearchIntercept(input: SearchInterceptInput):
|
|
89
|
+
export declare function buildSearchIntercept(input: SearchInterceptInput): SearchInterceptResult;
|
|
59
90
|
//# sourceMappingURL=search-intercept.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-intercept.d.ts","sourceRoot":"","sources":["../../src/activation/search-intercept.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"search-intercept.d.ts","sourceRoot":"","sources":["../../src/activation/search-intercept.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAOH;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAIX,CAAC;AAExB,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE9D;AA0GD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAUpE;AAqBD,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAC;IACZ,8EAA8E;IAC9E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mEAAmE;IACnE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,GAAG,CAAC,EAAE,IAAI,CAAC;IAEX,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;IAC3C,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,iBAAiB,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpC,IAAI,CAAC;AAYT;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CA4DvF"}
|