@gobing-ai/spur 0.3.94 → 0.3.96
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/.claude-plugin/marketplace.json +1 -1
- package/README.md +42 -0
- package/board/index.d.ts +38 -0
- package/config/plugin-scripts.json +3 -52
- package/config/rules/boundary/sp-script-placement.yaml +19 -0
- package/config/rules/strict/runtime-boundaries.yaml +5 -0
- package/config/rules/structure/test-location.yaml +2 -0
- package/config/rules/typescript/no-syscall-emulation-in-boundary-mock.yaml +1 -1
- package/config/rules/typescript/output-boundaries.yaml +15 -2
- package/config/script-placement-baseline.json +51 -0
- package/config/workflows/feature-verification.yaml +7 -4
- package/config/workflows/history-anatomy.yaml +23 -11
- package/config/workflows/idea-pipeline.yaml +87 -86
- package/config/workflows/pr-review.yaml +18 -9
- package/config/workflows/task-pipeline.yaml +84 -109
- package/config/workflows/wrapup-pipeline.yaml +173 -46
- package/package.json +15 -11
- package/plugins/sp/README.md +8 -10
- package/plugins/sp/agents/super-reviewer.md +43 -18
- package/plugins/sp/commands/dev-fixgha.md +83 -0
- package/plugins/sp/commands/dev-gitmsg.md +8 -6
- package/plugins/sp/commands/dev-gtd.md +2 -2
- package/plugins/sp/commands/dev-idea.md +22 -12
- package/plugins/sp/commands/dev-plan.md +8 -9
- package/plugins/sp/commands/dev-review.md +22 -13
- package/plugins/sp/commands/dev-verify.md +7 -4
- package/plugins/sp/commands/dev-verifyall.md +5 -4
- package/plugins/sp/commands/dev-wrap.md +1 -1
- package/plugins/sp/commands/spur-init.md +2 -2
- package/plugins/sp/hooks/context-post-tool.ts +2 -2
- package/plugins/sp/hooks/context-session-start.ts +2 -1
- package/plugins/sp/hooks/context-session-stop.ts +22 -14
- package/plugins/sp/hooks/pi/guard-extension.ts +109 -150
- package/plugins/sp/lib/history-anatomy.generated.d.mts +112 -0
- package/plugins/sp/lib/history-anatomy.generated.mjs +686 -0
- package/plugins/sp/lib/idea-handoff.generated.mjs +6 -5
- package/plugins/sp/lib/inline-run.generated.d.mts +13 -2
- package/plugins/sp/lib/inline-run.generated.mjs +33 -16
- package/plugins/sp/lib/quality-gate.generated.d.mts +104 -0
- package/plugins/sp/lib/quality-gate.generated.mjs +438 -0
- package/plugins/sp/lib/residual-scan.generated.d.mts +62 -0
- package/plugins/sp/lib/residual-scan.generated.mjs +210 -0
- package/plugins/sp/lib/spur-bin.ts +36 -0
- package/plugins/sp/lib/step-profile.generated.d.mts +71 -0
- package/plugins/sp/lib/step-profile.generated.mjs +174 -0
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/references/roles.md +1 -1
- package/plugins/sp/scripts/daily-summary/daily-summary.mjs +3 -3
- package/plugins/sp/scripts/daily-summary/daily-summary.ts +3 -3
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +2 -0
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +1 -0
- package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +9 -7
- package/plugins/sp/scripts/dogfood-testing/validate-report.ts +8 -7
- package/plugins/sp/scripts/feature-verification-steps.ts +6 -6
- package/plugins/sp/scripts/history-anatomy-cache.mjs +23 -22
- package/plugins/sp/scripts/history-anatomy-cache.ts +23 -928
- package/plugins/sp/scripts/inline-run-setup.mjs +90 -315
- package/plugins/sp/scripts/inline-run-setup.ts +109 -639
- package/plugins/sp/scripts/pr-reviewing.mjs +2 -0
- package/plugins/sp/scripts/pr-reviewing.ts +1 -0
- package/plugins/sp/scripts/quality-gate.mjs +38 -21
- package/plugins/sp/scripts/quality-gate.ts +20 -660
- package/plugins/sp/scripts/residual-scan.mjs +138 -159
- package/plugins/sp/scripts/residual-scan.ts +102 -499
- package/plugins/sp/scripts/script-root.mjs +129 -0
- package/plugins/sp/scripts/script-root.ts +199 -0
- package/plugins/sp/scripts/workflow-step-profile.mjs +27 -16
- package/plugins/sp/scripts/workflow-step-profile.ts +22 -314
- package/plugins/sp/scripts/wrapup-drift-probe.mjs +12 -3
- package/plugins/sp/scripts/wrapup-drift-probe.ts +6 -3
- package/plugins/sp/scripts/wrapup-steps.mjs +42 -40
- package/plugins/sp/scripts/wrapup-steps.ts +64 -46
- package/plugins/sp/skills/code-improvement/SKILL.md +5 -4
- package/plugins/sp/skills/code-verification/SKILL.md +46 -16
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +13 -2
- package/plugins/sp/skills/functional-review/SKILL.md +8 -5
- package/plugins/sp/skills/functional-review/references/verdict-schema.md +1 -1
- package/plugins/sp/skills/history-anatomy/references/modes.md +2 -1
- package/plugins/sp/skills/next-feature/references/handoff-routing.md +1 -1
- package/plugins/sp/skills/next-router/references/routing-table.md +2 -2
- package/plugins/sp/skills/spur-cli/SKILL.md +3 -3
- package/plugins/sp/skills/spur-cli/references/agent.md +10 -10
- package/plugins/sp/skills/spur-cli/references/features.md +17 -6
- package/plugins/sp/skills/spur-cli/references/init.md +17 -16
- package/plugins/sp/skills/spur-cli/references/self.md +3 -2
- package/plugins/sp/skills/spur-cli/references/serve.md +10 -10
- package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +28 -5
- package/plugins/sp/skills/spur-cli/references/tasks.md +14 -8
- package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +4 -3
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +11 -9
- package/plugins/sp/skills/spur-dev/references/decision-brief.md +1 -1
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +86 -70
- package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +3 -3
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +107 -44
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +5 -9
- package/plugins/sp/skills/spur-dev/references/feature-link-helper.md +3 -3
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +31 -21
- package/plugins/sp/skills/spur-dev/references/gate-checklists.md +19 -19
- package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +4 -3
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +35 -6
- package/plugins/sp/skills/spur-doctor/SKILL.md +1 -1
- package/plugins/sp/skills/sys-architecture/SKILL.md +3 -2
- package/plugins/sp/tsconfig.json +8 -0
- package/spur.js +6638 -4775
- package/web/_astro/BoardApp.BIjMatT1.js +1 -0
- package/web/_astro/{BoardApp.FTEs3-N8.js → BoardApp.GvjIe9Z6.js} +150 -153
- package/web/_astro/TaskDetail.BZM3EAFx.js +1 -0
- package/web/_astro/_commonjsHelpers.CqkleIqs.js +1 -0
- package/web/_astro/{arc.uuAf51IT.js → arc.HkRiZnoI.js} +1 -1
- package/web/_astro/architectureDiagram-3BPJPVTR.BDdK-tgZ.js +36 -0
- package/web/_astro/{blockDiagram-GPEHLZMM.D1mGCq3p.js → blockDiagram-GPEHLZMM.CZ9kOBxx.js} +1 -1
- package/web/_astro/board-facade-react-dom-client.B2U5wMvk.js +1 -0
- package/web/_astro/board-facade-react-dom.Cd2MuMhF.js +1 -0
- package/web/_astro/board-facade-react-jsx-dev-runtime.B_L3JzfC.js +1 -0
- package/web/_astro/board-facade-react-jsx-runtime.BY2yfHRi.js +1 -0
- package/web/_astro/board-facade-react-router-dom.Dy5pjzOw.js +1 -0
- package/web/_astro/board-facade-react-router.DjjqU27_.js +1 -0
- package/web/_astro/board-facade-react.Dgf4GRyj.js +1 -0
- package/web/_astro/{c4Diagram-AAUBKEIU.CMsolcde.js → c4Diagram-AAUBKEIU.DXK9qeRD.js} +1 -1
- package/web/_astro/channel.DlhX2MEt.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.CrGA3fik.js → chunk-2J33WTMH.BTD2WeX5.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.DsLVVla0.js → chunk-4BX2VUAB.Ci6Qbcvk.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.Dxc59Tfi.js → chunk-55IACEB6.yl3zsj7p.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.CaEVE2Wy.js → chunk-727SXJPM.ClXZsfyR.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.BiJ4HXeI.js → chunk-AQP2D5EJ.BmKWZBcP.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.Mxf1fru5.js → chunk-FMBD7UC4.By30fcb7.js} +1 -1
- package/web/_astro/chunk-JMJ3UQ3L.BQJEJHu4.js +34 -0
- package/web/_astro/{chunk-ND2GUHAM.pyOWQixH.js → chunk-ND2GUHAM.24NmrD-k.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.BmEsg4vr.js → chunk-QZHKN3VN.BN4sKdcS.js} +1 -1
- package/web/_astro/chunk-YNUBSHFH.CxeAygfi.js +7 -0
- package/web/_astro/{classDiagram-4FO5ZUOK.BHhhMFTO.js → classDiagram-4FO5ZUOK.CJpoMPb5.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.BHhhMFTO.js → classDiagram-v2-Q7XG4LA2.CJpoMPb5.js} +1 -1
- package/web/_astro/client.BhluLQqe.js +1 -0
- package/web/_astro/client.DBpSRLnx.js +9 -0
- package/web/_astro/cose-bilkent-S5V4N54A.BraxQ2Nt.js +1 -0
- package/web/_astro/{cynefin-OW5HDTMX.C2j1_lKL.js → cynefin-OW5HDTMX.gzoU73oL.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.hZ2NCTdT.js → dagre-BM42HDAG.wyDfWySU.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.Bfw5_EzK.js → diagram-2AECGRRQ.h2_EbMxV.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.Bt1V_Tmk.js → diagram-5GNKFQAL.Db6dcs89.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.DEk-YFwp.js → diagram-KO2AKTUF.NVwzxu_U.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.CDjndtQm.js → diagram-LMA3HP47.B-eNgDQk.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.cFnUHScG.js → diagram-OG6HWLK6.Bsa8ZRbJ.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.DlhYp7NV.js → erDiagram-TEJ5UH35.BospRE5Q.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.DNTpsxfx.js → flowDiagram-I6XJVG4X.DMzvHwAA.js} +1 -1
- package/web/_astro/ganttDiagram-6RSMTGT7.Dmdxgd-M.js +292 -0
- package/web/_astro/{gitGraphDiagram-PVQCEYII.DkEqNI0P.js → gitGraphDiagram-PVQCEYII.CaqdO0rL.js} +1 -1
- package/web/_astro/index.5dn-Zm-2.js +1 -0
- package/web/_astro/index.C-IqPpW2.js +1 -0
- package/web/_astro/index.Cyc_GA4f.js +1 -0
- package/web/_astro/index.EoZlzLK-.css +1 -0
- package/web/_astro/index.tZfqwSut.js +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.CrjioCTG.js → infoDiagram-5YYISTIA.DDVD9Wn7.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.BcK0CN8n.js → ishikawaDiagram-YF4QCWOH.EKyCUFsL.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.p0CbBDX1.js → journeyDiagram-JHISSGLW.By2-RkYB.js} +1 -1
- package/web/_astro/jsx-runtime.DWOiEOII.js +1 -0
- package/web/_astro/{kanban-definition-UN3LZRKU.puHIFt6J.js → kanban-definition-UN3LZRKU.ar-WmlyR.js} +1 -1
- package/web/_astro/{linear.Bb-3a1d7.js → linear.BnzMBgo_.js} +1 -1
- package/web/_astro/{mermaid.core.CJDgXOJs.js → mermaid.core.DSqeFu2Y.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.BoAZEI9t.js → mindmap-definition-RKZ34NQL.1XcF8Wh2.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.CJNSdqY7.js → pieDiagram-4H26LBE5.DnItHOdK.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.DtTy7_0Z.js → quadrantDiagram-W4KKPZXB.BQQyrnBt.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.BNYV98Xg.js → requirementDiagram-4Y6WPE33.Dmzxun82.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.DRq9DGHp.js → sankeyDiagram-5OEKKPKP.BBIeRKYB.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.B7KdBFCm.js → sequenceDiagram-3UESZ5HK.CUNVdBBf.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.CD62ZJ2H.js → stateDiagram-AJRCARHV.DlFf2sJm.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.CeVk1TAj.js → stateDiagram-v2-BHNVJYJU.DXR7I1H5.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.C_ZPA5tT.js → timeline-definition-PNZ67QCA.BcO-GyX2.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.CrThO_FQ.js → vennDiagram-CIIHVFJN.ChCECmmW.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.DSZCA5nl.js → wardleyDiagram-YWT4CUSO.CRaT12mD.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.KI7baTuk.js → xychartDiagram-2RQKCTM6.B3lsHVpj.js} +1 -1
- package/web/board-runtime.json +69 -0
- package/web/index.html +2 -2
- package/plugins/sp/lib/artifact-digest.generated.d.mts +0 -7
- package/plugins/sp/lib/artifact-digest.generated.mjs +0 -48
- package/plugins/sp/scripts/feature-sync-bounded.mjs +0 -298
- package/plugins/sp/scripts/feature-sync-bounded.ts +0 -479
- package/plugins/sp/scripts/idea-coverage-check.ts +0 -168
- package/plugins/sp/scripts/inline-pipeline-parity-check.ts +0 -298
- package/plugins/sp/scripts/record-feature-sync.mjs +0 -63
- package/plugins/sp/scripts/record-feature-sync.ts +0 -84
- package/plugins/sp/scripts/script-contract-check.ts +0 -377
- package/plugins/sp/scripts/stage-registry-adapter.ts +0 -1533
- package/plugins/sp/scripts/surface-drift-inventory.ts +0 -989
- package/plugins/sp/scripts/task-evidence-precheck.ts +0 -187
- package/plugins/sp/scripts/task-size-precheck.ts +0 -210
- package/plugins/sp/scripts/transition-shim-check.ts +0 -238
- package/plugins/sp/scripts/validate-commands.ts +0 -689
- package/plugins/sp/scripts/validate-flag-contracts.ts +0 -878
- package/plugins/sp/scripts/verify-answer-lint.ts +0 -547
- package/web/_astro/BoardApp.C02hAHPO.js +0 -1
- package/web/_astro/TaskDetail.C-GdsS-t.js +0 -1
- package/web/_astro/architectureDiagram-3BPJPVTR.CGe629A1.js +0 -36
- package/web/_astro/channel.fsgl7o5j.js +0 -1
- package/web/_astro/client.yhYJvxCU.js +0 -9
- package/web/_astro/cose-bilkent-S5V4N54A.2fH4YOlp.js +0 -1
- package/web/_astro/ganttDiagram-6RSMTGT7.DC_p36PI.js +0 -292
- package/web/_astro/index.De90oHcH.js +0 -1
- package/web/_astro/index.Hjbr15fG.css +0 -1
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
* Implements:
|
|
8
8
|
* - task-write-guard (tool_call → block Write/Edit to Spur task files)
|
|
9
9
|
* - careful-guard (tool_call → warn on destructive Bash commands)
|
|
10
|
-
* - context-post-tool (tool_result →
|
|
11
|
-
* - context-session-start (session_start →
|
|
12
|
-
* - context-session-stop (session_shutdown →
|
|
10
|
+
* - context-post-tool (tool_result → shared recordToolUseEvent)
|
|
11
|
+
* - context-session-start (session_start → shared recordSessionStart)
|
|
12
|
+
* - context-session-stop (session_shutdown → shared recordSessionEnd)
|
|
13
|
+
*
|
|
14
|
+
* The ledger and session cores are shared with the Claude hooks (task 0969): this
|
|
15
|
+
* extension only normalizes Pi event shapes and adapts them to those cores.
|
|
13
16
|
*
|
|
14
17
|
* Installation:
|
|
15
18
|
* Add to ~/.pi/agent/settings.json packages:
|
|
@@ -19,13 +22,14 @@
|
|
|
19
22
|
*/
|
|
20
23
|
|
|
21
24
|
import { spawnSync } from 'node:child_process';
|
|
22
|
-
import {
|
|
25
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
23
26
|
import { homedir } from 'node:os';
|
|
24
27
|
import { isAbsolute, join, resolve } from 'node:path';
|
|
25
28
|
import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
|
|
26
29
|
import { getEnvVar, getEnvVars } from '../../lib/env';
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
30
|
+
import { recordToolUseEvent, type ToolPayload } from '../context-post-tool';
|
|
31
|
+
import { recordSessionStart } from '../context-session-start';
|
|
32
|
+
import { recordSessionEnd } from '../context-session-stop';
|
|
29
33
|
import { classifyCommand } from '../destructive-policy';
|
|
30
34
|
import { couldBeTaskFile } from '../task-file-policy';
|
|
31
35
|
|
|
@@ -35,8 +39,6 @@ import { couldBeTaskFile } from '../task-file-policy';
|
|
|
35
39
|
// process lifetime, and lazy resolution keeps the extension testable (tests
|
|
36
40
|
// chdir into a temp project before driving handlers).
|
|
37
41
|
const spurContextDir = (): string => join(process.cwd(), '.spur', 'context');
|
|
38
|
-
const sessionFilePath = (): string => join(spurContextDir(), '.session.json');
|
|
39
|
-
const ledgerFilePath = (): string => join(spurContextDir(), 'token-ledger.jsonl');
|
|
40
42
|
|
|
41
43
|
// ─── Helpers ─────────────────────────────────────────────────────────────
|
|
42
44
|
|
|
@@ -113,137 +115,86 @@ function resolveSpurTaskOwnership(filePath: string): TaskOwnership {
|
|
|
113
115
|
// `git push origin +main`, and warned on `git push --force-with-lease`). Do not
|
|
114
116
|
// re-introduce a local copy — add cases to `destructive-policy.test.ts` instead.
|
|
115
117
|
|
|
116
|
-
// ───
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (!existsSync(spurContextDir())) return;
|
|
138
|
-
const sessionId = readSessionId();
|
|
139
|
-
if (!sessionId) return;
|
|
140
|
-
|
|
141
|
-
const summary = summarizeToolEvent(event);
|
|
142
|
-
const tokens = command ? Math.ceil(cappedByteLength(command) / 4) : 0;
|
|
143
|
-
const input = event.tool_input ?? {};
|
|
144
|
-
// Pi tool names are lowercase (`read`) and its write/edit tools take `path`, not `file_path`.
|
|
145
|
-
const path = typeof input.file_path === 'string' ? input.file_path : input.path;
|
|
146
|
-
|
|
147
|
-
const ledgerEntry = JSON.stringify({
|
|
148
|
-
session: sessionId,
|
|
149
|
-
type: event.tool_name?.toLowerCase() === 'read' ? 'read' : 'write',
|
|
150
|
-
tool: event.tool_name,
|
|
151
|
-
file: typeof path === 'string' ? path : undefined,
|
|
152
|
-
summary,
|
|
153
|
-
tokens,
|
|
154
|
-
ts: new Date().toISOString(),
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
appendFileSync(ledgerFilePath(), `${ledgerEntry}\n`);
|
|
158
|
-
} catch {
|
|
159
|
-
// fail-open: skip ledger writes on error
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function readSessionId(): string | undefined {
|
|
164
|
-
try {
|
|
165
|
-
if (!existsSync(sessionFilePath())) return undefined;
|
|
166
|
-
const data = JSON.parse(readFileSync(sessionFilePath(), 'utf-8')) as { session_id?: string };
|
|
167
|
-
return data.session_id;
|
|
168
|
-
} catch {
|
|
169
|
-
return undefined;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// ─── Session helpers (agent/model hints from agent-hint.ts; mirrors context-session-stop.ts) ─
|
|
174
|
-
|
|
175
|
-
function generateSessionId(): string {
|
|
176
|
-
const timestamp = Date.now().toString(36);
|
|
177
|
-
const random = Math.random().toString(36).slice(2, 10);
|
|
178
|
-
return `${timestamp}-${random}`;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function initSession(): void {
|
|
182
|
-
try {
|
|
183
|
-
mkdirSync(spurContextDir(), { recursive: true });
|
|
184
|
-
const sessionId = generateSessionId();
|
|
185
|
-
const session = {
|
|
186
|
-
session_id: sessionId,
|
|
187
|
-
agent: resolveAgentHintShared(getEnvVars(), 'pi'),
|
|
188
|
-
model: resolveModelHintShared(getEnvVars()),
|
|
189
|
-
started_at: new Date().toISOString(),
|
|
190
|
-
};
|
|
191
|
-
writeFileSync(sessionFilePath(), `${JSON.stringify(session, null, 2)}\n`);
|
|
192
|
-
|
|
193
|
-
// Append session_start event to ledger
|
|
194
|
-
const startEntry = JSON.stringify({
|
|
195
|
-
session: sessionId,
|
|
196
|
-
type: 'session_start',
|
|
197
|
-
agent: session.agent,
|
|
198
|
-
model: session.model,
|
|
199
|
-
ts: session.started_at,
|
|
200
|
-
});
|
|
201
|
-
appendFileSync(ledgerFilePath(), `${startEntry}\n`);
|
|
202
|
-
} catch {
|
|
203
|
-
// fail-open
|
|
118
|
+
// ─── Pi → Claude payload normalization (task 0969 R1) ─────────────────────
|
|
119
|
+
|
|
120
|
+
/** Pi tool name → the Claude tool name the shared core records. */
|
|
121
|
+
const PI_TO_CLAUDE: Record<string, string> = {
|
|
122
|
+
read: 'Read',
|
|
123
|
+
write: 'Write',
|
|
124
|
+
edit: 'Edit',
|
|
125
|
+
bash: 'Bash',
|
|
126
|
+
grep: 'Grep',
|
|
127
|
+
find: 'Glob',
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/** Join the text parts of a Pi tool_result `content` payload. */
|
|
131
|
+
function piContentText(content: unknown): string {
|
|
132
|
+
if (typeof content === 'string') return content;
|
|
133
|
+
if (!Array.isArray(content)) return '';
|
|
134
|
+
const parts: string[] = [];
|
|
135
|
+
for (const part of content) {
|
|
136
|
+
if (part && typeof part === 'object' && typeof (part as { text?: unknown }).text === 'string') {
|
|
137
|
+
parts.push((part as { text: string }).text);
|
|
138
|
+
}
|
|
204
139
|
}
|
|
140
|
+
return parts.join('\n');
|
|
205
141
|
}
|
|
206
142
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
143
|
+
/**
|
|
144
|
+
* Pure Pi-event → Claude-{@link ToolPayload} adapter. An unmapped tool returns null so the
|
|
145
|
+
* shared core writes no row (R1's row filter). Search tools keep `path` (never `file_path`)
|
|
146
|
+
* because the core treats `file_path` as the written file, not a search root.
|
|
147
|
+
*/
|
|
148
|
+
export function normalizePiToolEvent(
|
|
149
|
+
toolName: string,
|
|
150
|
+
input: Record<string, unknown> | undefined,
|
|
151
|
+
content?: unknown,
|
|
152
|
+
): ToolPayload | null {
|
|
153
|
+
const mapped = PI_TO_CLAUDE[toolName];
|
|
154
|
+
if (mapped === undefined) return null;
|
|
155
|
+
const i = input ?? {};
|
|
156
|
+
const str = (value: unknown): string => (typeof value === 'string' ? value : '');
|
|
157
|
+
const path = str(i.path) || str(i.file_path);
|
|
158
|
+
const text = piContentText(content);
|
|
159
|
+
const tool_response = text.length > 0 ? { content: text } : undefined;
|
|
160
|
+
|
|
161
|
+
switch (mapped) {
|
|
162
|
+
case 'Read':
|
|
163
|
+
return { tool_name: mapped, tool_input: { file_path: path }, tool_response };
|
|
164
|
+
case 'Write':
|
|
165
|
+
return { tool_name: mapped, tool_input: { file_path: path, content: str(i.content) }, tool_response };
|
|
166
|
+
case 'Edit': {
|
|
167
|
+
const edits = Array.isArray(i.edits) ? (i.edits as Array<Record<string, unknown>>) : [];
|
|
168
|
+
return {
|
|
169
|
+
tool_name: mapped,
|
|
170
|
+
tool_input: {
|
|
171
|
+
file_path: path,
|
|
172
|
+
old_string: edits.map((e) => str(e.oldText)).join(''),
|
|
173
|
+
new_string: edits.map((e) => str(e.newText)).join(''),
|
|
174
|
+
},
|
|
175
|
+
tool_response,
|
|
176
|
+
};
|
|
230
177
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
178
|
+
case 'Grep':
|
|
179
|
+
return {
|
|
180
|
+
tool_name: mapped,
|
|
181
|
+
tool_input: {
|
|
182
|
+
pattern: str(i.pattern),
|
|
183
|
+
...(path ? { path } : {}),
|
|
184
|
+
...(str(i.glob) ? { glob: str(i.glob) } : {}),
|
|
185
|
+
},
|
|
186
|
+
tool_response,
|
|
187
|
+
};
|
|
188
|
+
case 'Glob':
|
|
189
|
+
return {
|
|
190
|
+
tool_name: mapped,
|
|
191
|
+
tool_input: { pattern: str(i.pattern), ...(path ? { path } : {}) },
|
|
192
|
+
tool_response,
|
|
193
|
+
};
|
|
194
|
+
case 'Bash':
|
|
195
|
+
return { tool_name: mapped, tool_input: { command: str(i.command) }, tool_response };
|
|
196
|
+
default:
|
|
197
|
+
return null;
|
|
247
198
|
}
|
|
248
199
|
}
|
|
249
200
|
|
|
@@ -284,27 +235,35 @@ export default function (pi: ExtensionAPI): void {
|
|
|
284
235
|
return {};
|
|
285
236
|
});
|
|
286
237
|
|
|
287
|
-
// ── context-post-tool:
|
|
238
|
+
// ── context-post-tool: shared recordToolUseEvent (task 0969 R1) ──
|
|
288
239
|
pi.on('tool_result', async (event) => {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
240
|
+
try {
|
|
241
|
+
const payload = normalizePiToolEvent(
|
|
242
|
+
event.toolName,
|
|
243
|
+
event.input as Record<string, unknown> | undefined,
|
|
244
|
+
(event as { content?: unknown }).content,
|
|
245
|
+
);
|
|
246
|
+
if (payload) recordToolUseEvent(spurContextDir(), payload);
|
|
247
|
+
} catch {
|
|
248
|
+
// fail-open
|
|
249
|
+
}
|
|
299
250
|
});
|
|
300
251
|
|
|
301
|
-
// ── context-session-start:
|
|
252
|
+
// ── context-session-start: shared recordSessionStart (R2) ────────
|
|
302
253
|
pi.on('session_start', async () => {
|
|
303
|
-
|
|
254
|
+
try {
|
|
255
|
+
recordSessionStart(spurContextDir(), getEnvVars(), undefined, 'pi');
|
|
256
|
+
} catch {
|
|
257
|
+
// fail-open
|
|
258
|
+
}
|
|
304
259
|
});
|
|
305
260
|
|
|
306
|
-
// ── context-session-stop:
|
|
261
|
+
// ── context-session-stop: shared recordSessionEnd (R3) ──────────
|
|
307
262
|
pi.on('session_shutdown', async () => {
|
|
308
|
-
|
|
263
|
+
try {
|
|
264
|
+
recordSessionEnd(spurContextDir());
|
|
265
|
+
} catch {
|
|
266
|
+
// fail-open
|
|
267
|
+
}
|
|
309
268
|
});
|
|
310
269
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED by scripts/commands/bundle-plugin-lib.ts — do not edit.
|
|
3
|
+
* Source of truth: packages/app/src/services/history-anatomy.ts (task 1005 R2).
|
|
4
|
+
*/
|
|
5
|
+
export declare interface CacheIdentity {
|
|
6
|
+
contractVersion: string;
|
|
7
|
+
mode: 'daily' | 'ad-hoc';
|
|
8
|
+
date: string;
|
|
9
|
+
timezone: string;
|
|
10
|
+
bounds: { since: string; until: string };
|
|
11
|
+
sources: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare interface CacheProvenance {
|
|
14
|
+
identity: CacheIdentity;
|
|
15
|
+
windowState: 'provisional' | 'closed';
|
|
16
|
+
generatedAt: string;
|
|
17
|
+
validatedAt: string;
|
|
18
|
+
artifactDigest: string;
|
|
19
|
+
baselineArtifactDigest: string | null;
|
|
20
|
+
contractDigest: string;
|
|
21
|
+
skillDigest: string;
|
|
22
|
+
workflowDigest: string;
|
|
23
|
+
helperDigest: string;
|
|
24
|
+
coverage: Array<{ source: string; status: string; lastImportedAt: string | null }>;
|
|
25
|
+
runId?: string;
|
|
26
|
+
currentArtifactPath?: string;
|
|
27
|
+
baselineArtifactPath?: string | null;
|
|
28
|
+
spurVersion?: string;
|
|
29
|
+
schemaVersion?: number;
|
|
30
|
+
executor?: string;
|
|
31
|
+
model?: string;
|
|
32
|
+
cacheDisposition?: CacheDisposition;
|
|
33
|
+
}
|
|
34
|
+
export declare type CacheDisposition = 'hit' | 'miss' | 'forced-recompute';
|
|
35
|
+
export declare interface CacheDecision {
|
|
36
|
+
disposition: CacheDisposition;
|
|
37
|
+
reasons: string[];
|
|
38
|
+
}
|
|
39
|
+
export declare const REPORT_SECTIONS: string[];
|
|
40
|
+
export declare const FINDING_FIELDS: string[];
|
|
41
|
+
export declare function semanticArtifactDigest(artifactJson: unknown): string;
|
|
42
|
+
export declare function parseProvenance(reportMarkdown: string): CacheProvenance | null;
|
|
43
|
+
export declare function decideCache(
|
|
44
|
+
cached: CacheProvenance | null,
|
|
45
|
+
current: CacheProvenance,
|
|
46
|
+
opts: { recompute: boolean; dayClosed: boolean },
|
|
47
|
+
): CacheDecision;
|
|
48
|
+
export declare function checkReportStructure(reportMarkdown: string): { ok: boolean; problems: string[] };
|
|
49
|
+
export declare function logicDigest(path: string | undefined): string;
|
|
50
|
+
export declare function importedSnapshotAsOf(coverage: CacheProvenance['coverage']): string;
|
|
51
|
+
export declare function resolvePaths(opts: {
|
|
52
|
+
helper: string;
|
|
53
|
+
reportDir: string;
|
|
54
|
+
date?: string;
|
|
55
|
+
output?: string;
|
|
56
|
+
now?: Date;
|
|
57
|
+
tz?: string;
|
|
58
|
+
mode?: string;
|
|
59
|
+
since?: string;
|
|
60
|
+
until?: string;
|
|
61
|
+
}): string;
|
|
62
|
+
export declare type SelectorValidation =
|
|
63
|
+
| {
|
|
64
|
+
ok: true;
|
|
65
|
+
mode: 'daily' | 'ad-hoc';
|
|
66
|
+
date: string | null;
|
|
67
|
+
focus: string | null;
|
|
68
|
+
since: string | null;
|
|
69
|
+
until: string | null;
|
|
70
|
+
}
|
|
71
|
+
| { ok: false; errors: string[] };
|
|
72
|
+
export declare function validateSelector(opts: {
|
|
73
|
+
mode?: string;
|
|
74
|
+
date?: string;
|
|
75
|
+
since?: string;
|
|
76
|
+
until?: string;
|
|
77
|
+
focus?: string;
|
|
78
|
+
recompute?: string;
|
|
79
|
+
output?: string;
|
|
80
|
+
}): SelectorValidation;
|
|
81
|
+
export declare interface ProbeOptions {
|
|
82
|
+
artifact: string;
|
|
83
|
+
target: string;
|
|
84
|
+
baseline?: string;
|
|
85
|
+
mode: 'daily' | 'ad-hoc';
|
|
86
|
+
date?: string;
|
|
87
|
+
recompute: boolean;
|
|
88
|
+
executor?: string;
|
|
89
|
+
model?: string;
|
|
90
|
+
skillDir?: string;
|
|
91
|
+
contractFile?: string;
|
|
92
|
+
workflowFile?: string;
|
|
93
|
+
helperFile?: string;
|
|
94
|
+
contractVersion?: string;
|
|
95
|
+
runId?: string;
|
|
96
|
+
spurVersion?: string;
|
|
97
|
+
now?: Date;
|
|
98
|
+
}
|
|
99
|
+
export declare function buildProvenance(opts: ProbeOptions): CacheProvenance;
|
|
100
|
+
export declare function probe(opts: ProbeOptions): { decision: CacheDecision; current: CacheProvenance };
|
|
101
|
+
export declare function renderProvenanceFrontmatter(p: CacheProvenance): string;
|
|
102
|
+
export declare function bannerLine(p: CacheProvenance): string;
|
|
103
|
+
export declare function stampReport(candidateMarkdown: string, p: CacheProvenance): string;
|
|
104
|
+
export declare function refreshReport(publishedMarkdown: string, validatedAt: string, disposition: CacheDisposition): string;
|
|
105
|
+
export declare function publishAtomically(candidatePath: string, targetPath: string): void;
|
|
106
|
+
export declare interface CacheCliResult {
|
|
107
|
+
exitCode: number;
|
|
108
|
+
stdout: string;
|
|
109
|
+
stderr: string;
|
|
110
|
+
}
|
|
111
|
+
export declare function porcelainPaths(text: string): Set<string>;
|
|
112
|
+
export declare function diffPorcelain(before: string, now: string, expects: Set<string>): string[];
|