opensquid 0.5.441 → 0.5.447
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/functions/arm_scope.d.ts +27 -0
- package/dist/functions/arm_scope.d.ts.map +1 -0
- package/dist/functions/arm_scope.js +52 -0
- package/dist/functions/arm_scope.js.map +1 -0
- package/dist/functions/index.d.ts +1 -0
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +1 -0
- package/dist/functions/index.js.map +1 -1
- package/dist/runtime/bootstrap.d.ts.map +1 -1
- package/dist/runtime/bootstrap.js +2 -0
- package/dist/runtime/bootstrap.js.map +1 -1
- package/dist/runtime/handoff/render.d.ts +5 -4
- package/dist/runtime/handoff/render.d.ts.map +1 -1
- package/dist/runtime/handoff/render.js +7 -7
- package/dist/runtime/handoff/render.js.map +1 -1
- package/dist/runtime/hooks/active_task_mirror.js +0 -0
- package/dist/runtime/hooks/apply_patch.js +0 -0
- package/dist/runtime/hooks/dispatch.js +0 -0
- package/dist/runtime/hooks/hook_output.js +0 -0
- package/dist/runtime/hooks/memory_reconcile.js +0 -0
- package/dist/runtime/hooks/new_project_detect.js +0 -0
- package/dist/runtime/hooks/profession_resolver.js +0 -0
- package/dist/runtime/hooks/scope_intent.js +0 -0
- package/dist/runtime/hooks/session_id.js +0 -0
- package/dist/runtime/hooks/session_liveness.js +0 -0
- package/dist/runtime/hooks/stop_drive.js +0 -0
- package/dist/runtime/hooks/stop_stream.js +0 -0
- package/dist/runtime/hooks/subagent_guard.js +0 -0
- package/dist/runtime/hooks/transcript.js +0 -0
- package/dist/runtime/hooks/transcript_tasks.js +0 -0
- package/dist/runtime/ralph/orchestrator.d.ts.map +1 -1
- package/dist/runtime/ralph/orchestrator.js +2 -1
- package/dist/runtime/ralph/orchestrator.js.map +1 -1
- package/dist/setup/cli/limits_state.d.ts.map +1 -1
- package/dist/setup/cli/limits_state.js +6 -40
- package/dist/setup/cli/limits_state.js.map +1 -1
- package/dist/setup/cli/pack_walk.d.ts +32 -0
- package/dist/setup/cli/pack_walk.d.ts.map +1 -0
- package/dist/setup/cli/pack_walk.js +76 -0
- package/dist/setup/cli/pack_walk.js.map +1 -0
- package/dist/setup/cli/permissions_state.d.ts.map +1 -1
- package/dist/setup/cli/permissions_state.js +6 -37
- package/dist/setup/cli/permissions_state.js.map +1 -1
- package/dist/setup/cli/triggers_state.d.ts.map +1 -1
- package/dist/setup/cli/triggers_state.js +3 -29
- package/dist/setup/cli/triggers_state.js.map +1 -1
- package/dist/workgraph/events.d.ts.map +1 -1
- package/dist/workgraph/events.js +10 -0
- package/dist/workgraph/events.js.map +1 -1
- package/dist/workgraph/store.d.ts.map +1 -1
- package/dist/workgraph/store.js +5 -0
- package/dist/workgraph/store.js.map +1 -1
- package/dist/workgraph/types.d.ts +2 -1
- package/dist/workgraph/types.d.ts.map +1 -1
- package/docs/ARCHITECTURE.md +268 -0
- package/package.json +5 -3
- package/packs/builtin/coding-flow/skills/entry-and-handoffs/skill.yaml +13 -17
- package/dist/anti-drift/evaluator.d.ts +0 -88
- package/dist/anti-drift/evaluator.d.ts.map +0 -1
- package/dist/anti-drift/evaluator.js +0 -417
- package/dist/anti-drift/evaluator.js.map +0 -1
- package/dist/anti-drift/evaluator.test.js +0 -78
- package/dist/anti-drift/rules.d.ts +0 -80
- package/dist/anti-drift/rules.d.ts.map +0 -1
- package/dist/anti-drift/rules.js +0 -368
- package/dist/anti-drift/rules.js.map +0 -1
- package/dist/anti-drift/rules.test.js +0 -213
- package/dist/anti-drift/state.d.ts +0 -107
- package/dist/anti-drift/state.d.ts.map +0 -1
- package/dist/anti-drift/state.js +0 -177
- package/dist/anti-drift/state.js.map +0 -1
- package/dist/anti-drift/state.test.js +0 -120
- package/dist/chat/adapters/discord.d.ts +0 -41
- package/dist/chat/adapters/discord.d.ts.map +0 -1
- package/dist/chat/adapters/discord.js +0 -176
- package/dist/chat/adapters/discord.js.map +0 -1
- package/dist/chat/adapters/discord.test.js +0 -25
- package/dist/chat/adapters/slack.d.ts +0 -43
- package/dist/chat/adapters/slack.d.ts.map +0 -1
- package/dist/chat/adapters/slack.js +0 -172
- package/dist/chat/adapters/slack.js.map +0 -1
- package/dist/chat/adapters/slack.test.js +0 -30
- package/dist/chat/adapters/telegram.d.ts +0 -148
- package/dist/chat/adapters/telegram.d.ts.map +0 -1
- package/dist/chat/adapters/telegram.js +0 -498
- package/dist/chat/adapters/telegram.js.map +0 -1
- package/dist/chat/adapters/telegram.test.js +0 -94
- package/dist/chat/config.d.ts +0 -98
- package/dist/chat/config.d.ts.map +0 -1
- package/dist/chat/config.js +0 -185
- package/dist/chat/config.js.map +0 -1
- package/dist/chat/daemon/active-project.d.ts +0 -17
- package/dist/chat/daemon/active-project.d.ts.map +0 -1
- package/dist/chat/daemon/active-project.js +0 -23
- package/dist/chat/daemon/active-project.js.map +0 -1
- package/dist/chat/daemon/autospawn.d.ts +0 -40
- package/dist/chat/daemon/autospawn.d.ts.map +0 -1
- package/dist/chat/daemon/autospawn.js +0 -129
- package/dist/chat/daemon/autospawn.js.map +0 -1
- package/dist/chat/daemon/autospawn.test.js +0 -112
- package/dist/chat/daemon/cli.d.ts +0 -18
- package/dist/chat/daemon/cli.d.ts.map +0 -1
- package/dist/chat/daemon/cli.js +0 -71
- package/dist/chat/daemon/cli.js.map +0 -1
- package/dist/chat/daemon/collisions.js +0 -384
- package/dist/chat/daemon/health-check.d.ts +0 -69
- package/dist/chat/daemon/health-check.d.ts.map +0 -1
- package/dist/chat/daemon/health-check.js +0 -112
- package/dist/chat/daemon/health-check.js.map +0 -1
- package/dist/chat/daemon/inbox-read.d.ts +0 -35
- package/dist/chat/daemon/inbox-read.d.ts.map +0 -1
- package/dist/chat/daemon/inbox-read.js +0 -75
- package/dist/chat/daemon/inbox-read.js.map +0 -1
- package/dist/chat/daemon/inbox-read.test.js +0 -97
- package/dist/chat/daemon/inbox.d.ts +0 -63
- package/dist/chat/daemon/inbox.d.ts.map +0 -1
- package/dist/chat/daemon/inbox.js +0 -56
- package/dist/chat/daemon/inbox.js.map +0 -1
- package/dist/chat/daemon/inbox.test.js +0 -110
- package/dist/chat/daemon/lifecycle.d.ts +0 -71
- package/dist/chat/daemon/lifecycle.d.ts.map +0 -1
- package/dist/chat/daemon/lifecycle.js +0 -221
- package/dist/chat/daemon/lifecycle.js.map +0 -1
- package/dist/chat/daemon/lifecycle.test.js +0 -163
- package/dist/chat/daemon/protocol.d.ts +0 -107
- package/dist/chat/daemon/protocol.d.ts.map +0 -1
- package/dist/chat/daemon/protocol.js +0 -54
- package/dist/chat/daemon/protocol.js.map +0 -1
- package/dist/chat/daemon/routing.d.ts +0 -140
- package/dist/chat/daemon/routing.d.ts.map +0 -1
- package/dist/chat/daemon/routing.js +0 -198
- package/dist/chat/daemon/routing.js.map +0 -1
- package/dist/chat/daemon/routing.test.js +0 -259
- package/dist/chat/daemon/rpc-client.d.ts +0 -45
- package/dist/chat/daemon/rpc-client.d.ts.map +0 -1
- package/dist/chat/daemon/rpc-client.js +0 -133
- package/dist/chat/daemon/rpc-client.js.map +0 -1
- package/dist/chat/daemon/rpc-server.d.ts +0 -39
- package/dist/chat/daemon/rpc-server.d.ts.map +0 -1
- package/dist/chat/daemon/rpc-server.js +0 -385
- package/dist/chat/daemon/rpc-server.js.map +0 -1
- package/dist/chat/daemon/rpc.test.js +0 -177
- package/dist/chat/daemon/subscribers.js +0 -257
- package/dist/chat/daemon/worker.d.ts +0 -27
- package/dist/chat/daemon/worker.d.ts.map +0 -1
- package/dist/chat/daemon/worker.js +0 -313
- package/dist/chat/daemon/worker.js.map +0 -1
- package/dist/chat/daemon/workspace-topic.js +0 -324
- package/dist/chat/env-token.d.ts +0 -60
- package/dist/chat/env-token.d.ts.map +0 -1
- package/dist/chat/env-token.js +0 -137
- package/dist/chat/env-token.js.map +0 -1
- package/dist/chat/env-token.test.js +0 -160
- package/dist/chat/factory.d.ts +0 -30
- package/dist/chat/factory.d.ts.map +0 -1
- package/dist/chat/factory.js +0 -50
- package/dist/chat/factory.js.map +0 -1
- package/dist/chat/factory.test.js +0 -55
- package/dist/chat/gateway.d.ts +0 -176
- package/dist/chat/gateway.d.ts.map +0 -1
- package/dist/chat/gateway.js +0 -146
- package/dist/chat/gateway.js.map +0 -1
- package/dist/chat/gateway.test.js +0 -192
- package/dist/claude-md.d.ts +0 -39
- package/dist/claude-md.d.ts.map +0 -1
- package/dist/claude-md.js +0 -113
- package/dist/claude-md.js.map +0 -1
- package/dist/claude-md.test.js +0 -91
- package/dist/codex/activate.d.ts +0 -66
- package/dist/codex/activate.d.ts.map +0 -1
- package/dist/codex/activate.js +0 -329
- package/dist/codex/activate.js.map +0 -1
- package/dist/codex/activate.test.js +0 -229
- package/dist/codex/bundled-default/bundled-default.test.js +0 -161
- package/dist/codex/cli-publish.test.js +0 -133
- package/dist/codex/cli.d.ts +0 -35
- package/dist/codex/cli.d.ts.map +0 -1
- package/dist/codex/cli.js +0 -554
- package/dist/codex/cli.js.map +0 -1
- package/dist/codex/cli.test.js +0 -277
- package/dist/codex/import-skill-md.d.ts +0 -53
- package/dist/codex/import-skill-md.d.ts.map +0 -1
- package/dist/codex/import-skill-md.js +0 -236
- package/dist/codex/import-skill-md.js.map +0 -1
- package/dist/codex/import-skill-md.test.js +0 -225
- package/dist/codex/loader.d.ts +0 -27
- package/dist/codex/loader.d.ts.map +0 -1
- package/dist/codex/loader.js +0 -86
- package/dist/codex/loader.js.map +0 -1
- package/dist/codex/loader.test.js +0 -75
- package/dist/codex/parse.d.ts +0 -28
- package/dist/codex/parse.d.ts.map +0 -1
- package/dist/codex/parse.js +0 -309
- package/dist/codex/parse.js.map +0 -1
- package/dist/codex/parse.test.js +0 -241
- package/dist/codex/store.d.ts +0 -87
- package/dist/codex/store.d.ts.map +0 -1
- package/dist/codex/store.js +0 -205
- package/dist/codex/store.js.map +0 -1
- package/dist/codex/store.test.js +0 -242
- package/dist/codex/types.d.ts +0 -398
- package/dist/codex/types.d.ts.map +0 -1
- package/dist/codex/types.js +0 -21
- package/dist/codex/types.js.map +0 -1
- package/dist/config.d.ts +0 -53
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -202
- package/dist/config.js.map +0 -1
- package/dist/config.test.js +0 -117
- package/dist/engine/cli.d.ts +0 -14
- package/dist/engine/cli.d.ts.map +0 -1
- package/dist/engine/cli.js +0 -171
- package/dist/engine/cli.js.map +0 -1
- package/dist/engine/client.d.ts +0 -219
- package/dist/engine/client.d.ts.map +0 -1
- package/dist/engine/client.js +0 -312
- package/dist/engine/client.js.map +0 -1
- package/dist/engine/config.d.ts +0 -62
- package/dist/engine/config.d.ts.map +0 -1
- package/dist/engine/config.js +0 -223
- package/dist/engine/config.js.map +0 -1
- package/dist/engine/index.d.ts +0 -17
- package/dist/engine/index.d.ts.map +0 -1
- package/dist/engine/index.js +0 -16
- package/dist/engine/index.js.map +0 -1
- package/dist/engine/resolver.d.ts +0 -62
- package/dist/engine/resolver.d.ts.map +0 -1
- package/dist/engine/resolver.js +0 -103
- package/dist/engine/resolver.js.map +0 -1
- package/dist/engine/singleton.d.ts +0 -95
- package/dist/engine/singleton.d.ts.map +0 -1
- package/dist/engine/singleton.js +0 -325
- package/dist/engine/singleton.js.map +0 -1
- package/dist/engine/types.d.ts +0 -402
- package/dist/engine/types.d.ts.map +0 -1
- package/dist/engine/types.js +0 -22
- package/dist/engine/types.js.map +0 -1
- package/dist/engine-binary-resolver.js +0 -110
- package/dist/engine-binary-resolver.test.js +0 -61
- package/dist/engine-cli.js +0 -60
- package/dist/engine-client.js +0 -301
- package/dist/engine-client.test.js +0 -118
- package/dist/functions/chain_state.d.ts +0 -51
- package/dist/functions/chain_state.d.ts.map +0 -1
- package/dist/functions/chain_state.js +0 -59
- package/dist/functions/chain_state.js.map +0 -1
- package/dist/hooks/drift-catalog.d.ts +0 -68
- package/dist/hooks/drift-catalog.d.ts.map +0 -1
- package/dist/hooks/drift-catalog.js +0 -184
- package/dist/hooks/drift-catalog.js.map +0 -1
- package/dist/hooks/drift-catalog.test.js +0 -154
- package/dist/hooks/drift-patterns.d.ts +0 -110
- package/dist/hooks/drift-patterns.d.ts.map +0 -1
- package/dist/hooks/drift-patterns.js +0 -289
- package/dist/hooks/drift-patterns.js.map +0 -1
- package/dist/hooks/drift-patterns.test.js +0 -325
- package/dist/hooks/engine-vocab-gate.d.ts +0 -108
- package/dist/hooks/engine-vocab-gate.d.ts.map +0 -1
- package/dist/hooks/engine-vocab-gate.js +0 -225
- package/dist/hooks/engine-vocab-gate.js.map +0 -1
- package/dist/hooks/engine-vocab-gate.test.js +0 -170
- package/dist/hooks/heartbeat.d.ts +0 -107
- package/dist/hooks/heartbeat.d.ts.map +0 -1
- package/dist/hooks/heartbeat.js +0 -316
- package/dist/hooks/heartbeat.js.map +0 -1
- package/dist/hooks/heartbeat.test.js +0 -393
- package/dist/hooks/honesty-ledger-session-scope.test.js +0 -100
- package/dist/hooks/honesty-ledger.d.ts +0 -123
- package/dist/hooks/honesty-ledger.d.ts.map +0 -1
- package/dist/hooks/honesty-ledger.js +0 -226
- package/dist/hooks/honesty-ledger.js.map +0 -1
- package/dist/hooks/honesty-ledger.test.js +0 -466
- package/dist/hooks/inline-report-check.d.ts +0 -63
- package/dist/hooks/inline-report-check.d.ts.map +0 -1
- package/dist/hooks/inline-report-check.js +0 -88
- package/dist/hooks/inline-report-check.js.map +0 -1
- package/dist/hooks/inline-report-check.test.js +0 -96
- package/dist/hooks/pre-tool-use.d.ts +0 -62
- package/dist/hooks/pre-tool-use.d.ts.map +0 -1
- package/dist/hooks/pre-tool-use.js +0 -342
- package/dist/hooks/pre-tool-use.js.map +0 -1
- package/dist/hooks/pre-tool-use.test.js +0 -134
- package/dist/hooks/session-end.d.ts +0 -15
- package/dist/hooks/session-end.d.ts.map +0 -1
- package/dist/hooks/session-end.js +0 -60
- package/dist/hooks/session-end.js.map +0 -1
- package/dist/hooks/session-end.test.js +0 -52
- package/dist/hooks/stop.d.ts +0 -35
- package/dist/hooks/stop.d.ts.map +0 -1
- package/dist/hooks/stop.js +0 -136
- package/dist/hooks/stop.js.map +0 -1
- package/dist/hooks/transcript-active-task.test.js +0 -342
- package/dist/hooks/transcript.d.ts +0 -26
- package/dist/hooks/transcript.d.ts.map +0 -1
- package/dist/hooks/transcript.js +0 -266
- package/dist/hooks/transcript.js.map +0 -1
- package/dist/hooks/transcript.test.js +0 -103
- package/dist/hooks/user-prompt-submit.d.ts +0 -74
- package/dist/hooks/user-prompt-submit.d.ts.map +0 -1
- package/dist/hooks/user-prompt-submit.js +0 -256
- package/dist/hooks/user-prompt-submit.js.map +0 -1
- package/dist/hooks/user-prompt-submit.test.js +0 -118
- package/dist/hooks/versioning-gate.d.ts +0 -101
- package/dist/hooks/versioning-gate.d.ts.map +0 -1
- package/dist/hooks/versioning-gate.js +0 -245
- package/dist/hooks/versioning-gate.js.map +0 -1
- package/dist/hooks/versioning-gate.test.js +0 -368
- package/dist/hooks/workflow-gate.d.ts +0 -64
- package/dist/hooks/workflow-gate.d.ts.map +0 -1
- package/dist/hooks/workflow-gate.js +0 -152
- package/dist/hooks/workflow-gate.js.map +0 -1
- package/dist/hooks/workflow-gate.test.js +0 -197
- package/dist/hooks-cli.d.ts +0 -25
- package/dist/hooks-cli.d.ts.map +0 -1
- package/dist/hooks-cli.js +0 -286
- package/dist/hooks-cli.js.map +0 -1
- package/dist/hooks-cli.test.js +0 -148
- package/dist/origin.d.ts +0 -16
- package/dist/origin.d.ts.map +0 -1
- package/dist/origin.js +0 -92
- package/dist/origin.js.map +0 -1
- package/dist/packs/seed_lessons_ingest.d.ts +0 -30
- package/dist/packs/seed_lessons_ingest.d.ts.map +0 -1
- package/dist/packs/seed_lessons_ingest.js +0 -107
- package/dist/packs/seed_lessons_ingest.js.map +0 -1
- package/dist/project-cli.d.ts +0 -7
- package/dist/project-cli.d.ts.map +0 -1
- package/dist/project-cli.js +0 -145
- package/dist/project-cli.js.map +0 -1
- package/dist/project.d.ts +0 -127
- package/dist/project.d.ts.map +0 -1
- package/dist/project.js +0 -281
- package/dist/project.js.map +0 -1
- package/dist/project.test.js +0 -287
- package/dist/rag/backends/loop_engine.d.ts +0 -61
- package/dist/rag/backends/loop_engine.d.ts.map +0 -1
- package/dist/rag/backends/loop_engine.js +0 -160
- package/dist/rag/backends/loop_engine.js.map +0 -1
- package/dist/recall.d.ts +0 -82
- package/dist/recall.d.ts.map +0 -1
- package/dist/recall.js +0 -81
- package/dist/recall.js.map +0 -1
- package/dist/runtime/agent_bridge/autospawn.d.ts +0 -131
- package/dist/runtime/agent_bridge/autospawn.d.ts.map +0 -1
- package/dist/runtime/agent_bridge/autospawn.js +0 -251
- package/dist/runtime/agent_bridge/autospawn.js.map +0 -1
- package/dist/runtime/chain_state.d.ts +0 -124
- package/dist/runtime/chain_state.d.ts.map +0 -1
- package/dist/runtime/chain_state.js +0 -189
- package/dist/runtime/chain_state.js.map +0 -1
- package/dist/runtime/hooks/permission_decision.d.ts +0 -34
- package/dist/runtime/hooks/permission_decision.d.ts.map +0 -1
- package/dist/runtime/hooks/permission_decision.js +0 -39
- package/dist/runtime/hooks/permission_decision.js.map +0 -1
- package/dist/runtime/workflow_fsm.d.ts +0 -21
- package/dist/runtime/workflow_fsm.d.ts.map +0 -1
- package/dist/runtime/workflow_fsm.js +0 -25
- package/dist/runtime/workflow_fsm.js.map +0 -1
- package/dist/runtime/workflow_map.d.ts +0 -26
- package/dist/runtime/workflow_map.d.ts.map +0 -1
- package/dist/runtime/workflow_map.js +0 -38
- package/dist/runtime/workflow_map.js.map +0 -1
- package/dist/scope.d.ts +0 -48
- package/dist/scope.d.ts.map +0 -1
- package/dist/scope.js +0 -111
- package/dist/scope.js.map +0 -1
- package/dist/setup/cli/topic_create_step.d.ts +0 -84
- package/dist/setup/cli/topic_create_step.d.ts.map +0 -1
- package/dist/setup/cli/topic_create_step.js +0 -213
- package/dist/setup/cli/topic_create_step.js.map +0 -1
- package/dist/system-export.d.ts +0 -65
- package/dist/system-export.d.ts.map +0 -1
- package/dist/system-export.js +0 -194
- package/dist/system-export.js.map +0 -1
- package/dist/utterance/classifier.d.ts +0 -53
- package/dist/utterance/classifier.d.ts.map +0 -1
- package/dist/utterance/classifier.js +0 -184
- package/dist/utterance/classifier.js.map +0 -1
- package/dist/utterance/classifier.test.js +0 -147
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* agent-bridge headless responder autospawn (T-CHAT-AS-TERMINAL CAT.5.1).
|
|
3
|
-
*
|
|
4
|
-
* The chat-transport daemon (`src/channels/daemon/autospawn.ts`) already
|
|
5
|
-
* autospawns from the MCP chat-bridge boot. The HEADLESS RESPONDER — the
|
|
6
|
-
* agent-bridge daemon that ANSWERS chat when no terminal is live (CAT.5 the
|
|
7
|
-
* project umbrella's headless responder, CAT.6 the project-less `general`
|
|
8
|
-
* session) — did NOT. This module mirrors that chat-daemon autospawn so the
|
|
9
|
-
* headless responder is ALWAYS-ON too: started opportunistically on MCP boot,
|
|
10
|
-
* keyed PER-INSTANCE so `loop` + `general` run concurrently (CAT.5.1's
|
|
11
|
-
* per-scope lock/pid in daemon.ts).
|
|
12
|
-
*
|
|
13
|
-
* SAFE to autospawn the project headless even while a terminal is live: CAT.5's
|
|
14
|
-
* lease-ownership guard makes it STAND DOWN. The headless only answers when it
|
|
15
|
-
* owns a fresh umbrella lease; while a human `chat watch` lease is present the
|
|
16
|
-
* dispatcher's flush-time `isLeaseFreshAndOwnedBy` guard suppresses it — it
|
|
17
|
-
* idles at zero token cost (fs-only heartbeat) until the human lease lapses.
|
|
18
|
-
*
|
|
19
|
-
* Behavior (mirrors `ensureChatDaemonRunning`):
|
|
20
|
-
* - No-op when no chat platform is configured.
|
|
21
|
-
* - No-op when the SCOPED daemon (its own pidfile) is already running.
|
|
22
|
-
* - Else acquire an atomic per-scope spawn-lock (`fs.open(lock, 'wx')`) so two
|
|
23
|
-
* MCP servers don't double-spawn; the loser waits briefly for the pidfile.
|
|
24
|
-
* Stale lock (> 15s) is reclaimed.
|
|
25
|
-
* - Always async + non-throwing. A resolution failure (no project uuid / no
|
|
26
|
-
* pack) → `{ status: 'no_config' }` (skip that scope, never throw).
|
|
27
|
-
*
|
|
28
|
-
* It spawns `dist/cli.js agent-bridge start [--general]` DETACHED:
|
|
29
|
-
* - general: `agent-bridge start --general` (env as-is — the worker resolves
|
|
30
|
-
* the built-in `general` pack itself).
|
|
31
|
-
* - project umbrella: `agent-bridge start` with `OPENSQUID_PROJECT_UUID` +
|
|
32
|
-
* `OPENSQUID_PACK_ROOT` injected into the child env (resolved exactly like
|
|
33
|
-
* cli.ts's non-general path: `resolveProjectUuid` + `resolvePackRootFromEnv`).
|
|
34
|
-
* If the project uuid can't be resolved → skip (no-op).
|
|
35
|
-
*
|
|
36
|
-
* Imports from: node:fs, node:os, node:path, node:child_process, node:url,
|
|
37
|
-
* ../../channels/config, ../../channels/routing, ../paths, ./daemon.
|
|
38
|
-
* Imported by: src/mcp/chat-bridge-server.ts (boot) + tests.
|
|
39
|
-
*/
|
|
40
|
-
import { spawn } from 'node:child_process';
|
|
41
|
-
import { promises as fs } from 'node:fs';
|
|
42
|
-
import { dirname, resolve } from 'node:path';
|
|
43
|
-
import { fileURLToPath } from 'node:url';
|
|
44
|
-
import { loadChatConfig } from '../../channels/config.js';
|
|
45
|
-
import { GENERAL_UMBRELLA } from '../../channels/routing.js';
|
|
46
|
-
import { resolveProjectUuid } from '../paths.js';
|
|
47
|
-
import { agentBridgeLockPath, agentBridgePidPath, resolvePackRootFromEnv, } from './daemon.js';
|
|
48
|
-
const STALE_LOCK_AGE_MS = 15_000;
|
|
49
|
-
const PIDFILE_WAIT_MS = 8_000;
|
|
50
|
-
const POLL_INTERVAL_MS = 100;
|
|
51
|
-
/**
|
|
52
|
-
* Resolve the CLI binary (`dist/cli.js`). From the MCP server at
|
|
53
|
-
* `dist/mcp/chat-bridge-server.js` the CLI sits at `dist/cli.js`; from this
|
|
54
|
-
* module's built location (`dist/runtime/agent_bridge/autospawn.js`) it's three
|
|
55
|
-
* dirs up. We resolve relative to the MCP-server layout to match the chat
|
|
56
|
-
* daemon's `resolveCliEntrypoint`, honoring `OPENSQUID_CLI_ENTRYPOINT`.
|
|
57
|
-
*/
|
|
58
|
-
export function resolveCliEntrypoint() {
|
|
59
|
-
const override = process.env.OPENSQUID_CLI_ENTRYPOINT;
|
|
60
|
-
if (override !== undefined && override.length > 0)
|
|
61
|
-
return override;
|
|
62
|
-
const here = fileURLToPath(import.meta.url);
|
|
63
|
-
// dist/runtime/agent_bridge/autospawn.js → dist → dist/cli.js
|
|
64
|
-
return resolve(dirname(here), '..', '..', 'cli.js');
|
|
65
|
-
}
|
|
66
|
-
/** True iff at least one chat platform has a token configured. */
|
|
67
|
-
async function anyChatConfigured() {
|
|
68
|
-
const config = await loadChatConfig();
|
|
69
|
-
return (config.telegram?.bot_token !== undefined ||
|
|
70
|
-
config.discord?.bot_token !== undefined ||
|
|
71
|
-
config.slack?.bot_token !== undefined);
|
|
72
|
-
}
|
|
73
|
-
/** `kill -0 <pid>` liveness — ESRCH (dead) → false, EPERM (foreign live) → true. */
|
|
74
|
-
function isProcessAlive(pid) {
|
|
75
|
-
try {
|
|
76
|
-
process.kill(pid, 0);
|
|
77
|
-
return true;
|
|
78
|
-
}
|
|
79
|
-
catch (err) {
|
|
80
|
-
return err.code === 'EPERM';
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/** Default scoped-status probe: read `agent-bridge[-<scope>].pid` + `kill -0`. */
|
|
84
|
-
async function defaultScopedStatus(scope) {
|
|
85
|
-
let raw;
|
|
86
|
-
try {
|
|
87
|
-
raw = await fs.readFile(agentBridgePidPath(scope), 'utf8');
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
return { running: false };
|
|
91
|
-
}
|
|
92
|
-
const pid = parseInt(raw.trim(), 10);
|
|
93
|
-
if (!Number.isFinite(pid) || pid <= 0)
|
|
94
|
-
return { running: false };
|
|
95
|
-
return isProcessAlive(pid) ? { running: true, pid } : { running: false };
|
|
96
|
-
}
|
|
97
|
-
/** Default spawn: detached `node <entrypoint> <args...>` with the merged env. */
|
|
98
|
-
function defaultSpawn(entrypoint, inv) {
|
|
99
|
-
const child = spawn(process.execPath, [entrypoint, ...inv.args], {
|
|
100
|
-
detached: true,
|
|
101
|
-
stdio: 'ignore',
|
|
102
|
-
env: inv.env,
|
|
103
|
-
});
|
|
104
|
-
child.unref();
|
|
105
|
-
return child.pid !== undefined ? { pid: child.pid } : {};
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Build the detached spawn invocation for a target, or `null` to SKIP (a
|
|
109
|
-
* project umbrella whose project uuid can't be resolved). Pure given its deps.
|
|
110
|
-
*/
|
|
111
|
-
function buildInvocation(target, deps, projectUuid) {
|
|
112
|
-
if (target.kind === 'general') {
|
|
113
|
-
// General: env as-is; the worker resolves the built-in `general` pack.
|
|
114
|
-
return { args: ['agent-bridge', 'start', '--general'], env: { ...deps.env } };
|
|
115
|
-
}
|
|
116
|
-
// Project umbrella: inject the resolved project uuid + pack root so the
|
|
117
|
-
// detached `agent-bridge start` worker keys off THIS scope (matches cli.ts's
|
|
118
|
-
// non-general path). Skip when the project uuid can't be resolved.
|
|
119
|
-
if (projectUuid === null)
|
|
120
|
-
return null;
|
|
121
|
-
const packRoot = deps.resolvePackRootFn(deps.env);
|
|
122
|
-
return {
|
|
123
|
-
args: ['agent-bridge', 'start'],
|
|
124
|
-
env: {
|
|
125
|
-
...deps.env,
|
|
126
|
-
OPENSQUID_PROJECT_UUID: projectUuid,
|
|
127
|
-
OPENSQUID_PACK_ROOT: packRoot,
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
/** Scope key for a target (umbrella id is the scope identity for both kinds). */
|
|
132
|
-
function scopeForTarget(target) {
|
|
133
|
-
return target.kind === 'general'
|
|
134
|
-
? { umbrellaId: GENERAL_UMBRELLA }
|
|
135
|
-
: { umbrellaId: target.umbrellaId };
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Best-effort: ensure the headless agent-bridge responder for `target` is
|
|
139
|
-
* running. Returns on the no-op paths (no config, already running, peer
|
|
140
|
-
* spawning, unresolvable scope). NEVER throws.
|
|
141
|
-
*/
|
|
142
|
-
export async function ensureAgentBridgeRunning(target, opts = {}) {
|
|
143
|
-
const isConfigured = opts.isConfigured ?? anyChatConfigured;
|
|
144
|
-
const statusFn = opts.statusFn ?? defaultScopedStatus;
|
|
145
|
-
const spawnFn = opts.spawnFn ?? defaultSpawn;
|
|
146
|
-
const env = opts.env ?? process.env;
|
|
147
|
-
const resolveProjectUuidFn = opts.resolveProjectUuidFn ?? resolveProjectUuid;
|
|
148
|
-
const resolvePackRootFn = opts.resolvePackRootFn ?? resolvePackRootFromEnv;
|
|
149
|
-
try {
|
|
150
|
-
if (!(await isConfigured()))
|
|
151
|
-
return { status: 'no_config' };
|
|
152
|
-
const scope = scopeForTarget(target);
|
|
153
|
-
// Resolve the project uuid up-front for the umbrella path so we can SKIP
|
|
154
|
-
// (no_config) before touching any lock when it's unresolvable.
|
|
155
|
-
let projectUuid = null;
|
|
156
|
-
if (target.kind === 'umbrella') {
|
|
157
|
-
projectUuid = await resolveProjectUuidFn({ cwd: target.cwd, env });
|
|
158
|
-
if (projectUuid === null)
|
|
159
|
-
return { status: 'no_config' };
|
|
160
|
-
}
|
|
161
|
-
const cur = await statusFn(scope);
|
|
162
|
-
if (cur.running)
|
|
163
|
-
return { status: 'already_running', ...(cur.pid !== undefined ? { pid: cur.pid } : {}) };
|
|
164
|
-
const invocation = buildInvocation(target, { resolvePackRootFn, env }, projectUuid);
|
|
165
|
-
if (invocation === null)
|
|
166
|
-
return { status: 'no_config' };
|
|
167
|
-
const entrypoint = opts.entrypoint ?? resolveCliEntrypoint();
|
|
168
|
-
const lockPath = agentBridgeLockPath(scope);
|
|
169
|
-
const acquired = await tryAcquireLock(lockPath);
|
|
170
|
-
if (acquired) {
|
|
171
|
-
try {
|
|
172
|
-
const re = await statusFn(scope);
|
|
173
|
-
if (re.running) {
|
|
174
|
-
return { status: 'already_running', ...(re.pid !== undefined ? { pid: re.pid } : {}) };
|
|
175
|
-
}
|
|
176
|
-
const res = spawnFn(entrypoint, invocation);
|
|
177
|
-
return res.pid !== undefined ? { status: 'spawned', pid: res.pid } : { status: 'spawned' };
|
|
178
|
-
}
|
|
179
|
-
finally {
|
|
180
|
-
await fs.unlink(lockPath).catch(() => {
|
|
181
|
-
/* race-tolerant */
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
// Another process holds the lock — wait for its pidfile.
|
|
186
|
-
const pid = await waitForPeer(statusFn, scope);
|
|
187
|
-
if (pid !== null)
|
|
188
|
-
return { status: 'waited_for_peer', pid };
|
|
189
|
-
return { status: 'error', error: 'peer spawn timed out' };
|
|
190
|
-
}
|
|
191
|
-
catch (err) {
|
|
192
|
-
return { status: 'error', error: err instanceof Error ? err.message : String(err) };
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
async function tryAcquireLock(lockPath) {
|
|
196
|
-
await fs.mkdir(dirname(lockPath), { recursive: true });
|
|
197
|
-
try {
|
|
198
|
-
const fd = await fs.open(lockPath, 'wx');
|
|
199
|
-
await fd.write(`${process.pid}\n`);
|
|
200
|
-
await fd.close();
|
|
201
|
-
return true;
|
|
202
|
-
}
|
|
203
|
-
catch (err) {
|
|
204
|
-
if (err.code !== 'EEXIST')
|
|
205
|
-
throw err;
|
|
206
|
-
try {
|
|
207
|
-
const st = await fs.stat(lockPath);
|
|
208
|
-
if (Date.now() - st.mtimeMs > STALE_LOCK_AGE_MS) {
|
|
209
|
-
await fs.unlink(lockPath).catch(() => {
|
|
210
|
-
/* race */
|
|
211
|
-
});
|
|
212
|
-
return tryAcquireLock(lockPath);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
catch {
|
|
216
|
-
return tryAcquireLock(lockPath);
|
|
217
|
-
}
|
|
218
|
-
return false;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
async function waitForPeer(statusFn, scope) {
|
|
222
|
-
const deadline = Date.now() + PIDFILE_WAIT_MS;
|
|
223
|
-
while (Date.now() < deadline) {
|
|
224
|
-
const s = await statusFn(scope);
|
|
225
|
-
if (s.running)
|
|
226
|
-
return s.pid ?? -1;
|
|
227
|
-
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
228
|
-
}
|
|
229
|
-
return null;
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* MCP-boot convenience (CAT.5.1): ensure (a) the GENERAL headless responder
|
|
233
|
-
* (always) and (b) the headless responder for the umbrella the cwd resolves to
|
|
234
|
-
* (if any). Each is fire-and-forget at the call site; this helper awaits both
|
|
235
|
-
* and returns their results for logging. Never throws.
|
|
236
|
-
*
|
|
237
|
-
* `cwd` defaults to `CLAUDE_PROJECT_DIR ?? process.cwd()` (matches the MCP
|
|
238
|
-
* server's active-umbrella resolution). `umbrellaForCwd` lets the caller pass
|
|
239
|
-
* the already-resolved umbrella (the MCP boot resolves it once for logging).
|
|
240
|
-
*/
|
|
241
|
-
export async function ensureHeadlessRespondersForBoot(opts) {
|
|
242
|
-
const ensureFn = opts.ensureFn ?? ensureAgentBridgeRunning;
|
|
243
|
-
const cwd = opts.cwd ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
244
|
-
const general = await ensureFn({ kind: 'general' }, opts.deps);
|
|
245
|
-
let umbrella = null;
|
|
246
|
-
if (opts.umbrellaForCwd !== null && opts.umbrellaForCwd !== GENERAL_UMBRELLA) {
|
|
247
|
-
umbrella = await ensureFn({ kind: 'umbrella', umbrellaId: opts.umbrellaForCwd, cwd }, opts.deps);
|
|
248
|
-
}
|
|
249
|
-
return { general, umbrella };
|
|
250
|
-
}
|
|
251
|
-
//# sourceMappingURL=autospawn.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"autospawn.js","sourceRoot":"","sources":["../../../src/runtime/agent_bridge/autospawn.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-session auto-start chain state machine (T-ASC, ASC.1).
|
|
3
|
-
*
|
|
4
|
-
* Tracks the user-locked pipeline scope-decomposer → task-spec-author →
|
|
5
|
-
* workflow / 7-layer across a single Claude Code session. The state is the
|
|
6
|
-
* substrate ASC.2's `Skill.requires: chain_stage` precondition reads, and the
|
|
7
|
-
* data source ASC.5's reframed scope-decomposer handoff rules consume to
|
|
8
|
-
* shape their structured `directive` verdicts (ASC.3).
|
|
9
|
-
*
|
|
10
|
-
* 7 stages (declaration order = pipeline order):
|
|
11
|
-
* idle — no scope work in flight (initial)
|
|
12
|
-
* scoping — scope-authoring intent detected on the most recent
|
|
13
|
-
* prompt (the SCOPE_INTENT_REGEX matched while idle)
|
|
14
|
-
* researched — a pre-research artifact landed on disk
|
|
15
|
-
* (docs/research/*-pre-research-*.md)
|
|
16
|
-
* spec_authored — a track spec landed on disk
|
|
17
|
-
* (docs/tasks/T-*.md)
|
|
18
|
-
* tasks_loaded — harness TaskCreate fired with metadata.taskId
|
|
19
|
-
* provenance (the spec became loaded tasks)
|
|
20
|
-
* phases_in_flight — at least one phase logged for the active task
|
|
21
|
-
* phases_complete — all 7 REQUIRED phases logged for the active task
|
|
22
|
-
*
|
|
23
|
-
* Writers (5 distributed transition points across the runtime):
|
|
24
|
-
* UserPromptSubmit → 'scoping' (prompt matches SCOPE_INTENT_REGEX
|
|
25
|
-
* AND current stage is 'idle')
|
|
26
|
-
* PreToolUse → 'researched' (Write to docs/research/*-pre-research-*.md)
|
|
27
|
-
* PreToolUse → 'spec_authored' (Write to docs/tasks/T-*.md)
|
|
28
|
-
* PreToolUse → 'tasks_loaded' (TaskCreate/TaskUpdate with metadata.taskId)
|
|
29
|
-
* log_phase MCP → 'phases_in_flight' / 'phases_complete'
|
|
30
|
-
*
|
|
31
|
-
* Lifecycle: session-scoped per T-ASC L3. SessionEnd hook calls
|
|
32
|
-
* `clearChainState`. Cross-session resume is OUT OF SCOPE for this track
|
|
33
|
-
* (separate product question).
|
|
34
|
-
*
|
|
35
|
-
* Invariants:
|
|
36
|
-
* - Same-stage write is idempotent (no double-history-entry, no file rewrite).
|
|
37
|
-
* The `history` is append-only and entries are NEVER removed mid-session
|
|
38
|
-
* (per L4); history captures stage ENTRIES, not write attempts.
|
|
39
|
-
* - No-throw read posture: absent / malformed → null; the caller defaults
|
|
40
|
-
* to 'idle' via `readChainStage`'s nullish coalesce. Same eventual-
|
|
41
|
-
* consistency model as session_state.ts:108-135 (recordSessionCwd).
|
|
42
|
-
* - Enrichment fields (pre_research_path, spec_path, task_ids) ACCUMULATE
|
|
43
|
-
* across transitions: a transition without enrich preserves prior values.
|
|
44
|
-
* A same-stage idempotent call does NOT update enrichment (L4 contract —
|
|
45
|
-
* same stage = no write at all). If a future need surfaces ("update
|
|
46
|
-
* enrichment on current stage"), add a sibling enrichChainState helper;
|
|
47
|
-
* do NOT loosen transitionChainStage's idempotency.
|
|
48
|
-
* - Write failures throw (caller-owned recovery). Call sites in hooks /
|
|
49
|
-
* log_phase wrap in try/catch with stderr-warn or silent (their existing
|
|
50
|
-
* best-effort discipline).
|
|
51
|
-
*
|
|
52
|
-
* Imports from: node:fs/promises, node:path, ./paths.js.
|
|
53
|
-
* Imported by:
|
|
54
|
-
* - src/runtime/hooks/{pre-tool-use,user-prompt-submit,session-end}.ts (writers)
|
|
55
|
-
* - src/mcp/tools/log_phase.ts (writer)
|
|
56
|
-
* - src/runtime/skill_requires.ts (ASC.2 — `chain_stage` precondition reader)
|
|
57
|
-
* - src/functions/chain_state.ts (ASC.5 — `read_chain_state` primitive)
|
|
58
|
-
*/
|
|
59
|
-
/** The 7 stages, in pipeline order. `as const` so ChainStage narrows to the literal union. */
|
|
60
|
-
export declare const CHAIN_STAGES: readonly ["idle", "scoping", "researched", "spec_authored", "tasks_loaded", "phases_in_flight", "phases_complete"];
|
|
61
|
-
export type ChainStage = (typeof CHAIN_STAGES)[number];
|
|
62
|
-
export interface ChainHistoryEntry {
|
|
63
|
-
stage: ChainStage;
|
|
64
|
-
/** ISO-8601 timestamp the chain ENTERED this stage. */
|
|
65
|
-
at: string;
|
|
66
|
-
}
|
|
67
|
-
export interface ChainState {
|
|
68
|
-
stage: ChainStage;
|
|
69
|
-
/** ISO timestamp the chain entered the CURRENT stage. */
|
|
70
|
-
started_at: string;
|
|
71
|
-
/** ISO timestamp of the most-recent transition write (same as started_at after a fresh transition). */
|
|
72
|
-
last_transition_at: string;
|
|
73
|
-
/** Absolute path to the pre-research artifact; set when transitioning to 'researched'. */
|
|
74
|
-
pre_research_path?: string;
|
|
75
|
-
/** Absolute path to the track spec; set when transitioning to 'spec_authored'. */
|
|
76
|
-
spec_path?: string;
|
|
77
|
-
/** Harness task ids that loaded from the spec; set when transitioning to 'tasks_loaded'. */
|
|
78
|
-
task_ids?: string[];
|
|
79
|
-
/** Append-only audit trail of every stage entered. */
|
|
80
|
-
history: ChainHistoryEntry[];
|
|
81
|
-
}
|
|
82
|
-
/** Optional enrichment supplied on transition; merges into ChainState (only when the stage actually transitions). */
|
|
83
|
-
export interface ChainEnrich {
|
|
84
|
-
pre_research_path?: string;
|
|
85
|
-
spec_path?: string;
|
|
86
|
-
task_ids?: string[];
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Write a stage transition. Idempotent on same-stage re-write: when the
|
|
90
|
-
* persisted stage already equals `next`, this is a no-op (history unchanged,
|
|
91
|
-
* enrichment NOT applied — L4 contract: same stage = no write).
|
|
92
|
-
*
|
|
93
|
-
* Enrichment fields ACCUMULATE on actual transitions: a transition without
|
|
94
|
-
* an explicit enrich value preserves whatever was in the prior state for that
|
|
95
|
-
* field. Supplying enrich for a stage we're already in is silently dropped
|
|
96
|
-
* (the function returns early). If a caller needs to update enrichment on
|
|
97
|
-
* the current stage, that's a separate concern (out of scope for ASC.1).
|
|
98
|
-
*
|
|
99
|
-
* Fail-open is caller-side: write failures throw, hook bins wrap with
|
|
100
|
-
* try/catch + stderr-warn, the log_phase MCP tool wraps silently (the tool's
|
|
101
|
-
* return shape is the gate's contract and a chain-state-write failure must
|
|
102
|
-
* NOT propagate into the tool response).
|
|
103
|
-
*/
|
|
104
|
-
export declare function transitionChainStage(sessionId: string, next: ChainStage, enrich?: ChainEnrich): Promise<void>;
|
|
105
|
-
/**
|
|
106
|
-
* Read the persisted ChainState, or `null` if absent/unreadable/malformed.
|
|
107
|
-
* Same no-throw posture as readSessionCwd / readActiveTask: a missing or
|
|
108
|
-
* shape-invalid file reads as null inside a hook bin, never an exception.
|
|
109
|
-
*/
|
|
110
|
-
export declare function readChainState(sessionId: string): Promise<ChainState | null>;
|
|
111
|
-
/**
|
|
112
|
-
* Read just the current stage; defaults to 'idle' when the chain has not yet
|
|
113
|
-
* been initialized (absent file) or when the persisted state is malformed.
|
|
114
|
-
* The convenience reader for callers that only care about the stage gate
|
|
115
|
-
* (ASC.2's `Skill.requires: chain_stage` precondition, ASC.5's rule guards).
|
|
116
|
-
*/
|
|
117
|
-
export declare function readChainStage(sessionId: string): Promise<ChainStage>;
|
|
118
|
-
/**
|
|
119
|
-
* Remove the chain-state file (SessionEnd cleanup). ENOENT is swallowed —
|
|
120
|
-
* a session that never advanced past 'idle' has no file to clear. Any other
|
|
121
|
-
* error throws (caller wraps with best-effort discipline).
|
|
122
|
-
*/
|
|
123
|
-
export declare function clearChainState(sessionId: string): Promise<void>;
|
|
124
|
-
//# sourceMappingURL=chain_state.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chain_state.d.ts","sourceRoot":"","sources":["../../src/runtime/chain_state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAMH,8FAA8F;AAC9F,eAAO,MAAM,YAAY,oHAQf,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAKvD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,UAAU,CAAC;IAClB,uDAAuD;IACvD,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,uGAAuG;IACvG,kBAAkB,EAAE,MAAM,CAAC;IAC3B,0FAA0F;IAC1F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,sDAAsD;IACtD,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,qHAAqH;AACrH,MAAM,WAAW,WAAW;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAkBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAyCf;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAQlF;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAE3E;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtE"}
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-session auto-start chain state machine (T-ASC, ASC.1).
|
|
3
|
-
*
|
|
4
|
-
* Tracks the user-locked pipeline scope-decomposer → task-spec-author →
|
|
5
|
-
* workflow / 7-layer across a single Claude Code session. The state is the
|
|
6
|
-
* substrate ASC.2's `Skill.requires: chain_stage` precondition reads, and the
|
|
7
|
-
* data source ASC.5's reframed scope-decomposer handoff rules consume to
|
|
8
|
-
* shape their structured `directive` verdicts (ASC.3).
|
|
9
|
-
*
|
|
10
|
-
* 7 stages (declaration order = pipeline order):
|
|
11
|
-
* idle — no scope work in flight (initial)
|
|
12
|
-
* scoping — scope-authoring intent detected on the most recent
|
|
13
|
-
* prompt (the SCOPE_INTENT_REGEX matched while idle)
|
|
14
|
-
* researched — a pre-research artifact landed on disk
|
|
15
|
-
* (docs/research/*-pre-research-*.md)
|
|
16
|
-
* spec_authored — a track spec landed on disk
|
|
17
|
-
* (docs/tasks/T-*.md)
|
|
18
|
-
* tasks_loaded — harness TaskCreate fired with metadata.taskId
|
|
19
|
-
* provenance (the spec became loaded tasks)
|
|
20
|
-
* phases_in_flight — at least one phase logged for the active task
|
|
21
|
-
* phases_complete — all 7 REQUIRED phases logged for the active task
|
|
22
|
-
*
|
|
23
|
-
* Writers (5 distributed transition points across the runtime):
|
|
24
|
-
* UserPromptSubmit → 'scoping' (prompt matches SCOPE_INTENT_REGEX
|
|
25
|
-
* AND current stage is 'idle')
|
|
26
|
-
* PreToolUse → 'researched' (Write to docs/research/*-pre-research-*.md)
|
|
27
|
-
* PreToolUse → 'spec_authored' (Write to docs/tasks/T-*.md)
|
|
28
|
-
* PreToolUse → 'tasks_loaded' (TaskCreate/TaskUpdate with metadata.taskId)
|
|
29
|
-
* log_phase MCP → 'phases_in_flight' / 'phases_complete'
|
|
30
|
-
*
|
|
31
|
-
* Lifecycle: session-scoped per T-ASC L3. SessionEnd hook calls
|
|
32
|
-
* `clearChainState`. Cross-session resume is OUT OF SCOPE for this track
|
|
33
|
-
* (separate product question).
|
|
34
|
-
*
|
|
35
|
-
* Invariants:
|
|
36
|
-
* - Same-stage write is idempotent (no double-history-entry, no file rewrite).
|
|
37
|
-
* The `history` is append-only and entries are NEVER removed mid-session
|
|
38
|
-
* (per L4); history captures stage ENTRIES, not write attempts.
|
|
39
|
-
* - No-throw read posture: absent / malformed → null; the caller defaults
|
|
40
|
-
* to 'idle' via `readChainStage`'s nullish coalesce. Same eventual-
|
|
41
|
-
* consistency model as session_state.ts:108-135 (recordSessionCwd).
|
|
42
|
-
* - Enrichment fields (pre_research_path, spec_path, task_ids) ACCUMULATE
|
|
43
|
-
* across transitions: a transition without enrich preserves prior values.
|
|
44
|
-
* A same-stage idempotent call does NOT update enrichment (L4 contract —
|
|
45
|
-
* same stage = no write at all). If a future need surfaces ("update
|
|
46
|
-
* enrichment on current stage"), add a sibling enrichChainState helper;
|
|
47
|
-
* do NOT loosen transitionChainStage's idempotency.
|
|
48
|
-
* - Write failures throw (caller-owned recovery). Call sites in hooks /
|
|
49
|
-
* log_phase wrap in try/catch with stderr-warn or silent (their existing
|
|
50
|
-
* best-effort discipline).
|
|
51
|
-
*
|
|
52
|
-
* Imports from: node:fs/promises, node:path, ./paths.js.
|
|
53
|
-
* Imported by:
|
|
54
|
-
* - src/runtime/hooks/{pre-tool-use,user-prompt-submit,session-end}.ts (writers)
|
|
55
|
-
* - src/mcp/tools/log_phase.ts (writer)
|
|
56
|
-
* - src/runtime/skill_requires.ts (ASC.2 — `chain_stage` precondition reader)
|
|
57
|
-
* - src/functions/chain_state.ts (ASC.5 — `read_chain_state` primitive)
|
|
58
|
-
*/
|
|
59
|
-
import { readFile, unlink } from 'node:fs/promises';
|
|
60
|
-
import { atomicWriteFile } from './atomic_write.js';
|
|
61
|
-
import { sessionStateFile } from './paths.js';
|
|
62
|
-
/** The 7 stages, in pipeline order. `as const` so ChainStage narrows to the literal union. */
|
|
63
|
-
export const CHAIN_STAGES = [
|
|
64
|
-
'idle',
|
|
65
|
-
'scoping',
|
|
66
|
-
'researched',
|
|
67
|
-
'spec_authored',
|
|
68
|
-
'tasks_loaded',
|
|
69
|
-
'phases_in_flight',
|
|
70
|
-
'phases_complete',
|
|
71
|
-
];
|
|
72
|
-
/** Well-known session-state key for the chain-state file. */
|
|
73
|
-
const CHAIN_STATE_KEY = 'chain-state';
|
|
74
|
-
/**
|
|
75
|
-
* Runtime type guard for the persisted shape. Validates every required field
|
|
76
|
-
* + stage-membership; the unknown-shape branches return false so the read
|
|
77
|
-
* helpers default to null (no-throw posture).
|
|
78
|
-
*/
|
|
79
|
-
function isChainState(o) {
|
|
80
|
-
if (o === null || typeof o !== 'object')
|
|
81
|
-
return false;
|
|
82
|
-
const obj = o;
|
|
83
|
-
if (typeof obj.stage !== 'string')
|
|
84
|
-
return false;
|
|
85
|
-
if (!CHAIN_STAGES.includes(obj.stage))
|
|
86
|
-
return false;
|
|
87
|
-
if (typeof obj.started_at !== 'string')
|
|
88
|
-
return false;
|
|
89
|
-
if (typeof obj.last_transition_at !== 'string')
|
|
90
|
-
return false;
|
|
91
|
-
if (!Array.isArray(obj.history))
|
|
92
|
-
return false;
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Write a stage transition. Idempotent on same-stage re-write: when the
|
|
97
|
-
* persisted stage already equals `next`, this is a no-op (history unchanged,
|
|
98
|
-
* enrichment NOT applied — L4 contract: same stage = no write).
|
|
99
|
-
*
|
|
100
|
-
* Enrichment fields ACCUMULATE on actual transitions: a transition without
|
|
101
|
-
* an explicit enrich value preserves whatever was in the prior state for that
|
|
102
|
-
* field. Supplying enrich for a stage we're already in is silently dropped
|
|
103
|
-
* (the function returns early). If a caller needs to update enrichment on
|
|
104
|
-
* the current stage, that's a separate concern (out of scope for ASC.1).
|
|
105
|
-
*
|
|
106
|
-
* Fail-open is caller-side: write failures throw, hook bins wrap with
|
|
107
|
-
* try/catch + stderr-warn, the log_phase MCP tool wraps silently (the tool's
|
|
108
|
-
* return shape is the gate's contract and a chain-state-write failure must
|
|
109
|
-
* NOT propagate into the tool response).
|
|
110
|
-
*/
|
|
111
|
-
export async function transitionChainStage(sessionId, next, enrich) {
|
|
112
|
-
const path = sessionStateFile(sessionId, CHAIN_STATE_KEY);
|
|
113
|
-
const now = new Date().toISOString();
|
|
114
|
-
const current = await readChainState(sessionId);
|
|
115
|
-
if (current?.stage === next)
|
|
116
|
-
return; // L4 idempotency: same stage = no-op
|
|
117
|
-
// T-PACK-FSM-STANDARDIZATION slice A4 — legality. The workflow pipeline is
|
|
118
|
-
// FORWARD-ONLY (CHAIN_STAGES order); forward JUMPS are allowed by design
|
|
119
|
-
// (e.g. a spec write lands `spec_authored` without an intervening prompt),
|
|
120
|
-
// but a BACKWARD transition was silently accepted before — the exact "accepts
|
|
121
|
-
// any target, no legality matrix" gap the generic FSM engine closes. Reject
|
|
122
|
-
// it: no-op + warn, so an illegal regress can't quietly rewind a gate. (The
|
|
123
|
-
// legitimate research loop-back lives in the `scope-fsm` pack's FSM, not this
|
|
124
|
-
// global one-shot chain.)
|
|
125
|
-
const curIdx = current ? CHAIN_STAGES.indexOf(current.stage) : -1;
|
|
126
|
-
const nextIdx = CHAIN_STAGES.indexOf(next);
|
|
127
|
-
if (nextIdx < curIdx) {
|
|
128
|
-
process.stderr.write(`opensquid: illegal backward chain transition ${current?.stage ?? 'idle'} -> ${next} ignored (forward-only)\n`);
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const merged = {
|
|
132
|
-
stage: next,
|
|
133
|
-
started_at: now,
|
|
134
|
-
last_transition_at: now,
|
|
135
|
-
...(current?.pre_research_path !== undefined
|
|
136
|
-
? { pre_research_path: current.pre_research_path }
|
|
137
|
-
: {}),
|
|
138
|
-
...(current?.spec_path !== undefined ? { spec_path: current.spec_path } : {}),
|
|
139
|
-
...(current?.task_ids !== undefined ? { task_ids: current.task_ids } : {}),
|
|
140
|
-
...(enrich?.pre_research_path !== undefined
|
|
141
|
-
? { pre_research_path: enrich.pre_research_path }
|
|
142
|
-
: {}),
|
|
143
|
-
...(enrich?.spec_path !== undefined ? { spec_path: enrich.spec_path } : {}),
|
|
144
|
-
...(enrich?.task_ids !== undefined ? { task_ids: enrich.task_ids } : {}),
|
|
145
|
-
history: [...(current?.history ?? []), { stage: next, at: now }],
|
|
146
|
-
};
|
|
147
|
-
// FC.1: atomic publish so concurrent transitions can't tear/lose the stage —
|
|
148
|
-
// the stage the gates read is always the last fully-committed one.
|
|
149
|
-
await atomicWriteFile(path, JSON.stringify(merged, null, 2));
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Read the persisted ChainState, or `null` if absent/unreadable/malformed.
|
|
153
|
-
* Same no-throw posture as readSessionCwd / readActiveTask: a missing or
|
|
154
|
-
* shape-invalid file reads as null inside a hook bin, never an exception.
|
|
155
|
-
*/
|
|
156
|
-
export async function readChainState(sessionId) {
|
|
157
|
-
try {
|
|
158
|
-
const raw = await readFile(sessionStateFile(sessionId, CHAIN_STATE_KEY), 'utf8');
|
|
159
|
-
const parsed = JSON.parse(raw);
|
|
160
|
-
return isChainState(parsed) ? parsed : null;
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
return null;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Read just the current stage; defaults to 'idle' when the chain has not yet
|
|
168
|
-
* been initialized (absent file) or when the persisted state is malformed.
|
|
169
|
-
* The convenience reader for callers that only care about the stage gate
|
|
170
|
-
* (ASC.2's `Skill.requires: chain_stage` precondition, ASC.5's rule guards).
|
|
171
|
-
*/
|
|
172
|
-
export async function readChainStage(sessionId) {
|
|
173
|
-
return (await readChainState(sessionId))?.stage ?? 'idle';
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Remove the chain-state file (SessionEnd cleanup). ENOENT is swallowed —
|
|
177
|
-
* a session that never advanced past 'idle' has no file to clear. Any other
|
|
178
|
-
* error throws (caller wraps with best-effort discipline).
|
|
179
|
-
*/
|
|
180
|
-
export async function clearChainState(sessionId) {
|
|
181
|
-
try {
|
|
182
|
-
await unlink(sessionStateFile(sessionId, CHAIN_STATE_KEY));
|
|
183
|
-
}
|
|
184
|
-
catch (e) {
|
|
185
|
-
if (e.code !== 'ENOENT')
|
|
186
|
-
throw e;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
//# sourceMappingURL=chain_state.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chain_state.js","sourceRoot":"","sources":["../../src/runtime/chain_state.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PreToolUse permission-decision envelope (T-RJ-FOLLOWUPS FU.11).
|
|
3
|
-
*
|
|
4
|
-
* A PreToolUse hook signals a block in one of two ways:
|
|
5
|
-
* - `exit 2` — the simple path, BUT `--dangerously-skip-permissions`
|
|
6
|
-
* (= `bypassPermissions` mode) silently IGNORES it (proven live: a
|
|
7
|
-
* `git commit` the gate should block ran anyway).
|
|
8
|
-
* - a `permissionDecision: "deny"` JSON envelope on stdout (exit 0) — HONORED
|
|
9
|
-
* even under `bypassPermissions` (proven live: the call was denied).
|
|
10
|
-
*
|
|
11
|
-
* So opensquid emits the JSON envelope on every block, making drift gates
|
|
12
|
-
* enforce in BOTH normal and bypass permission modes. Pure builder so the shape
|
|
13
|
-
* is unit-testable without spawning the hook bin.
|
|
14
|
-
*/
|
|
15
|
-
export interface PreToolUseDeny {
|
|
16
|
-
hookSpecificOutput: {
|
|
17
|
-
hookEventName: 'PreToolUse';
|
|
18
|
-
permissionDecision: 'deny';
|
|
19
|
-
permissionDecisionReason: string;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Every drift/block message opensquid emits to the user carries a leading 🦑 so
|
|
24
|
-
* it's unmistakably opensquid speaking — NOT the agent's own prose, NOT a chat
|
|
25
|
-
* message (chat replies via chat_send are deliberately unprefixed). Added HERE at
|
|
26
|
-
* the hook EMIT boundary (not in the dispatcher/verdict layer) so skill YAML
|
|
27
|
-
* `message:` fields stay clean and the dispatch internals stay emoji-free.
|
|
28
|
-
* Idempotent; empty string passes through untouched (nothing to surface).
|
|
29
|
-
*/
|
|
30
|
-
export declare const SQUID = "\uD83E\uDD91";
|
|
31
|
-
export declare function squidPrefix(message: string): string;
|
|
32
|
-
/** Build the deny envelope; falls back to a generic reason when none is given. */
|
|
33
|
-
export declare function buildPreToolUseDeny(reason: string): PreToolUseDeny;
|
|
34
|
-
//# sourceMappingURL=permission_decision.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"permission_decision.d.ts","sourceRoot":"","sources":["../../../src/runtime/hooks/permission_decision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,cAAc;IAC7B,kBAAkB,EAAE;QAClB,aAAa,EAAE,YAAY,CAAC;QAC5B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,wBAAwB,EAAE,MAAM,CAAC;KAClC,CAAC;CACH;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,iBAAO,CAAC;AAC1B,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAUlE"}
|