harnery 0.0.1 → 0.2.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/LICENSE +21 -0
- package/README.md +84 -2
- package/bin/agent-coord +42 -0
- package/bin/agent-hook +44 -0
- package/bin/harn +40 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +18 -0
- package/dist/commander.d.ts +128 -0
- package/dist/commander.d.ts.map +1 -0
- package/dist/commander.js +126 -0
- package/dist/commands/agents.d.ts +18 -0
- package/dist/commands/agents.d.ts.map +1 -0
- package/dist/commands/agents.js +3946 -0
- package/dist/commands/backup.d.ts +22 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +262 -0
- package/dist/commands/browse-ai.d.ts +4 -0
- package/dist/commands/browse-ai.d.ts.map +1 -0
- package/dist/commands/browse-ai.js +156 -0
- package/dist/commands/browse.d.ts +4 -0
- package/dist/commands/browse.d.ts.map +1 -0
- package/dist/commands/browse.js +590 -0
- package/dist/commands/callers.d.ts +4 -0
- package/dist/commands/callers.d.ts.map +1 -0
- package/dist/commands/callers.js +276 -0
- package/dist/commands/completion.d.ts +17 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +158 -0
- package/dist/commands/config-get.d.ts +4 -0
- package/dist/commands/config-get.d.ts.map +1 -0
- package/dist/commands/config-get.js +131 -0
- package/dist/commands/context.d.ts +11 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +185 -0
- package/dist/commands/cookies.d.ts +4 -0
- package/dist/commands/cookies.d.ts.map +1 -0
- package/dist/commands/cookies.js +140 -0
- package/dist/commands/docs.d.ts +4 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +137 -0
- package/dist/commands/doctor.d.ts +25 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +200 -0
- package/dist/commands/edit-batch.d.ts +18 -0
- package/dist/commands/edit-batch.d.ts.map +1 -0
- package/dist/commands/edit-batch.js +172 -0
- package/dist/commands/eml.d.ts +4 -0
- package/dist/commands/eml.d.ts.map +1 -0
- package/dist/commands/eml.js +428 -0
- package/dist/commands/env.d.ts +4 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +201 -0
- package/dist/commands/fetch.d.ts +4 -0
- package/dist/commands/fetch.d.ts.map +1 -0
- package/dist/commands/fetch.js +99 -0
- package/dist/commands/file-history.d.ts +4 -0
- package/dist/commands/file-history.d.ts.map +1 -0
- package/dist/commands/file-history.js +152 -0
- package/dist/commands/grep.d.ts +4 -0
- package/dist/commands/grep.d.ts.map +1 -0
- package/dist/commands/grep.js +317 -0
- package/dist/commands/init.d.ts +82 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +288 -0
- package/dist/commands/outline.d.ts +4 -0
- package/dist/commands/outline.d.ts.map +1 -0
- package/dist/commands/outline.js +494 -0
- package/dist/commands/presence.d.ts +12 -0
- package/dist/commands/presence.d.ts.map +1 -0
- package/dist/commands/presence.js +123 -0
- package/dist/commands/read.d.ts +7 -0
- package/dist/commands/read.d.ts.map +1 -0
- package/dist/commands/read.js +46 -0
- package/dist/commands/scratch.d.ts +4 -0
- package/dist/commands/scratch.d.ts.map +1 -0
- package/dist/commands/scratch.js +426 -0
- package/dist/commands/session.d.ts +4 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +162 -0
- package/dist/commands/sync.d.ts +24 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +275 -0
- package/dist/commands/toc.d.ts +5 -0
- package/dist/commands/toc.d.ts.map +1 -0
- package/dist/commands/toc.js +153 -0
- package/dist/commands/tokens.d.ts +4 -0
- package/dist/commands/tokens.d.ts.map +1 -0
- package/dist/commands/tokens.js +48 -0
- package/dist/commands/tunnel.d.ts +4 -0
- package/dist/commands/tunnel.d.ts.map +1 -0
- package/dist/commands/tunnel.js +513 -0
- package/dist/commands/uninstall.d.ts +22 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +126 -0
- package/dist/commands/web.d.ts +4 -0
- package/dist/commands/web.d.ts.map +1 -0
- package/dist/commands/web.js +165 -0
- package/dist/core/agents/canonical-emit.d.ts +27 -0
- package/dist/core/agents/canonical-emit.d.ts.map +1 -0
- package/dist/core/agents/canonical-emit.js +72 -0
- package/dist/core/agents/cli-emit.d.ts +27 -0
- package/dist/core/agents/cli-emit.d.ts.map +1 -0
- package/dist/core/agents/cli-emit.js +57 -0
- package/dist/core/agents/cli.d.ts +10 -0
- package/dist/core/agents/cli.d.ts.map +1 -0
- package/dist/core/agents/cli.js +757 -0
- package/dist/core/agents/codex-replay.d.ts +29 -0
- package/dist/core/agents/codex-replay.d.ts.map +1 -0
- package/dist/core/agents/codex-replay.js +138 -0
- package/dist/core/agents/coord-client.d.ts +98 -0
- package/dist/core/agents/coord-client.d.ts.map +1 -0
- package/dist/core/agents/coord-client.js +212 -0
- package/dist/core/agents/events/consume.d.ts +59 -0
- package/dist/core/agents/events/consume.d.ts.map +1 -0
- package/dist/core/agents/events/consume.js +147 -0
- package/dist/core/agents/events/emit.d.ts +42 -0
- package/dist/core/agents/events/emit.d.ts.map +1 -0
- package/dist/core/agents/events/emit.js +70 -0
- package/dist/core/agents/events/ulid.d.ts +11 -0
- package/dist/core/agents/events/ulid.d.ts.map +1 -0
- package/dist/core/agents/events/ulid.js +47 -0
- package/dist/core/agents/index.d.ts +14 -0
- package/dist/core/agents/index.d.ts.map +1 -0
- package/dist/core/agents/index.js +13 -0
- package/dist/core/agents/paths.d.ts +6 -0
- package/dist/core/agents/paths.d.ts.map +1 -0
- package/dist/core/agents/paths.js +17 -0
- package/dist/core/agents/render/prompt-context.d.ts +43 -0
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -0
- package/dist/core/agents/render/prompt-context.js +335 -0
- package/dist/core/agents/render/session-context.d.ts +39 -0
- package/dist/core/agents/render/session-context.d.ts.map +1 -0
- package/dist/core/agents/render/session-context.js +283 -0
- package/dist/core/agents/rules/claim-conflict.d.ts +35 -0
- package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -0
- package/dist/core/agents/rules/claim-conflict.js +244 -0
- package/dist/core/agents/rules/commit-conflict.d.ts +59 -0
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -0
- package/dist/core/agents/rules/commit-conflict.js +244 -0
- package/dist/core/agents/rules/stop-hook.d.ts +44 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -0
- package/dist/core/agents/rules/stop-hook.js +161 -0
- package/dist/core/agents/session-events.d.ts +41 -0
- package/dist/core/agents/session-events.d.ts.map +1 -0
- package/dist/core/agents/session-events.js +205 -0
- package/dist/core/agents/state/activity-log.d.ts +18 -0
- package/dist/core/agents/state/activity-log.d.ts.map +1 -0
- package/dist/core/agents/state/activity-log.js +34 -0
- package/dist/core/agents/state/council.d.ts +39 -0
- package/dist/core/agents/state/council.d.ts.map +1 -0
- package/dist/core/agents/state/council.js +216 -0
- package/dist/core/agents/state/heartbeat-projector.d.ts +59 -0
- package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -0
- package/dist/core/agents/state/heartbeat-projector.js +436 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts +64 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -0
- package/dist/core/agents/state/heartbeat-writer.js +271 -0
- package/dist/core/agents/state/names.d.ts +35 -0
- package/dist/core/agents/state/names.d.ts.map +1 -0
- package/dist/core/agents/state/names.js +376 -0
- package/dist/core/agents/state/pidmap.d.ts +11 -0
- package/dist/core/agents/state/pidmap.d.ts.map +1 -0
- package/dist/core/agents/state/pidmap.js +32 -0
- package/dist/core/agents/state/scratch.d.ts +27 -0
- package/dist/core/agents/state/scratch.d.ts.map +1 -0
- package/dist/core/agents/state/scratch.js +90 -0
- package/dist/core/agents/state/shell-mutation.d.ts +17 -0
- package/dist/core/agents/state/shell-mutation.d.ts.map +1 -0
- package/dist/core/agents/state/shell-mutation.js +41 -0
- package/dist/core/agents/state/stale-sweep.d.ts +16 -0
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -0
- package/dist/core/agents/state/stale-sweep.js +166 -0
- package/dist/core/config.d.ts +29 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +108 -0
- package/dist/core/hooks/cli.d.ts +21 -0
- package/dist/core/hooks/cli.d.ts.map +1 -0
- package/dist/core/hooks/cli.js +1123 -0
- package/dist/core/hooks/effects/image-capture.d.ts +43 -0
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -0
- package/dist/core/hooks/effects/image-capture.js +288 -0
- package/dist/core/hooks/effects/index.d.ts +64 -0
- package/dist/core/hooks/effects/index.d.ts.map +1 -0
- package/dist/core/hooks/effects/index.js +197 -0
- package/dist/core/hooks/events/emit.d.ts +31 -0
- package/dist/core/hooks/events/emit.d.ts.map +1 -0
- package/dist/core/hooks/events/emit.js +89 -0
- package/dist/core/hooks/events/schema.d.ts +235 -0
- package/dist/core/hooks/events/schema.d.ts.map +1 -0
- package/dist/core/hooks/events/schema.js +12 -0
- package/dist/core/hooks/events/ulid.d.ts +10 -0
- package/dist/core/hooks/events/ulid.d.ts.map +1 -0
- package/dist/core/hooks/events/ulid.js +47 -0
- package/dist/core/hooks/harness/detect.d.ts +9 -0
- package/dist/core/hooks/harness/detect.d.ts.map +1 -0
- package/dist/core/hooks/harness/detect.js +29 -0
- package/dist/core/hooks/harness/events.d.ts +45 -0
- package/dist/core/hooks/harness/events.d.ts.map +1 -0
- package/dist/core/hooks/harness/events.js +71 -0
- package/dist/core/hooks/harness/output.d.ts +46 -0
- package/dist/core/hooks/harness/output.d.ts.map +1 -0
- package/dist/core/hooks/harness/output.js +87 -0
- package/dist/core/hooks/harness/parse.d.ts +67 -0
- package/dist/core/hooks/harness/parse.d.ts.map +1 -0
- package/dist/core/hooks/harness/parse.js +132 -0
- package/dist/core/hooks/index.d.ts +8 -0
- package/dist/core/hooks/index.d.ts.map +1 -0
- package/dist/core/hooks/index.js +7 -0
- package/dist/core/hooks/resolve/anchor.d.ts +37 -0
- package/dist/core/hooks/resolve/anchor.d.ts.map +1 -0
- package/dist/core/hooks/resolve/anchor.js +48 -0
- package/dist/core/hooks/resolve/coord-root.d.ts +6 -0
- package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -0
- package/dist/core/hooks/resolve/coord-root.js +27 -0
- package/dist/core/hooks/resolve/intent.d.ts +33 -0
- package/dist/core/hooks/resolve/intent.d.ts.map +1 -0
- package/dist/core/hooks/resolve/intent.js +79 -0
- package/dist/core/hooks/resolve/owner.d.ts +42 -0
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -0
- package/dist/core/hooks/resolve/owner.js +140 -0
- package/dist/core/hooks/resolve/transcript.d.ts +26 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -0
- package/dist/core/hooks/resolve/transcript.js +73 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/lib/agent-browser/client.d.ts +99 -0
- package/dist/lib/agent-browser/client.d.ts.map +1 -0
- package/dist/lib/agent-browser/client.js +177 -0
- package/dist/lib/agent-browser/index.d.ts +2 -0
- package/dist/lib/agent-browser/index.d.ts.map +1 -0
- package/dist/lib/agent-browser/index.js +1 -0
- package/dist/lib/browser/client.d.ts +193 -0
- package/dist/lib/browser/client.d.ts.map +1 -0
- package/dist/lib/browser/client.js +325 -0
- package/dist/lib/browser/dev-overlay.d.ts +23 -0
- package/dist/lib/browser/dev-overlay.d.ts.map +1 -0
- package/dist/lib/browser/dev-overlay.js +153 -0
- package/dist/lib/browser/index.d.ts +5 -0
- package/dist/lib/browser/index.d.ts.map +1 -0
- package/dist/lib/browser/index.js +2 -0
- package/dist/lib/browser/layout.d.ts +79 -0
- package/dist/lib/browser/layout.d.ts.map +1 -0
- package/dist/lib/browser/layout.js +220 -0
- package/dist/lib/browser/visibility.d.ts +86 -0
- package/dist/lib/browser/visibility.d.ts.map +1 -0
- package/dist/lib/browser/visibility.js +333 -0
- package/dist/lib/browser/visual-diff.d.ts +38 -0
- package/dist/lib/browser/visual-diff.d.ts.map +1 -0
- package/dist/lib/browser/visual-diff.js +107 -0
- package/dist/lib/completion/bash.d.ts +25 -0
- package/dist/lib/completion/bash.d.ts.map +1 -0
- package/dist/lib/completion/bash.js +284 -0
- package/dist/lib/completion/fish.d.ts +16 -0
- package/dist/lib/completion/fish.d.ts.map +1 -0
- package/dist/lib/completion/fish.js +118 -0
- package/dist/lib/completion/index.d.ts +5 -0
- package/dist/lib/completion/index.d.ts.map +1 -0
- package/dist/lib/completion/index.js +4 -0
- package/dist/lib/completion/walk.d.ts +68 -0
- package/dist/lib/completion/walk.d.ts.map +1 -0
- package/dist/lib/completion/walk.js +102 -0
- package/dist/lib/completion/zsh.d.ts +13 -0
- package/dist/lib/completion/zsh.d.ts.map +1 -0
- package/dist/lib/completion/zsh.js +249 -0
- package/dist/lib/context/index.d.ts +107 -0
- package/dist/lib/context/index.d.ts.map +1 -0
- package/dist/lib/context/index.js +275 -0
- package/dist/lib/cookies/client.d.ts +131 -0
- package/dist/lib/cookies/client.d.ts.map +1 -0
- package/dist/lib/cookies/client.js +239 -0
- package/dist/lib/cookies/index.d.ts +2 -0
- package/dist/lib/cookies/index.d.ts.map +1 -0
- package/dist/lib/cookies/index.js +1 -0
- package/dist/lib/council/index.d.ts +266 -0
- package/dist/lib/council/index.d.ts.map +1 -0
- package/dist/lib/council/index.js +674 -0
- package/dist/lib/docs-index.d.ts +28 -0
- package/dist/lib/docs-index.d.ts.map +1 -0
- package/dist/lib/docs-index.js +169 -0
- package/dist/lib/docs-lint.d.ts +26 -0
- package/dist/lib/docs-lint.d.ts.map +1 -0
- package/dist/lib/docs-lint.js +378 -0
- package/dist/lib/docs-sweep.d.ts +34 -0
- package/dist/lib/docs-sweep.d.ts.map +1 -0
- package/dist/lib/docs-sweep.js +304 -0
- package/dist/lib/docs.d.ts +27 -0
- package/dist/lib/docs.d.ts.map +1 -0
- package/dist/lib/docs.js +142 -0
- package/dist/lib/env.d.ts +11 -0
- package/dist/lib/env.d.ts.map +1 -0
- package/dist/lib/env.js +12 -0
- package/dist/lib/exec.d.ts +32 -0
- package/dist/lib/exec.d.ts.map +1 -0
- package/dist/lib/exec.js +54 -0
- package/dist/lib/format.d.ts +29 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +139 -0
- package/dist/lib/http/client.d.ts +56 -0
- package/dist/lib/http/client.d.ts.map +1 -0
- package/dist/lib/http/client.js +160 -0
- package/dist/lib/http/index.d.ts +2 -0
- package/dist/lib/http/index.d.ts.map +1 -0
- package/dist/lib/http/index.js +1 -0
- package/dist/lib/identities/index.d.ts +77 -0
- package/dist/lib/identities/index.d.ts.map +1 -0
- package/dist/lib/identities/index.js +190 -0
- package/dist/lib/machine.d.ts +19 -0
- package/dist/lib/machine.d.ts.map +1 -0
- package/dist/lib/machine.js +61 -0
- package/dist/lib/presence.d.ts +48 -0
- package/dist/lib/presence.d.ts.map +1 -0
- package/dist/lib/presence.js +123 -0
- package/dist/lib/readability/client.d.ts +32 -0
- package/dist/lib/readability/client.d.ts.map +1 -0
- package/dist/lib/readability/client.js +119 -0
- package/dist/lib/readability/index.d.ts +2 -0
- package/dist/lib/readability/index.d.ts.map +1 -0
- package/dist/lib/readability/index.js +1 -0
- package/dist/lib/scratch/index.d.ts +74 -0
- package/dist/lib/scratch/index.d.ts.map +1 -0
- package/dist/lib/scratch/index.js +393 -0
- package/dist/lib/tunnel/gate.d.ts +12 -0
- package/dist/lib/tunnel/gate.d.ts.map +1 -0
- package/dist/lib/tunnel/gate.js +101 -0
- package/dist/lib/tunnel/state.d.ts +34 -0
- package/dist/lib/tunnel/state.d.ts.map +1 -0
- package/dist/lib/tunnel/state.js +132 -0
- package/package.json +160 -8
- package/schemas/.gitkeep +0 -0
- package/schemas/config.schema.json +109 -0
- package/src/cli.ts +22 -0
- package/src/commander.ts +242 -0
- package/src/commands/.gitkeep +0 -0
- package/src/commands/agents.ts +4567 -0
- package/src/commands/backup.ts +305 -0
- package/src/commands/browse-ai.ts +198 -0
- package/src/commands/browse.ts +849 -0
- package/src/commands/callers.ts +363 -0
- package/src/commands/completion.ts +193 -0
- package/src/commands/config-get.ts +161 -0
- package/src/commands/context.ts +209 -0
- package/src/commands/cookies.ts +198 -0
- package/src/commands/docs.ts +174 -0
- package/src/commands/doctor.ts +231 -0
- package/src/commands/edit-batch.ts +233 -0
- package/src/commands/eml.ts +519 -0
- package/src/commands/env.ts +254 -0
- package/src/commands/fetch.ts +136 -0
- package/src/commands/file-history.ts +202 -0
- package/src/commands/grep.ts +371 -0
- package/src/commands/init.ts +335 -0
- package/src/commands/outline.ts +564 -0
- package/src/commands/presence.ts +152 -0
- package/src/commands/read.ts +64 -0
- package/src/commands/scratch.ts +445 -0
- package/src/commands/session.ts +187 -0
- package/src/commands/sync.ts +306 -0
- package/src/commands/toc.ts +218 -0
- package/src/commands/tokens.ts +79 -0
- package/src/commands/tunnel.ts +633 -0
- package/src/commands/uninstall.ts +144 -0
- package/src/commands/web.ts +193 -0
- package/src/core/agents/canonical-emit.ts +77 -0
- package/src/core/agents/cli-emit.ts +64 -0
- package/src/core/agents/cli.ts +838 -0
- package/src/core/agents/codex-replay.ts +163 -0
- package/src/core/agents/coord-client.ts +249 -0
- package/src/core/agents/events/consume.ts +196 -0
- package/src/core/agents/events/emit.ts +108 -0
- package/src/core/agents/events/ulid.ts +51 -0
- package/src/core/agents/index.ts +14 -0
- package/src/core/agents/paths.ts +16 -0
- package/src/core/agents/render/prompt-context.ts +401 -0
- package/src/core/agents/render/session-context.ts +341 -0
- package/src/core/agents/rules/claim-conflict.ts +282 -0
- package/src/core/agents/rules/commit-conflict.ts +303 -0
- package/src/core/agents/rules/stop-hook.ts +229 -0
- package/src/core/agents/session-events.ts +228 -0
- package/src/core/agents/state/activity-log.ts +33 -0
- package/src/core/agents/state/council.ts +265 -0
- package/src/core/agents/state/heartbeat-projector.ts +488 -0
- package/src/core/agents/state/heartbeat-writer.ts +333 -0
- package/src/core/agents/state/names.ts +399 -0
- package/src/core/agents/state/pidmap.ts +38 -0
- package/src/core/agents/state/scratch.ts +121 -0
- package/src/core/agents/state/shell-mutation.ts +44 -0
- package/src/core/agents/state/stale-sweep.ts +190 -0
- package/src/core/config.ts +111 -0
- package/src/core/hooks/cli.ts +1247 -0
- package/src/core/hooks/effects/image-capture.ts +330 -0
- package/src/core/hooks/effects/index.ts +210 -0
- package/src/core/hooks/events/emit.ts +120 -0
- package/src/core/hooks/events/schema.ts +430 -0
- package/src/core/hooks/events/ulid.ts +51 -0
- package/src/core/hooks/harness/detect.ts +30 -0
- package/src/core/hooks/harness/events.ts +102 -0
- package/src/core/hooks/harness/output.ts +100 -0
- package/src/core/hooks/harness/parse.ts +180 -0
- package/src/core/hooks/index.ts +16 -0
- package/src/core/hooks/resolve/anchor.ts +51 -0
- package/src/core/hooks/resolve/coord-root.ts +25 -0
- package/src/core/hooks/resolve/intent.ts +89 -0
- package/src/core/hooks/resolve/owner.ts +140 -0
- package/src/core/hooks/resolve/transcript.ts +72 -0
- package/src/hooks/.gitkeep +0 -0
- package/src/index.ts +15 -0
- package/src/lib/agent-browser/client.ts +239 -0
- package/src/lib/agent-browser/index.ts +1 -0
- package/src/lib/browser/client.ts +449 -0
- package/src/lib/browser/dev-overlay.ts +207 -0
- package/src/lib/browser/index.ts +24 -0
- package/src/lib/browser/layout.ts +288 -0
- package/src/lib/browser/visibility.ts +419 -0
- package/src/lib/browser/visual-diff.ts +150 -0
- package/src/lib/completion/bash.ts +291 -0
- package/src/lib/completion/fish.ts +134 -0
- package/src/lib/completion/index.ts +10 -0
- package/src/lib/completion/walk.ts +184 -0
- package/src/lib/completion/zsh.ts +262 -0
- package/src/lib/context/index.ts +386 -0
- package/src/lib/cookies/client.ts +301 -0
- package/src/lib/cookies/index.ts +13 -0
- package/src/lib/council/index.ts +803 -0
- package/src/lib/docs-index.ts +216 -0
- package/src/lib/docs-lint.ts +413 -0
- package/src/lib/docs-sweep.ts +348 -0
- package/src/lib/docs.ts +199 -0
- package/src/lib/env.ts +12 -0
- package/src/lib/exec.ts +74 -0
- package/src/lib/format.ts +147 -0
- package/src/lib/http/client.ts +211 -0
- package/src/lib/http/index.ts +1 -0
- package/src/lib/identities/index.ts +210 -0
- package/src/lib/machine.ts +61 -0
- package/src/lib/presence.ts +154 -0
- package/src/lib/readability/client.ts +156 -0
- package/src/lib/readability/index.ts +5 -0
- package/src/lib/readability/turndown-plugin-gfm.d.ts +10 -0
- package/src/lib/scratch/index.ts +470 -0
- package/src/lib/tunnel/gate.ts +113 -0
- package/src/lib/tunnel/state.ts +167 -0
- package/src/web/.gitkeep +0 -0
- package/index.js +0 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness-aware hook output JSON. Each adapter target has its own protocol
|
|
3
|
+
* shape, so encode it once here so post-emit handlers don't have to branch on
|
|
4
|
+
* `harness` everywhere.
|
|
5
|
+
*
|
|
6
|
+
* Shapes (verified against live dispatchers + each harness's upstream hooks docs):
|
|
7
|
+
*
|
|
8
|
+
* - **Claude Code**: `{hookSpecificOutput: {hookEventName, additionalContext}}`
|
|
9
|
+
* for SessionStart / UserPromptSubmit / SubagentStart; deny uses
|
|
10
|
+
* `{hookSpecificOutput: {hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason}}`.
|
|
11
|
+
* - **Cursor**: `{additional_context, env?}` flat for sessionStart /
|
|
12
|
+
* beforeSubmitPrompt; deny uses `{permission: "deny", agent_message, user_message}`.
|
|
13
|
+
* - **Codex**: structurally identical to Claude Code (confirmed by Phase 0
|
|
14
|
+
* probe + the matching shape in the Codex harness adapter).
|
|
15
|
+
*
|
|
16
|
+
* Every helper writes to process.stdout + newline-terminates so callers can
|
|
17
|
+
* fire-and-forget. Empty text → no-op (no JSON written).
|
|
18
|
+
*/
|
|
19
|
+
/** Emit a context-injection (peer table, wiring check, council pending, …). */
|
|
20
|
+
export function emitContext(harness, event, text) {
|
|
21
|
+
if (!text || text.length === 0)
|
|
22
|
+
return;
|
|
23
|
+
const json = buildContextJson(harness, event, text);
|
|
24
|
+
process.stdout.write(`${JSON.stringify(json)}\n`);
|
|
25
|
+
}
|
|
26
|
+
/** Emit a PreToolUse deny: blocks the tool call with `reason` shown to the model. */
|
|
27
|
+
export function emitDeny(harness, reason) {
|
|
28
|
+
if (!reason)
|
|
29
|
+
return;
|
|
30
|
+
const json = buildDenyJson(harness, reason);
|
|
31
|
+
process.stdout.write(`${JSON.stringify(json)}\n`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Emit a Stop-hook block in the firing harness's enforcement channel and return
|
|
35
|
+
* the process exit code the caller should use.
|
|
36
|
+
*
|
|
37
|
+
* The verdict (allow/block + reason) is computed harness-agnostically in
|
|
38
|
+
* agents/rules/stop-hook.ts; this function only shapes *how the block is
|
|
39
|
+
* communicated back*, because each harness has a different mechanism:
|
|
40
|
+
*
|
|
41
|
+
* - **Claude Code / Codex** honor `exit 2` + a stderr reason as a turn block,
|
|
42
|
+
* and the harness re-prompts the model with the stderr text.
|
|
43
|
+
* - **Cursor** ignores stop-hook exit codes (non-zero = fail-open, the turn
|
|
44
|
+
* proceeds) and re-prompts ONLY via a `followup_message` field in stdout
|
|
45
|
+
* JSON, which it auto-submits as the next user message: the sanctioned
|
|
46
|
+
* "iterate until a goal is met" channel, capped by `loop_limit` (default 5).
|
|
47
|
+
* We exit 0 so Cursor treats the run as a success and honors the output.
|
|
48
|
+
* (Confirmed against cursor.com/docs/agent/hooks.)
|
|
49
|
+
*/
|
|
50
|
+
export function emitStopBlock(harness, verdict) {
|
|
51
|
+
const message = `${verdict.reason ?? "End-of-turn coordination ritual incomplete."}\n[agent-hook stop]: rule=${verdict.rule}`;
|
|
52
|
+
if (harness === "cursor") {
|
|
53
|
+
process.stdout.write(`${JSON.stringify({ followup_message: message })}\n`);
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
process.stderr.write(`${message}\n`);
|
|
57
|
+
return 2;
|
|
58
|
+
}
|
|
59
|
+
function buildContextJson(harness, event, text) {
|
|
60
|
+
if (harness === "cursor") {
|
|
61
|
+
// Cursor uses a flat top-level key + an env block that survives across the
|
|
62
|
+
// session. The dispatcher historically also wrote
|
|
63
|
+
// `env: {HARNERY_AGENT_COORD_HARNESS, HARNERY_AGENT_COORD_PLATFORM}`. These are
|
|
64
|
+
// observer hints, not load-bearing; agent-hook + agent-coord recover the
|
|
65
|
+
// harness from event metadata. Drop them.
|
|
66
|
+
return { additional_context: text };
|
|
67
|
+
}
|
|
68
|
+
// Claude Code + Codex share the `hookSpecificOutput` envelope.
|
|
69
|
+
return {
|
|
70
|
+
hookSpecificOutput: {
|
|
71
|
+
hookEventName: event,
|
|
72
|
+
additionalContext: text,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function buildDenyJson(harness, reason) {
|
|
77
|
+
if (harness === "cursor") {
|
|
78
|
+
return { permission: "deny", agent_message: reason, user_message: reason };
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
hookSpecificOutput: {
|
|
82
|
+
hookEventName: "PreToolUse",
|
|
83
|
+
permissionDecision: "deny",
|
|
84
|
+
permissionDecisionReason: reason,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness payload parser. One file because all three harnesses (CC, Cursor,
|
|
3
|
+
* Codex) share most of their PreToolUse / PostToolUse field names (Codex's
|
|
4
|
+
* field names match CC's directly) and Cursor's deltas are small enough to
|
|
5
|
+
* branch inline.
|
|
6
|
+
*
|
|
7
|
+
* The parser is intentionally tolerant: every field reads through `pickStr`,
|
|
8
|
+
* `pickNum`, etc., so a missing key returns `undefined` instead of throwing.
|
|
9
|
+
* Phase 2 ship criterion is "parser correctness across thousands of real
|
|
10
|
+
* events without affecting behavior": fail-soft beats fail-hard.
|
|
11
|
+
*/
|
|
12
|
+
import type { Harness } from "../events/schema.js";
|
|
13
|
+
export interface ParsedPayload {
|
|
14
|
+
hook_event_name?: string;
|
|
15
|
+
session_id?: string;
|
|
16
|
+
agent_id?: string;
|
|
17
|
+
subagent_id?: string;
|
|
18
|
+
conversation_id?: string;
|
|
19
|
+
parent_session_id?: string;
|
|
20
|
+
turn_id?: string;
|
|
21
|
+
parent_turn_id?: string;
|
|
22
|
+
transcript_path?: string;
|
|
23
|
+
cwd?: string;
|
|
24
|
+
pid?: number;
|
|
25
|
+
model?: string;
|
|
26
|
+
source?: string;
|
|
27
|
+
prompt?: string;
|
|
28
|
+
tool_name?: string;
|
|
29
|
+
tool_input?: unknown;
|
|
30
|
+
tool_response?: unknown;
|
|
31
|
+
tool_use_id?: string;
|
|
32
|
+
stop_hook_active?: boolean;
|
|
33
|
+
clean_exit?: boolean;
|
|
34
|
+
exit_status?: string;
|
|
35
|
+
reason?: string;
|
|
36
|
+
/** original parsed object, preserved for callers that need a field we didn't pluck. */
|
|
37
|
+
raw: Record<string, unknown>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse the raw stdin payload string for any harness. Returns null when JSON
|
|
41
|
+
* parse fails (Cursor occasionally fires hooks with no payload).
|
|
42
|
+
*/
|
|
43
|
+
export declare function parsePayload(raw: string, _harness: Harness): ParsedPayload | null;
|
|
44
|
+
/**
|
|
45
|
+
* Pull the bash command string out of a Bash/Shell tool_input. Returns
|
|
46
|
+
* undefined for non-shell tools.
|
|
47
|
+
*/
|
|
48
|
+
export declare function extractBashCommand(toolName: string | undefined, toolInput: unknown): string | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Pull the model's description string out of a tool_input. Only Claude Code's
|
|
51
|
+
* Bash tool requires this field; falls back to undefined elsewhere.
|
|
52
|
+
*/
|
|
53
|
+
export declare function extractToolDescription(toolInput: unknown): string | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Each harness uses a slightly different name for the "same" lifecycle event.
|
|
56
|
+
* Map the CLI-arg event-name (kebab-case, set by us in the wiring) to one of
|
|
57
|
+
* the canonical event_types. Phase 2's CLI passes the kebab event
|
|
58
|
+
* name; this returns the canonical event_type or null when the event has no
|
|
59
|
+
* canonical equivalent (e.g. Cursor's before-shell-execution duplicates
|
|
60
|
+
* pre-tool-use semantically, so we route both to `tool.pre_use`).
|
|
61
|
+
*/
|
|
62
|
+
export declare function normalizeEventName(eventName: string): {
|
|
63
|
+
event_type: NormalizedEventType;
|
|
64
|
+
intra_turn: boolean;
|
|
65
|
+
} | null;
|
|
66
|
+
export type NormalizedEventType = "session.start" | "session.end" | "user_prompt.submit" | "turn.stop" | "subagent.start" | "subagent.stop" | "tool.pre_use" | "tool.post_use" | "tool.post_use_failure";
|
|
67
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/harness/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uFAAuF;IACvF,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAkCjF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,SAAS,EAAE,OAAO,GACjB,MAAM,GAAG,SAAS,CASpB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAO7E;AAmBD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAChB;IAAE,UAAU,EAAE,mBAAmB,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA6BjE;AAED,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,aAAa,GACb,oBAAoB,GACpB,WAAW,GACX,gBAAgB,GAChB,eAAe,GACf,cAAc,GACd,eAAe,GACf,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness payload parser. One file because all three harnesses (CC, Cursor,
|
|
3
|
+
* Codex) share most of their PreToolUse / PostToolUse field names (Codex's
|
|
4
|
+
* field names match CC's directly) and Cursor's deltas are small enough to
|
|
5
|
+
* branch inline.
|
|
6
|
+
*
|
|
7
|
+
* The parser is intentionally tolerant: every field reads through `pickStr`,
|
|
8
|
+
* `pickNum`, etc., so a missing key returns `undefined` instead of throwing.
|
|
9
|
+
* Phase 2 ship criterion is "parser correctness across thousands of real
|
|
10
|
+
* events without affecting behavior": fail-soft beats fail-hard.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Parse the raw stdin payload string for any harness. Returns null when JSON
|
|
14
|
+
* parse fails (Cursor occasionally fires hooks with no payload).
|
|
15
|
+
*/
|
|
16
|
+
export function parsePayload(raw, _harness) {
|
|
17
|
+
if (!raw || raw.trim().length === 0)
|
|
18
|
+
return null;
|
|
19
|
+
let json;
|
|
20
|
+
try {
|
|
21
|
+
json = JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
hook_event_name: pickStr(json, "hook_event_name"),
|
|
28
|
+
session_id: pickStr(json, "session_id"),
|
|
29
|
+
agent_id: pickStr(json, "agent_id"),
|
|
30
|
+
subagent_id: pickStr(json, "subagent_id"),
|
|
31
|
+
conversation_id: pickStr(json, "conversation_id"),
|
|
32
|
+
parent_session_id: pickStr(json, "parent_session_id"),
|
|
33
|
+
turn_id: pickStr(json, "turn_id"),
|
|
34
|
+
parent_turn_id: pickStr(json, "parent_turn_id"),
|
|
35
|
+
transcript_path: pickStr(json, "transcript_path"),
|
|
36
|
+
cwd: pickStr(json, "cwd"),
|
|
37
|
+
pid: pickNum(json, "pid"),
|
|
38
|
+
model: pickStr(json, "model"),
|
|
39
|
+
source: pickStr(json, "source"),
|
|
40
|
+
prompt: pickStr(json, "prompt"),
|
|
41
|
+
tool_name: pickStr(json, "tool_name"),
|
|
42
|
+
tool_input: json.tool_input,
|
|
43
|
+
tool_response: json.tool_response,
|
|
44
|
+
tool_use_id: pickStr(json, "tool_use_id"),
|
|
45
|
+
stop_hook_active: pickBool(json, "stop_hook_active"),
|
|
46
|
+
clean_exit: pickBool(json, "clean_exit"),
|
|
47
|
+
exit_status: pickStr(json, "exit_status"),
|
|
48
|
+
reason: pickStr(json, "reason"),
|
|
49
|
+
raw: json,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Pull the bash command string out of a Bash/Shell tool_input. Returns
|
|
54
|
+
* undefined for non-shell tools.
|
|
55
|
+
*/
|
|
56
|
+
export function extractBashCommand(toolName, toolInput) {
|
|
57
|
+
if (!toolName)
|
|
58
|
+
return undefined;
|
|
59
|
+
if (toolName !== "Bash" && toolName !== "Shell")
|
|
60
|
+
return undefined;
|
|
61
|
+
if (toolInput && typeof toolInput === "object") {
|
|
62
|
+
const t = toolInput;
|
|
63
|
+
const cmd = t.command;
|
|
64
|
+
if (typeof cmd === "string")
|
|
65
|
+
return cmd;
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Pull the model's description string out of a tool_input. Only Claude Code's
|
|
71
|
+
* Bash tool requires this field; falls back to undefined elsewhere.
|
|
72
|
+
*/
|
|
73
|
+
export function extractToolDescription(toolInput) {
|
|
74
|
+
if (toolInput && typeof toolInput === "object") {
|
|
75
|
+
const t = toolInput;
|
|
76
|
+
const d = t.description;
|
|
77
|
+
if (typeof d === "string")
|
|
78
|
+
return d;
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
function pickStr(o, k) {
|
|
83
|
+
const v = o[k];
|
|
84
|
+
return typeof v === "string" && v.length > 0 ? v : undefined;
|
|
85
|
+
}
|
|
86
|
+
function pickNum(o, k) {
|
|
87
|
+
const v = o[k];
|
|
88
|
+
return typeof v === "number" && Number.isFinite(v) ? v : undefined;
|
|
89
|
+
}
|
|
90
|
+
function pickBool(o, k) {
|
|
91
|
+
const v = o[k];
|
|
92
|
+
return typeof v === "boolean" ? v : undefined;
|
|
93
|
+
}
|
|
94
|
+
// ── Event-name normalization ────────────────────────────────────────────────
|
|
95
|
+
/**
|
|
96
|
+
* Each harness uses a slightly different name for the "same" lifecycle event.
|
|
97
|
+
* Map the CLI-arg event-name (kebab-case, set by us in the wiring) to one of
|
|
98
|
+
* the canonical event_types. Phase 2's CLI passes the kebab event
|
|
99
|
+
* name; this returns the canonical event_type or null when the event has no
|
|
100
|
+
* canonical equivalent (e.g. Cursor's before-shell-execution duplicates
|
|
101
|
+
* pre-tool-use semantically, so we route both to `tool.pre_use`).
|
|
102
|
+
*/
|
|
103
|
+
export function normalizeEventName(eventName) {
|
|
104
|
+
switch (eventName) {
|
|
105
|
+
case "session-start":
|
|
106
|
+
return { event_type: "session.start", intra_turn: false };
|
|
107
|
+
case "session-end":
|
|
108
|
+
return { event_type: "session.end", intra_turn: false };
|
|
109
|
+
case "user-prompt-submit":
|
|
110
|
+
return { event_type: "user_prompt.submit", intra_turn: false };
|
|
111
|
+
case "stop":
|
|
112
|
+
return { event_type: "turn.stop", intra_turn: false };
|
|
113
|
+
case "stop-failure":
|
|
114
|
+
// Phase 2: a failed stop is still a turn boundary; emit turn.stop and
|
|
115
|
+
// attach the failure signal in `data`. Phase 5 may introduce a
|
|
116
|
+
// dedicated `turn.stop_failure` event if the projector needs to branch.
|
|
117
|
+
return { event_type: "turn.stop", intra_turn: false };
|
|
118
|
+
case "sub-agent-start":
|
|
119
|
+
return { event_type: "subagent.start", intra_turn: false };
|
|
120
|
+
case "sub-agent-stop":
|
|
121
|
+
return { event_type: "subagent.stop", intra_turn: false };
|
|
122
|
+
case "pre-tool-use":
|
|
123
|
+
case "before-shell-execution":
|
|
124
|
+
return { event_type: "tool.pre_use", intra_turn: true };
|
|
125
|
+
case "post-tool-use":
|
|
126
|
+
return { event_type: "tool.post_use", intra_turn: true };
|
|
127
|
+
case "post-tool-use-failure":
|
|
128
|
+
return { event_type: "tool.post_use_failure", intra_turn: true };
|
|
129
|
+
default:
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent-hooks library exports.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1 (skeleton): exposes only the canonical event schema types. Parsers,
|
|
5
|
+
* resolvers, and emit helpers ship in Phase 2.
|
|
6
|
+
*/
|
|
7
|
+
export { type Event, type EventEnvelope, type EventType, type Harness, type RedactionMarker, SCHEMA_VERSION, type Source, } from "./events/schema.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,KAAK,KAAK,EACV,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,OAAO,EACZ,KAAK,eAAe,EACpB,cAAc,EACd,KAAK,MAAM,GACZ,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure pid-map anchor selection: picks which PID in a process's ppid chain
|
|
3
|
+
* the heartbeat pid-map row should be keyed to, so the agent's later shell
|
|
4
|
+
* tool calls (which ppid-walk up to find it) resolve their own identity.
|
|
5
|
+
*
|
|
6
|
+
* Split out of cli.ts's `findHarnessAnchorPid` so the comm-matching logic is
|
|
7
|
+
* unit-testable against the real Phase 0 Cursor probe chains without needing a
|
|
8
|
+
* live /proc tree.
|
|
9
|
+
*
|
|
10
|
+
* Why the cursor `node` fallback exists: Cursor's WSL/Linux process tree has
|
|
11
|
+
* NO process named `cursor`: the chain is `bash → bash → node → node → sh →
|
|
12
|
+
* Relay → init`. The `node` ancestors are stable across every hook + tool event
|
|
13
|
+
* in one IDE-window session, so anchoring there gives the agent's shell tool
|
|
14
|
+
* calls a reachable, stable pid-map row. This faithfully restores the previous
|
|
15
|
+
* cursor anchor behavior (match `cursor` first, then fall back to `node`) that
|
|
16
|
+
* was dropped in the Phase 4-6 TS refactor, the same regression class as the
|
|
17
|
+
* heartbeat-platform + pidmap-self-heal losses. Scoped to `harness === "cursor"`
|
|
18
|
+
* so Claude Code / Codex never
|
|
19
|
+
* mis-anchor on an unrelated `node` ancestor (they match their own comm token
|
|
20
|
+
* directly).
|
|
21
|
+
*
|
|
22
|
+
* Known limitation (matches the bash original): two Cursor chats sharing one
|
|
23
|
+
* IDE window share their `node` ancestor, so the pid-map row is last-writer-
|
|
24
|
+
* wins between them. Single-chat-per-window (the common case) is correct;
|
|
25
|
+
* concurrent same-window chats disambiguate via `--session-id`.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Pick the anchor PID from a ppid chain ordered nearest-first (the resolving
|
|
29
|
+
* process at index 0, walking up toward init). Returns the first ancestor
|
|
30
|
+
* matching a harness comm token; for cursor, falls back to the first `node`
|
|
31
|
+
* ancestor; otherwise undefined (caller falls back to process.ppid).
|
|
32
|
+
*/
|
|
33
|
+
export declare function selectAnchorPid(chain: ReadonlyArray<{
|
|
34
|
+
pid: number;
|
|
35
|
+
comm: string;
|
|
36
|
+
}>, harness?: string): number | undefined;
|
|
37
|
+
//# sourceMappingURL=anchor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/resolve/anchor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,aAAa,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACnD,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,GAAG,SAAS,CAUpB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure pid-map anchor selection: picks which PID in a process's ppid chain
|
|
3
|
+
* the heartbeat pid-map row should be keyed to, so the agent's later shell
|
|
4
|
+
* tool calls (which ppid-walk up to find it) resolve their own identity.
|
|
5
|
+
*
|
|
6
|
+
* Split out of cli.ts's `findHarnessAnchorPid` so the comm-matching logic is
|
|
7
|
+
* unit-testable against the real Phase 0 Cursor probe chains without needing a
|
|
8
|
+
* live /proc tree.
|
|
9
|
+
*
|
|
10
|
+
* Why the cursor `node` fallback exists: Cursor's WSL/Linux process tree has
|
|
11
|
+
* NO process named `cursor`: the chain is `bash → bash → node → node → sh →
|
|
12
|
+
* Relay → init`. The `node` ancestors are stable across every hook + tool event
|
|
13
|
+
* in one IDE-window session, so anchoring there gives the agent's shell tool
|
|
14
|
+
* calls a reachable, stable pid-map row. This faithfully restores the previous
|
|
15
|
+
* cursor anchor behavior (match `cursor` first, then fall back to `node`) that
|
|
16
|
+
* was dropped in the Phase 4-6 TS refactor, the same regression class as the
|
|
17
|
+
* heartbeat-platform + pidmap-self-heal losses. Scoped to `harness === "cursor"`
|
|
18
|
+
* so Claude Code / Codex never
|
|
19
|
+
* mis-anchor on an unrelated `node` ancestor (they match their own comm token
|
|
20
|
+
* directly).
|
|
21
|
+
*
|
|
22
|
+
* Known limitation (matches the bash original): two Cursor chats sharing one
|
|
23
|
+
* IDE window share their `node` ancestor, so the pid-map row is last-writer-
|
|
24
|
+
* wins between them. Single-chat-per-window (the common case) is correct;
|
|
25
|
+
* concurrent same-window chats disambiguate via `--session-id`.
|
|
26
|
+
*/
|
|
27
|
+
/** Harness-binary comm names. CC's tool calls descend from `claude`, Codex's
|
|
28
|
+
* from `codex`; matched directly so neither needs the `node` fallback. */
|
|
29
|
+
const PRIMARY_COMM_TOKENS = new Set(["claude", "claude-code", "cursor", "codex"]);
|
|
30
|
+
/**
|
|
31
|
+
* Pick the anchor PID from a ppid chain ordered nearest-first (the resolving
|
|
32
|
+
* process at index 0, walking up toward init). Returns the first ancestor
|
|
33
|
+
* matching a harness comm token; for cursor, falls back to the first `node`
|
|
34
|
+
* ancestor; otherwise undefined (caller falls back to process.ppid).
|
|
35
|
+
*/
|
|
36
|
+
export function selectAnchorPid(chain, harness) {
|
|
37
|
+
for (const hop of chain) {
|
|
38
|
+
if (PRIMARY_COMM_TOKENS.has(hop.comm))
|
|
39
|
+
return hop.pid;
|
|
40
|
+
}
|
|
41
|
+
if (harness === "cursor") {
|
|
42
|
+
for (const hop of chain) {
|
|
43
|
+
if (hop.comm === "node")
|
|
44
|
+
return hop.pid;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walk up from `start` looking for a directory containing `.harnery/`. The
|
|
3
|
+
* single coord-root resolution so every adapter agrees on the same root.
|
|
4
|
+
*/
|
|
5
|
+
export declare function findCoordRoot(start?: string): string | null;
|
|
6
|
+
//# sourceMappingURL=coord-root.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coord-root.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/resolve/coord-root.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAgB1E"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { coordEnv } from "../../../lib/env.js";
|
|
4
|
+
/**
|
|
5
|
+
* Walk up from `start` looking for a directory containing `.harnery/`. The
|
|
6
|
+
* single coord-root resolution so every adapter agrees on the same root.
|
|
7
|
+
*/
|
|
8
|
+
export function findCoordRoot(start = process.cwd()) {
|
|
9
|
+
// HARNERY_COORD_ROOT_OVERRIDE: test-mode escape hatch matched by agent-coord
|
|
10
|
+
// and the bash side. Lets the sandboxed coord-test suite run against a
|
|
11
|
+
// temp directory rather than the real monorepo root. agent-hook's
|
|
12
|
+
// session.start handler may be the FIRST thing to create .harnery/ in a
|
|
13
|
+
// fresh sandbox, so the override is honored unconditionally (we don't
|
|
14
|
+
// require .harnery/ to pre-exist).
|
|
15
|
+
const override = coordEnv("COORD_ROOT_OVERRIDE");
|
|
16
|
+
if (override)
|
|
17
|
+
return override;
|
|
18
|
+
let dir = resolve(start);
|
|
19
|
+
while (true) {
|
|
20
|
+
if (existsSync(join(dir, ".harnery")))
|
|
21
|
+
return dir;
|
|
22
|
+
const parent = dirname(dir);
|
|
23
|
+
if (parent === dir)
|
|
24
|
+
return null;
|
|
25
|
+
dir = parent;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the model-declared intent for the current tool call. Three-source
|
|
3
|
+
* precedence:
|
|
4
|
+
*
|
|
5
|
+
* 1. `# intent: X` comment on the first line of the bash command.
|
|
6
|
+
* 2. `description` field on the tool input (Claude Code only).
|
|
7
|
+
* 3. `<intent>...</intent>` tag in the most-recent assistant prose, read
|
|
8
|
+
* from `.harnery/.last-intent.<instance_id>` (the bash bash-tap is the
|
|
9
|
+
* only thing that does transcript scanning today; agent-hook stamps the
|
|
10
|
+
* file on precedence 1/2 so the bash-tap can fall back to it).
|
|
11
|
+
*
|
|
12
|
+
* Phase 8 (2026-05-27): agent-hook writes the stamp file itself on precedence
|
|
13
|
+
* 1/2 (replacing coord-intent-stamp.sh's command/description branches). The
|
|
14
|
+
* transcript-tag branch is now the only thing left in coord-intent-stamp.sh.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveIntent(opts: {
|
|
17
|
+
coordRoot: string;
|
|
18
|
+
instanceId: string;
|
|
19
|
+
/** First-line `# intent: X` comment from the bash command (preferred fresh source). */
|
|
20
|
+
commandIntentComment?: string;
|
|
21
|
+
/** `description` field on the tool input (Claude Code only). */
|
|
22
|
+
description?: string;
|
|
23
|
+
}): {
|
|
24
|
+
intent: string;
|
|
25
|
+
source: "command-comment" | "description" | "stamp" | "none";
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Match `# intent: X` at the start of a command (after optional leading
|
|
29
|
+
* whitespace on the first line). Mirrors `extract_command_intent_comment` in
|
|
30
|
+
* coord-intent-stamp.sh.
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractIntentComment(command: string | undefined): string | undefined;
|
|
33
|
+
//# sourceMappingURL=intent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/resolve/intent.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,iBAAiB,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,CAAA;CAAE,CAkCnF;AAYD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAMpF"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the model-declared intent for the current tool call. Three-source
|
|
5
|
+
* precedence:
|
|
6
|
+
*
|
|
7
|
+
* 1. `# intent: X` comment on the first line of the bash command.
|
|
8
|
+
* 2. `description` field on the tool input (Claude Code only).
|
|
9
|
+
* 3. `<intent>...</intent>` tag in the most-recent assistant prose, read
|
|
10
|
+
* from `.harnery/.last-intent.<instance_id>` (the bash bash-tap is the
|
|
11
|
+
* only thing that does transcript scanning today; agent-hook stamps the
|
|
12
|
+
* file on precedence 1/2 so the bash-tap can fall back to it).
|
|
13
|
+
*
|
|
14
|
+
* Phase 8 (2026-05-27): agent-hook writes the stamp file itself on precedence
|
|
15
|
+
* 1/2 (replacing coord-intent-stamp.sh's command/description branches). The
|
|
16
|
+
* transcript-tag branch is now the only thing left in coord-intent-stamp.sh.
|
|
17
|
+
*/
|
|
18
|
+
export function resolveIntent(opts) {
|
|
19
|
+
const stampPath = join(opts.coordRoot, ".harnery", `.last-intent.${opts.instanceId}`);
|
|
20
|
+
// 1. Fresh from the command itself (most reliable, cross-harness).
|
|
21
|
+
if (opts.commandIntentComment) {
|
|
22
|
+
const cleaned = clamp(opts.commandIntentComment);
|
|
23
|
+
if (cleaned) {
|
|
24
|
+
writeStamp(stampPath, cleaned);
|
|
25
|
+
return { intent: cleaned, source: "command-comment" };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// 2. Fresh from the tool input description (Claude Code only).
|
|
29
|
+
if (opts.description) {
|
|
30
|
+
const cleaned = clamp(opts.description);
|
|
31
|
+
if (cleaned) {
|
|
32
|
+
writeStamp(stampPath, cleaned);
|
|
33
|
+
return { intent: cleaned, source: "description" };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// 3. Whatever the bash-tap stamped from a transcript <intent> tag.
|
|
37
|
+
if (existsSync(stampPath)) {
|
|
38
|
+
try {
|
|
39
|
+
const stamped = readFileSync(stampPath, "utf8").trim();
|
|
40
|
+
if (stamped && stamped !== "(no intent)") {
|
|
41
|
+
return { intent: stamped, source: "stamp" };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
/* fallthrough */
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return { intent: "(no intent)", source: "none" };
|
|
49
|
+
}
|
|
50
|
+
function writeStamp(path, value) {
|
|
51
|
+
try {
|
|
52
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
53
|
+
writeFileSync(tmp, value, "utf8");
|
|
54
|
+
renameSync(tmp, path);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
/* best-effort */
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Match `# intent: X` at the start of a command (after optional leading
|
|
62
|
+
* whitespace on the first line). Mirrors `extract_command_intent_comment` in
|
|
63
|
+
* coord-intent-stamp.sh.
|
|
64
|
+
*/
|
|
65
|
+
export function extractIntentComment(command) {
|
|
66
|
+
if (!command)
|
|
67
|
+
return undefined;
|
|
68
|
+
const firstLine = command.split("\n", 1)[0];
|
|
69
|
+
const m = firstLine?.match(/^[ \t]*#[ \t]*intent:[ \t]*(.+)$/);
|
|
70
|
+
if (!m)
|
|
71
|
+
return undefined;
|
|
72
|
+
return m[1]?.trimEnd();
|
|
73
|
+
}
|
|
74
|
+
function clamp(v) {
|
|
75
|
+
const trimmed = v.trim();
|
|
76
|
+
if (trimmed.length <= 200)
|
|
77
|
+
return trimmed;
|
|
78
|
+
return `${trimmed.slice(0, 197)}...`;
|
|
79
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the canonical `instance_id` for the current hook invocation.
|
|
3
|
+
*
|
|
4
|
+
* Precedence:
|
|
5
|
+
*
|
|
6
|
+
* 1. `HARNERY_AGENT_COORD_OWNER` env var. Set by harness adapters when they know
|
|
7
|
+
* the owner identity at spawn time (Codex's apply_patch tool path uses
|
|
8
|
+
* this).
|
|
9
|
+
* 2. Hook payload fields, in order: `agent_id` → `subagent_id` →
|
|
10
|
+
* `session_id` → `conversation_id`. agent_id wins for CC subagent
|
|
11
|
+
* events; session_id is the parent-shape default.
|
|
12
|
+
* 3. PID-map lookup at `.harnery/pid-map/<pid>` for our own pid, then ppid
|
|
13
|
+
* chain (up to 20 hops).
|
|
14
|
+
*
|
|
15
|
+
* Returns null when nothing resolves. Callers must treat null as "no owner"
|
|
16
|
+
* and skip the event (Phase 2 fail-safe; Phase 3 will mint a temporary owner
|
|
17
|
+
* for orphan events).
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveOwner(opts: {
|
|
20
|
+
payload: Record<string, unknown> | null;
|
|
21
|
+
coordRoot: string;
|
|
22
|
+
}): {
|
|
23
|
+
instance_id: string;
|
|
24
|
+
source: "env" | "payload" | "pidmap-self" | "pidmap-ancestor";
|
|
25
|
+
} | null;
|
|
26
|
+
/**
|
|
27
|
+
* Find the parent owner for a subagent invocation. The per-shell marker at
|
|
28
|
+
* `.harnery/shells/<pid>` is set by `sub-agent-start` and removed by
|
|
29
|
+
* `sub-agent-stop`.
|
|
30
|
+
*
|
|
31
|
+
* Phase 2 stub: the marker file isn't written yet, so we return null in most
|
|
32
|
+
* cases. Phase 2 callers can pass through.
|
|
33
|
+
*/
|
|
34
|
+
export declare function readShellMarker(coordRoot: string, pid: number): string | null;
|
|
35
|
+
/** Read the heartbeat-recorded `agent_id` for an owner if it exists. */
|
|
36
|
+
export declare function readAgentIdForOwner(coordRoot: string, instanceId: string): string | null;
|
|
37
|
+
/** Diagnostic: list of pid-map entries (for debugging). */
|
|
38
|
+
export declare function listPidmap(coordRoot: string): Array<{
|
|
39
|
+
pid: number;
|
|
40
|
+
owner: string;
|
|
41
|
+
}>;
|
|
42
|
+
//# sourceMappingURL=owner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/resolve/owner.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,GAAG,SAAS,GAAG,aAAa,GAAG,iBAAiB,CAAA;CAAE,GAAG,IAAI,CA+ChG;AAmBD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ7E;AAED,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUxF;AAED,2DAA2D;AAC3D,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBnF"}
|