@tekmidian/pai 0.54.0 → 0.55.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/dist/{aibroker-client-CNfIBrl5.mjs → aibroker-client-B8Wtasez.mjs} +1 -1
- package/dist/{aibroker-client-DzkTpVjx.mjs → aibroker-client-BK1h--W_.mjs} +3 -3
- package/dist/{aibroker-client-DzkTpVjx.mjs.map → aibroker-client-BK1h--W_.mjs.map} +1 -1
- package/dist/{indexer-backend-CdvCJCkD.mjs → async-CLvuY7b-.mjs} +7 -7
- package/dist/async-CLvuY7b-.mjs.map +1 -0
- package/dist/auto-route-CF8WNaoy.mjs +100 -0
- package/dist/auto-route-CF8WNaoy.mjs.map +1 -0
- package/dist/{chain-BcBDJ1Id.mjs → chain-DogidBji.mjs} +4 -4
- package/dist/{chain-BcBDJ1Id.mjs.map → chain-DogidBji.mjs.map} +1 -1
- package/dist/cli/index.mjs +22 -23
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/program.d.mts.map +1 -1
- package/dist/cli/program.mjs +22 -23
- package/dist/{clusters-Cw_P6lO-.mjs → clusters-Ci1mseh2.mjs} +4 -36
- package/dist/clusters-Ci1mseh2.mjs.map +1 -0
- package/dist/{config-B3EPzRjf.mjs → config-B93YS8tP.mjs} +3 -3
- package/dist/{config-B3EPzRjf.mjs.map → config-B93YS8tP.mjs.map} +1 -1
- package/dist/{config-Bn9jpblO.mjs → config-D1omG_UU.mjs} +3 -3
- package/dist/{config-Bn9jpblO.mjs.map → config-D1omG_UU.mjs.map} +1 -1
- package/dist/{config-RjeVGJ7K.mjs → config-DCYWFaEi.mjs} +1 -1
- package/dist/{context-handover-cache-CXyH6QsC.mjs → context-handover-cache-k2kWbE6G.mjs} +82 -99
- package/dist/context-handover-cache-k2kWbE6G.mjs.map +1 -0
- package/dist/daemon/index.mjs +18 -24
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/daemon-B7Y8GQnt.mjs +19 -0
- package/dist/{daemon-BkJNFWr9.mjs → daemon-Cgrdvdo6.mjs} +97 -466
- package/dist/daemon-Cgrdvdo6.mjs.map +1 -0
- package/dist/daemon-mcp/index.mjs +10 -10
- package/dist/daemon-mcp/index.mjs.map +1 -1
- package/dist/{detector-DWXkeTlk.mjs → detector-3g7XuU1r.mjs} +5 -12
- package/dist/detector-3g7XuU1r.mjs.map +1 -0
- package/dist/detector-DgDn56j-.mjs +3 -0
- package/dist/{embeddings-ClqKtLZ8.mjs → embeddings-BNv3TQC5.mjs} +1 -1
- package/dist/{embeddings-DvRKcQyt.mjs → embeddings-DfrYNIng.mjs} +1 -1
- package/dist/{embeddings-DvRKcQyt.mjs.map → embeddings-DfrYNIng.mjs.map} +1 -1
- package/dist/factory-C9wGUe30.mjs +3 -0
- package/dist/factory-DiuntvwG.mjs +250 -0
- package/dist/factory-DiuntvwG.mjs.map +1 -0
- package/dist/{fallback-CPfyTSTx.mjs → fallback-DS6AEJsU.mjs} +190 -132
- package/dist/fallback-DS6AEJsU.mjs.map +1 -0
- package/dist/federation-db-CJDw_Pwq.mjs +3 -0
- package/dist/{db-DJ8rk0VM.mjs → federation-db-w8e-sKjp.mjs} +5 -5
- package/dist/federation-db-w8e-sKjp.mjs.map +1 -0
- package/dist/{helpers-crDEr6S2.mjs → helpers-D9WkIf9R.mjs} +1 -1
- package/dist/{helpers-crDEr6S2.mjs.map → helpers-D9WkIf9R.mjs.map} +1 -1
- package/dist/hooks/capture-all-events.mjs.map +1 -1
- package/dist/hooks/capture-session-summary.mjs.map +1 -1
- package/dist/hooks/capture-tool-output.mjs.map +1 -1
- package/dist/hooks/context-compression-hook.mjs.map +1 -1
- package/dist/hooks/load-core-context.mjs +5 -0
- package/dist/hooks/load-core-context.mjs.map +2 -2
- package/dist/hooks/load-project-context.mjs.map +1 -1
- package/dist/hooks/post-compact-inject.mjs.map +1 -1
- package/dist/hooks/route-agents-to-worker.mjs.map +1 -1
- package/dist/hooks/route-edits-to-worker.mjs +1 -1
- package/dist/hooks/route-edits-to-worker.mjs.map +2 -2
- package/dist/hooks/security-validator.mjs +8367 -19
- package/dist/hooks/security-validator.mjs.map +4 -4
- package/dist/hooks/stop-hook.mjs.map +2 -2
- package/dist/hooks/whisper-rules.mjs.map +2 -2
- package/dist/hooks/worker-proxy.mjs.map +1 -1
- package/dist/hooks/worker-status-line.mjs.map +2 -2
- package/dist/hooks/worker-supervision.mjs.map +1 -1
- package/dist/index.d.mts +327 -100
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +7 -11
- package/dist/indexer-backend-Cc-_NK3q.mjs +1 -0
- package/dist/indexer-backend-DcDtin1O.mjs +5 -0
- package/dist/{ipc-client-C6NryMMb.mjs → ipc-client-Dasm515c.mjs} +2 -2
- package/dist/{ipc-client-C6NryMMb.mjs.map → ipc-client-Dasm515c.mjs.map} +1 -1
- package/dist/kg-entity-Cj8Q6YmU.mjs +29 -0
- package/dist/kg-entity-Cj8Q6YmU.mjs.map +1 -0
- package/dist/{latent-ideas-BfL4nCQ3.mjs → latent-ideas-BRy6HNwg.mjs} +4 -4
- package/dist/{latent-ideas-BfL4nCQ3.mjs.map → latent-ideas-BRy6HNwg.mjs.map} +1 -1
- package/dist/{link-boost-C5PaNdzm.mjs → link-boost-BptbAPuv.mjs} +1 -1
- package/dist/{link-boost-C5PaNdzm.mjs.map → link-boost-BptbAPuv.mjs.map} +1 -1
- package/dist/{main-resolver-Bt1f6jJc.mjs → main-resolver-Dx-pxic1.mjs} +56 -31
- package/dist/main-resolver-Dx-pxic1.mjs.map +1 -0
- package/dist/main-resolver-uDtK9p6e.mjs +7 -0
- package/dist/merge-BncjJTfb.mjs +3 -0
- package/dist/merge-xoyfZQ4W.mjs +6 -0
- package/dist/merge-xoyfZQ4W.mjs.map +1 -0
- package/dist/{migrate-CfERwXhY.mjs → migrate-BD7D8EEh.mjs} +21 -54
- package/dist/migrate-BD7D8EEh.mjs.map +1 -0
- package/dist/{neighborhood-CETR_P4y.mjs → neighborhood-D8uscnGy.mjs} +4 -25
- package/dist/neighborhood-D8uscnGy.mjs.map +1 -0
- package/dist/{note-context-DCcRWBoN.mjs → note-context-CgffaUMh.mjs} +3 -23
- package/dist/note-context-CgffaUMh.mjs.map +1 -0
- package/dist/{pai-home-ChAOupZc.mjs → pai-home-CeOIYltV.mjs} +2 -2
- package/dist/pai-home-CeOIYltV.mjs.map +1 -0
- package/dist/{pai-marker-B20KqhA8.mjs → pai-marker-D1MMswkz.mjs} +1 -1
- package/dist/{pai-marker-B20KqhA8.mjs.map → pai-marker-D1MMswkz.mjs.map} +1 -1
- package/dist/{planner-BLbCtBUa.mjs → planner-C2wWnZrZ.mjs} +7 -7
- package/dist/{planner-BLbCtBUa.mjs.map → planner-C2wWnZrZ.mjs.map} +1 -1
- package/dist/{postgres-CUSXWgTG.mjs → postgres-nvU5pShF.mjs} +863 -4
- package/dist/postgres-nvU5pShF.mjs.map +1 -0
- package/dist/{program-DYux0CW2.mjs → program-Cb-9J5Ie.mjs} +2260 -1399
- package/dist/program-Cb-9J5Ie.mjs.map +1 -0
- package/dist/query-feedback-COYCnvHQ.mjs +3 -0
- package/dist/{query-feedback-CTs_jx6i.mjs → query-feedback-xz5axTj3.mjs} +3 -3
- package/dist/query-feedback-xz5axTj3.mjs.map +1 -0
- package/dist/{db-Ddns80yf.mjs → registry-db-Bkpbp7Gf.mjs} +5 -5
- package/dist/registry-db-Bkpbp7Gf.mjs.map +1 -0
- package/dist/registry-db-DwXpf7yF.mjs +3 -0
- package/dist/registry-postgres-B07-hmn8.mjs +795 -0
- package/dist/registry-postgres-B07-hmn8.mjs.map +1 -0
- package/dist/registry-sqlite-CkGND_tm.mjs +593 -0
- package/dist/registry-sqlite-CkGND_tm.mjs.map +1 -0
- package/dist/{reranker-B5qUTamW.mjs → reranker-BS5gqGeF.mjs} +1 -1
- package/dist/{reranker-HHmhZk6v.mjs → reranker-CRVawoEh.mjs} +1 -1
- package/dist/{reranker-HHmhZk6v.mjs.map → reranker-CRVawoEh.mjs.map} +1 -1
- package/dist/router-BXOf_e9e.mjs +3 -0
- package/dist/{router-DBAZfE7X.mjs → router-BdxdsAvs.mjs} +2 -2
- package/dist/{router-DBAZfE7X.mjs.map → router-BdxdsAvs.mjs.map} +1 -1
- package/dist/{run-C7EDdVAB.mjs → run-DkTrZejF.mjs} +268 -53
- package/dist/run-DkTrZejF.mjs.map +1 -0
- package/dist/{runtime-paths-B0P1TvUr.mjs → runtime-paths-BRwDeBEg.mjs} +1 -1
- package/dist/{runtime-paths-B0P1TvUr.mjs.map → runtime-paths-BRwDeBEg.mjs.map} +1 -1
- package/dist/search-BQHL5wDr.mjs +3 -0
- package/dist/search-BaTbyWjK.mjs +107 -0
- package/dist/search-BaTbyWjK.mjs.map +1 -0
- package/dist/{server-CGiHdaUp.mjs → server-CGuZFOeR.mjs} +4 -4
- package/dist/{server-CGiHdaUp.mjs.map → server-CGuZFOeR.mjs.map} +1 -1
- package/dist/{session-keepalive-DC2JGggK.mjs → session-keepalive-C5_69Av6.mjs} +7 -7
- package/dist/{session-keepalive-DC2JGggK.mjs.map → session-keepalive-C5_69Av6.mjs.map} +1 -1
- package/dist/skills/Plan/SKILL.md +1 -1
- package/dist/{sources-KBGEA_E6.mjs → sources-BBe3AZ-W.mjs} +8 -27
- package/dist/sources-BBe3AZ-W.mjs.map +1 -0
- package/dist/sqlite-D9p5a4qe.mjs +935 -0
- package/dist/sqlite-D9p5a4qe.mjs.map +1 -0
- package/dist/state-CwlGAKgF.mjs +3 -0
- package/dist/{state-DwrsOoMi.mjs → state-n13uPK5B.mjs} +6 -5
- package/dist/state-n13uPK5B.mjs.map +1 -0
- package/dist/{stop-words-BaMEGVeY.mjs → stop-words-ClCwO8mZ.mjs} +1 -1
- package/dist/{stop-words-BaMEGVeY.mjs.map → stop-words-ClCwO8mZ.mjs.map} +1 -1
- package/dist/{themes-BVoAnLZj.mjs → themes-B2v7RNnA.mjs} +3 -3
- package/dist/{themes-BVoAnLZj.mjs.map → themes-B2v7RNnA.mjs.map} +1 -1
- package/dist/{tools-BEqiJt_j.mjs → tools-Diro2s8J.mjs} +157 -398
- package/dist/tools-Diro2s8J.mjs.map +1 -0
- package/dist/{tools-BwsOTmjh.mjs → tools-KgL1rkPD.mjs} +4 -4
- package/dist/{trace-Cy8quQTm.mjs → trace-BRflVyBi.mjs} +1 -1
- package/dist/{trace-Cy8quQTm.mjs.map → trace-BRflVyBi.mjs.map} +1 -1
- package/dist/{utils-BD8g8oSf.mjs → utils-BrX9FLeK.mjs} +1 -1
- package/dist/{utils-CJymHkYm.mjs → utils-C9HsYDpO.mjs} +1 -1
- package/dist/{utils-CJymHkYm.mjs.map → utils-C9HsYDpO.mjs.map} +1 -1
- package/dist/{vault-indexer-C5i-OAyr.mjs → vault-indexer-DHYBpRZ5.mjs} +2 -2
- package/dist/{vault-indexer-C5i-OAyr.mjs.map → vault-indexer-DHYBpRZ5.mjs.map} +1 -1
- package/dist/{wakeup-Yk5lQ0jb.mjs → wakeup-D0uvqLsE.mjs} +95 -4
- package/dist/wakeup-D0uvqLsE.mjs.map +1 -0
- package/dist/work-queue-worker-DEbWsrDQ.mjs +11 -0
- package/dist/{work-queue-worker-utPp4hUv.mjs → work-queue-worker-DufMOtrL.mjs} +9 -9
- package/dist/work-queue-worker-DufMOtrL.mjs.map +1 -0
- package/dist/{zettelkasten-DezbXghl.mjs → zettelkasten-BPxSOalU.mjs} +4 -4
- package/dist/{zettelkasten-DezbXghl.mjs.map → zettelkasten-BPxSOalU.mjs.map} +1 -1
- package/docker/init.sql +5 -1
- package/docs/commands/README.md +5 -0
- package/docs/commands/audit.md +1 -1
- package/docs/commands/backup.md +1 -1
- package/docs/commands/clear-names.md +1 -1
- package/docs/commands/config.md +4 -4
- package/docs/commands/daemon.md +1 -1
- package/docs/commands/db.md +15 -1
- package/docs/commands/end.md +1 -1
- package/docs/commands/help.md +1 -1
- package/docs/commands/hooks-db.md +47 -0
- package/docs/commands/identity.md +1 -1
- package/docs/commands/kg.md +1 -1
- package/docs/commands/launch.md +1 -1
- package/docs/commands/mcp.md +1 -1
- package/docs/commands/memory.md +1 -1
- package/docs/commands/notify.md +1 -1
- package/docs/commands/observation.md +1 -1
- package/docs/commands/obsidian.md +1 -1
- package/docs/commands/pause.md +1 -1
- package/docs/commands/project.md +1 -1
- package/docs/commands/projects.md +1 -1
- package/docs/commands/registry.md +1 -1
- package/docs/commands/restore.md +1 -1
- package/docs/commands/session.md +2 -2
- package/docs/commands/sessions.md +1 -1
- package/docs/commands/setup.md +1 -1
- package/docs/commands/shell-init.md +1 -1
- package/docs/commands/skill.md +1 -1
- package/docs/commands/task.md +1 -1
- package/docs/commands/topic.md +1 -1
- package/docs/commands/update.md +1 -1
- package/docs/commands/worker.md +1 -1
- package/docs/commands/zettel.md +1 -1
- package/docs/design/postgres-only.md +438 -0
- package/docs/design/registry-method-map.md +174 -0
- package/package.json +1 -1
- package/src/hooks/pre-compact.sh +2 -40
- package/src/hooks/session-hooks-db.test.ts +93 -0
- package/src/hooks/session-stop.sh +2 -26
- package/src/hooks/ts/lib/edit-gate.test.ts +9 -0
- package/src/hooks/ts/lib/edit-gate.ts +5 -2
- package/src/hooks/ts/lib/plutil-guard.test.ts +54 -0
- package/src/hooks/ts/lib/plutil-guard.ts +43 -0
- package/src/hooks/ts/lib/worker-git-guard.test.ts +134 -0
- package/src/hooks/ts/lib/worker-git-guard.ts +103 -0
- package/src/hooks/ts/pre-tool-use/security-validator.test.ts +68 -0
- package/src/hooks/ts/pre-tool-use/security-validator.ts +69 -21
- package/src/hooks/ts/session-start/load-core-context.ts +13 -0
- package/src/hooks/ts/session-start/session-start-worker-guard.test.ts +13 -0
- package/dist/auto-route-CcD0OWWB.mjs +0 -86
- package/dist/auto-route-CcD0OWWB.mjs.map +0 -1
- package/dist/clusters-Cw_P6lO-.mjs.map +0 -1
- package/dist/context-handover-cache-CXyH6QsC.mjs.map +0 -1
- package/dist/daemon-BkJNFWr9.mjs.map +0 -1
- package/dist/daemon-CiythMfR.mjs +0 -25
- package/dist/db-BOBfewFH.mjs +0 -3
- package/dist/db-DJ8rk0VM.mjs.map +0 -1
- package/dist/db-DbY2O8QO.mjs +0 -3
- package/dist/db-Ddns80yf.mjs.map +0 -1
- package/dist/detect-Bf2z-oKB.mjs +0 -86
- package/dist/detect-Bf2z-oKB.mjs.map +0 -1
- package/dist/detector-CkwkXuGh.mjs +0 -5
- package/dist/detector-DWXkeTlk.mjs.map +0 -1
- package/dist/factory-Ba8j9K7q.mjs +0 -3
- package/dist/factory-Bt7TWQje.mjs +0 -150
- package/dist/factory-Bt7TWQje.mjs.map +0 -1
- package/dist/fallback-CPfyTSTx.mjs.map +0 -1
- package/dist/indexer-backend-CdvCJCkD.mjs.map +0 -1
- package/dist/kg-entity-BSW7ra8i.mjs +0 -176
- package/dist/kg-entity-BSW7ra8i.mjs.map +0 -1
- package/dist/main-resolver-Bt1f6jJc.mjs.map +0 -1
- package/dist/main-resolver-DYHhw5Ig.mjs +0 -7
- package/dist/migrate-CfERwXhY.mjs.map +0 -1
- package/dist/neighborhood-CETR_P4y.mjs.map +0 -1
- package/dist/note-context-DCcRWBoN.mjs.map +0 -1
- package/dist/pai-home-ChAOupZc.mjs.map +0 -1
- package/dist/postgres-CUSXWgTG.mjs.map +0 -1
- package/dist/program-DYux0CW2.mjs.map +0 -1
- package/dist/query-feedback-Bm6XvCmg.mjs +0 -3
- package/dist/query-feedback-CTs_jx6i.mjs.map +0 -1
- package/dist/router-CremHKTI.mjs +0 -3
- package/dist/run-C7EDdVAB.mjs.map +0 -1
- package/dist/search-B69cQwDB.mjs +0 -303
- package/dist/search-B69cQwDB.mjs.map +0 -1
- package/dist/search-fb-5ovj4.mjs +0 -4
- package/dist/sources-KBGEA_E6.mjs.map +0 -1
- package/dist/sqlite-By6r2YhZ.mjs +0 -271
- package/dist/sqlite-By6r2YhZ.mjs.map +0 -1
- package/dist/state-Ca0ltLgI.mjs +0 -3
- package/dist/state-DwrsOoMi.mjs.map +0 -1
- package/dist/sync-Btcb6xA4.mjs +0 -310
- package/dist/sync-Btcb6xA4.mjs.map +0 -1
- package/dist/tools-BEqiJt_j.mjs.map +0 -1
- package/dist/wakeup-Yk5lQ0jb.mjs.map +0 -1
- package/dist/work-queue-worker-DsdJx-jn.mjs +0 -14
- package/dist/work-queue-worker-utPp4hUv.mjs.map +0 -1
|
@@ -24,7 +24,7 @@ function decideEditGate(ctx) {
|
|
|
24
24
|
const label = basename(ctx.filePath).slice(0, 60) || "edit";
|
|
25
25
|
return {
|
|
26
26
|
decision: "block",
|
|
27
|
-
reason: `main session does not edit code:
|
|
27
|
+
reason: `main session does not edit code \u2014 this is a standing policy for the whole session, not a problem with this edit: retrying Edit/Write on ${ctx.filePath} or any other code file will be denied the same way. Next step: write a spec file, then run pai worker run --label "${label}" --class implement --provider anthropic --output-format json -p "$(cat <spec>)" (target: ${ctx.filePath})`
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/hooks/ts/pre-tool-use/route-edits-to-worker.ts", "../../../src/hooks/ts/lib/edit-gate.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n\n/**\n * route-edits-to-worker.ts \u2014 PreToolUse (Edit|MultiEdit|Write)\n *\n * The outer orchestrator session does not edit code files; code changes go\n * through `pai worker run`. Allowed through silently:\n * - worker sessions (the runner sets PAI_WORKER=1)\n * - paths outside any git work tree\n * - the exempt scratch prefixes (.claude incl. memory dirs, the local\n * notes/tasks/scratchpad dirs, the OS temp dir)\n * - prose: notes, session logs, handovers \u2014 see lib/edit-gate.ts isProseEdit\n * Everything else inside a git work tree is blocked with the worker command.\n *\n * This file is only I/O: read stdin, resolve the path, ask lib/edit-gate for\n * the decision, print it. The decision itself lives in lib/edit-gate.ts and\n * is tested there.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { decideEditGate, type EditGateContext } from \"../lib/edit-gate.js\";\n\nfunction isUnder(p: string, prefix: string): boolean {\n return p === prefix || p.startsWith(prefix + sep);\n}\n\n// A .git entry in any ancestor marks a git work tree (.git is a directory in\n// a normal repo, a file in a linked worktree \u2014 existsSync covers both).\nfunction inGitWorkTree(p: string): boolean {\n let dir = resolve(p);\n for (;;) {\n if (existsSync(join(dir, \".git\"))) return true;\n const parent = dirname(dir);\n if (parent === dir) return false;\n dir = parent;\n }\n}\n\nfunction exemptPrefixes(): string[] {\n const home = homedir();\n return [\n join(home, \".claude\"),\n join(home, \"colibri\", \"Notes\"),\n join(home, \"colibri\", \"tasks\"),\n join(home, \"colibri\", \"scratchpad\"),\n tmpdir(),\n \"/tmp\",\n ];\n}\n\nfunction allow(): void {\n process.exit(0);\n}\n\nfunction block(reason: string): void {\n process.stdout.write(JSON.stringify({ decision: \"block\", reason }) + \"\\n\");\n process.exit(0);\n}\n\nasync function main(): Promise<void> {\n let text = \"\";\n try {\n for await (const chunk of process.stdin) text += chunk;\n } catch {\n return allow();\n }\n if (!text.trim()) return allow();\n\n let input: { cwd?: string; tool_input?: { file_path?: string } };\n try {\n input = JSON.parse(text);\n } catch {\n return allow();\n }\n\n const filePath =\n input.tool_input && typeof input.tool_input.file_path === \"string\" ? input.tool_input.file_path : \"\";\n if (!filePath) return allow();\n\n const abs = resolve(input.cwd ?? process.cwd(), filePath);\n\n const ctx: EditGateContext = {\n filePath: abs,\n isPaiWorker: process.env.PAI_WORKER === \"1\",\n isExemptPrefix: exemptPrefixes().some((p) => isUnder(abs, p)),\n isGitWorkTree: inGitWorkTree(abs),\n };\n\n const decision = decideEditGate(ctx);\n if (decision.decision === \"block\") return block(decision.reason);\n return allow();\n}\n\nmain().catch(() => process.exit(0));\n", "/**\n * edit-gate.ts \u2014 the decision behind the PreToolUse edit-routing gate.\n *\n * Pure: no stdin, no filesystem, no process.env read of its own. The hook\n * entry (pre-tool-use/route-edits-to-worker.ts) resolves paths and checks the\n * filesystem/env, then hands this module the already-computed facts to\n * decide on \u2014 same split as lib/agent-gate.ts.\n */\n\nimport { basename, extname } from \"node:path\";\n\nexport interface EditGateContext {\n /** Absolute, already-resolved target path. */\n filePath: string;\n isPaiWorker: boolean;\n isExemptPrefix: boolean;\n isGitWorkTree: boolean;\n}\n\nexport type EditGateDecision = { decision: \"allow\" } | { decision: \"block\"; reason: string };\n\n/** Extensions that are prose regardless of which directory they live in. */\nconst PROSE_EXTENSIONS = new Set([\".md\", \".markdown\", \".txt\"]);\n\n/**\n * True for notes, session logs, handovers and other prose the outer session\n * writes directly instead of routing through a worker \u2014 a `Notes`/`notes`\n * directory segment anywhere in the path, or a prose file extension.\n * Extension check runs first: a source file that happens to live under a\n * `notes/` directory is still code, but `src/foo.md` is still prose.\n */\nexport function isProseEdit(filePath: string): boolean {\n const ext = extname(filePath).toLowerCase();\n if (PROSE_EXTENSIONS.has(ext)) return true;\n return filePath.split(/[\\\\/]/).some((segment) => segment === \"Notes\" || segment === \"notes\");\n}\n\nexport function decideEditGate(ctx: EditGateContext): EditGateDecision {\n if (ctx.isPaiWorker) return { decision: \"allow\" };\n if (ctx.isExemptPrefix) return { decision: \"allow\" };\n if (isProseEdit(ctx.filePath)) return { decision: \"allow\" };\n if (!ctx.isGitWorkTree) return { decision: \"allow\" };\n\n const label = basename(ctx.filePath).slice(0, 60) || \"edit\";\n return {\n decision: \"block\",\n reason:\n `main session does not edit code:
|
|
5
|
-
"mappings": ";;;;;;AAmBA,SAAS,kBAAkB;AAC3B,SAAS,SAAS,MAAM,SAAS,WAAW;AAC5C,SAAS,SAAS,cAAc;;;ACZhC,SAAS,UAAU,eAAe;AAalC,IAAM,mBAAmB,oBAAI,IAAI,CAAC,OAAO,aAAa,MAAM,CAAC;AAStD,SAAS,YAAY,UAA2B;AACrD,QAAM,MAAM,QAAQ,QAAQ,EAAE,YAAY;AAC1C,MAAI,iBAAiB,IAAI,GAAG,EAAG,QAAO;AACtC,SAAO,SAAS,MAAM,OAAO,EAAE,KAAK,CAAC,YAAY,YAAY,WAAW,YAAY,OAAO;AAC7F;AAEO,SAAS,eAAe,KAAwC;AACrE,MAAI,IAAI,YAAa,QAAO,EAAE,UAAU,QAAQ;AAChD,MAAI,IAAI,eAAgB,QAAO,EAAE,UAAU,QAAQ;AACnD,MAAI,YAAY,IAAI,QAAQ,EAAG,QAAO,EAAE,UAAU,QAAQ;AAC1D,MAAI,CAAC,IAAI,cAAe,QAAO,EAAE,UAAU,QAAQ;AAEnD,QAAM,QAAQ,SAAS,IAAI,QAAQ,EAAE,MAAM,GAAG,EAAE,KAAK;AACrD,SAAO;AAAA,IACL,UAAU;AAAA,IACV,QACE,
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n\n/**\n * route-edits-to-worker.ts \u2014 PreToolUse (Edit|MultiEdit|Write)\n *\n * The outer orchestrator session does not edit code files; code changes go\n * through `pai worker run`. Allowed through silently:\n * - worker sessions (the runner sets PAI_WORKER=1)\n * - paths outside any git work tree\n * - the exempt scratch prefixes (.claude incl. memory dirs, the local\n * notes/tasks/scratchpad dirs, the OS temp dir)\n * - prose: notes, session logs, handovers \u2014 see lib/edit-gate.ts isProseEdit\n * Everything else inside a git work tree is blocked with the worker command.\n *\n * This file is only I/O: read stdin, resolve the path, ask lib/edit-gate for\n * the decision, print it. The decision itself lives in lib/edit-gate.ts and\n * is tested there.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { decideEditGate, type EditGateContext } from \"../lib/edit-gate.js\";\n\nfunction isUnder(p: string, prefix: string): boolean {\n return p === prefix || p.startsWith(prefix + sep);\n}\n\n// A .git entry in any ancestor marks a git work tree (.git is a directory in\n// a normal repo, a file in a linked worktree \u2014 existsSync covers both).\nfunction inGitWorkTree(p: string): boolean {\n let dir = resolve(p);\n for (;;) {\n if (existsSync(join(dir, \".git\"))) return true;\n const parent = dirname(dir);\n if (parent === dir) return false;\n dir = parent;\n }\n}\n\nfunction exemptPrefixes(): string[] {\n const home = homedir();\n return [\n join(home, \".claude\"),\n join(home, \"colibri\", \"Notes\"),\n join(home, \"colibri\", \"tasks\"),\n join(home, \"colibri\", \"scratchpad\"),\n tmpdir(),\n \"/tmp\",\n ];\n}\n\nfunction allow(): void {\n process.exit(0);\n}\n\nfunction block(reason: string): void {\n process.stdout.write(JSON.stringify({ decision: \"block\", reason }) + \"\\n\");\n process.exit(0);\n}\n\nasync function main(): Promise<void> {\n let text = \"\";\n try {\n for await (const chunk of process.stdin) text += chunk;\n } catch {\n return allow();\n }\n if (!text.trim()) return allow();\n\n let input: { cwd?: string; tool_input?: { file_path?: string } };\n try {\n input = JSON.parse(text);\n } catch {\n return allow();\n }\n\n const filePath =\n input.tool_input && typeof input.tool_input.file_path === \"string\" ? input.tool_input.file_path : \"\";\n if (!filePath) return allow();\n\n const abs = resolve(input.cwd ?? process.cwd(), filePath);\n\n const ctx: EditGateContext = {\n filePath: abs,\n isPaiWorker: process.env.PAI_WORKER === \"1\",\n isExemptPrefix: exemptPrefixes().some((p) => isUnder(abs, p)),\n isGitWorkTree: inGitWorkTree(abs),\n };\n\n const decision = decideEditGate(ctx);\n if (decision.decision === \"block\") return block(decision.reason);\n return allow();\n}\n\nmain().catch(() => process.exit(0));\n", "/**\n * edit-gate.ts \u2014 the decision behind the PreToolUse edit-routing gate.\n *\n * Pure: no stdin, no filesystem, no process.env read of its own. The hook\n * entry (pre-tool-use/route-edits-to-worker.ts) resolves paths and checks the\n * filesystem/env, then hands this module the already-computed facts to\n * decide on \u2014 same split as lib/agent-gate.ts.\n */\n\nimport { basename, extname } from \"node:path\";\n\nexport interface EditGateContext {\n /** Absolute, already-resolved target path. */\n filePath: string;\n isPaiWorker: boolean;\n isExemptPrefix: boolean;\n isGitWorkTree: boolean;\n}\n\nexport type EditGateDecision = { decision: \"allow\" } | { decision: \"block\"; reason: string };\n\n/** Extensions that are prose regardless of which directory they live in. */\nconst PROSE_EXTENSIONS = new Set([\".md\", \".markdown\", \".txt\"]);\n\n/**\n * True for notes, session logs, handovers and other prose the outer session\n * writes directly instead of routing through a worker \u2014 a `Notes`/`notes`\n * directory segment anywhere in the path, or a prose file extension.\n * Extension check runs first: a source file that happens to live under a\n * `notes/` directory is still code, but `src/foo.md` is still prose.\n */\nexport function isProseEdit(filePath: string): boolean {\n const ext = extname(filePath).toLowerCase();\n if (PROSE_EXTENSIONS.has(ext)) return true;\n return filePath.split(/[\\\\/]/).some((segment) => segment === \"Notes\" || segment === \"notes\");\n}\n\nexport function decideEditGate(ctx: EditGateContext): EditGateDecision {\n if (ctx.isPaiWorker) return { decision: \"allow\" };\n if (ctx.isExemptPrefix) return { decision: \"allow\" };\n if (isProseEdit(ctx.filePath)) return { decision: \"allow\" };\n if (!ctx.isGitWorkTree) return { decision: \"allow\" };\n\n const label = basename(ctx.filePath).slice(0, 60) || \"edit\";\n return {\n decision: \"block\",\n reason:\n `main session does not edit code \u2014 this is a standing policy for the whole session, not a problem ` +\n `with this edit: retrying Edit/Write on ${ctx.filePath} or any other code file will be denied the ` +\n `same way. Next step: write a spec file, then run ` +\n `pai worker run --label \"${label}\" --class implement --provider anthropic --output-format json -p \"$(cat <spec>)\" ` +\n `(target: ${ctx.filePath})`,\n };\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;AAmBA,SAAS,kBAAkB;AAC3B,SAAS,SAAS,MAAM,SAAS,WAAW;AAC5C,SAAS,SAAS,cAAc;;;ACZhC,SAAS,UAAU,eAAe;AAalC,IAAM,mBAAmB,oBAAI,IAAI,CAAC,OAAO,aAAa,MAAM,CAAC;AAStD,SAAS,YAAY,UAA2B;AACrD,QAAM,MAAM,QAAQ,QAAQ,EAAE,YAAY;AAC1C,MAAI,iBAAiB,IAAI,GAAG,EAAG,QAAO;AACtC,SAAO,SAAS,MAAM,OAAO,EAAE,KAAK,CAAC,YAAY,YAAY,WAAW,YAAY,OAAO;AAC7F;AAEO,SAAS,eAAe,KAAwC;AACrE,MAAI,IAAI,YAAa,QAAO,EAAE,UAAU,QAAQ;AAChD,MAAI,IAAI,eAAgB,QAAO,EAAE,UAAU,QAAQ;AACnD,MAAI,YAAY,IAAI,QAAQ,EAAG,QAAO,EAAE,UAAU,QAAQ;AAC1D,MAAI,CAAC,IAAI,cAAe,QAAO,EAAE,UAAU,QAAQ;AAEnD,QAAM,QAAQ,SAAS,IAAI,QAAQ,EAAE,MAAM,GAAG,EAAE,KAAK;AACrD,SAAO;AAAA,IACL,UAAU;AAAA,IACV,QACE,gJAC0C,IAAI,QAAQ,uHAE3B,KAAK,6FACpB,IAAI,QAAQ;AAAA,EAC5B;AACF;;;AD7BA,SAAS,QAAQ,GAAW,QAAyB;AACnD,SAAO,MAAM,UAAU,EAAE,WAAW,SAAS,GAAG;AAClD;AAIA,SAAS,cAAc,GAAoB;AACzC,MAAI,MAAM,QAAQ,CAAC;AACnB,aAAS;AACP,QAAI,WAAW,KAAK,KAAK,MAAM,CAAC,EAAG,QAAO;AAC1C,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACF;AAEA,SAAS,iBAA2B;AAClC,QAAM,OAAO,QAAQ;AACrB,SAAO;AAAA,IACL,KAAK,MAAM,SAAS;AAAA,IACpB,KAAK,MAAM,WAAW,OAAO;AAAA,IAC7B,KAAK,MAAM,WAAW,OAAO;AAAA,IAC7B,KAAK,MAAM,WAAW,YAAY;AAAA,IAClC,OAAO;AAAA,IACP;AAAA,EACF;AACF;AAEA,SAAS,QAAc;AACrB,UAAQ,KAAK,CAAC;AAChB;AAEA,SAAS,MAAM,QAAsB;AACnC,UAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,UAAU,SAAS,OAAO,CAAC,IAAI,IAAI;AACzE,UAAQ,KAAK,CAAC;AAChB;AAEA,eAAe,OAAsB;AACnC,MAAI,OAAO;AACX,MAAI;AACF,qBAAiB,SAAS,QAAQ,MAAO,SAAQ;AAAA,EACnD,QAAQ;AACN,WAAO,MAAM;AAAA,EACf;AACA,MAAI,CAAC,KAAK,KAAK,EAAG,QAAO,MAAM;AAE/B,MAAI;AACJ,MAAI;AACF,YAAQ,KAAK,MAAM,IAAI;AAAA,EACzB,QAAQ;AACN,WAAO,MAAM;AAAA,EACf;AAEA,QAAM,WACJ,MAAM,cAAc,OAAO,MAAM,WAAW,cAAc,WAAW,MAAM,WAAW,YAAY;AACpG,MAAI,CAAC,SAAU,QAAO,MAAM;AAE5B,QAAM,MAAM,QAAQ,MAAM,OAAO,QAAQ,IAAI,GAAG,QAAQ;AAExD,QAAM,MAAuB;AAAA,IAC3B,UAAU;AAAA,IACV,aAAa,QAAQ,IAAI,eAAe;AAAA,IACxC,gBAAgB,eAAe,EAAE,KAAK,CAAC,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,IAC5D,eAAe,cAAc,GAAG;AAAA,EAClC;AAEA,QAAM,WAAW,eAAe,GAAG;AACnC,MAAI,SAAS,aAAa,QAAS,QAAO,MAAM,SAAS,MAAM;AAC/D,SAAO,MAAM;AACf;AAEA,KAAK,EAAE,MAAM,MAAM,QAAQ,KAAK,CAAC,CAAC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|