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,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `harn init`: idempotently wire harnery into a project.
|
|
3
|
+
*
|
|
4
|
+
* Two things a fresh consumer otherwise has to know to do by hand (both silent
|
|
5
|
+
* if skipped):
|
|
6
|
+
* 1. Create the `.harnery/` coord root; without it `findCoordRoot` returns
|
|
7
|
+
* null and every hook no-ops forever.
|
|
8
|
+
* 2. Register the agent-hook entries in the harness settings file.
|
|
9
|
+
*
|
|
10
|
+
* Wires whichever harness `--harness` names (Claude Code `.claude/settings.json`,
|
|
11
|
+
* Cursor `.cursor/hooks.json`, or Codex `.codex/hooks.json`): the per-harness
|
|
12
|
+
* file path, event list, and hook-entry shape all come from HARNESS_SPECS.
|
|
13
|
+
*
|
|
14
|
+
* `harn init` does both, non-destructively: it merges hook entries into an
|
|
15
|
+
* existing settings file (preserving any other hooks) and skips entries that are
|
|
16
|
+
* already wired, so it's safe to re-run. `--dry-run` previews without writing.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { spawnSync } from "node:child_process";
|
|
20
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
21
|
+
import { dirname, relative, resolve } from "node:path";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
import type { Command } from "commander";
|
|
24
|
+
import type { EmitContext } from "../commander.ts";
|
|
25
|
+
import { DEFAULT_BIN_NAME, stripJsonComments } from "../core/config.ts";
|
|
26
|
+
import {
|
|
27
|
+
HARNESS_SPECS,
|
|
28
|
+
type HarnessId,
|
|
29
|
+
type HarnessSpec,
|
|
30
|
+
type HookEntryShape,
|
|
31
|
+
} from "../core/hooks/harness/events.ts";
|
|
32
|
+
|
|
33
|
+
// This file is src/commands/init.ts → harnery package root is two levels up.
|
|
34
|
+
const HARNERY_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
35
|
+
|
|
36
|
+
interface InitOpts {
|
|
37
|
+
harness: string;
|
|
38
|
+
dryRun?: boolean;
|
|
39
|
+
projectRoot?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Claude Code + Codex entry: `{ hooks: [{ type, command }] }`. */
|
|
43
|
+
interface ClaudeHookGroup {
|
|
44
|
+
matcher?: string;
|
|
45
|
+
hooks: { type: string; command: string }[];
|
|
46
|
+
}
|
|
47
|
+
/** Cursor entry: a flat `{ command }`. */
|
|
48
|
+
interface CursorHookGroup {
|
|
49
|
+
command: string;
|
|
50
|
+
type?: string;
|
|
51
|
+
matcher?: string;
|
|
52
|
+
}
|
|
53
|
+
type HookGroup = ClaudeHookGroup | CursorHookGroup;
|
|
54
|
+
|
|
55
|
+
export interface SettingsFile {
|
|
56
|
+
version?: number;
|
|
57
|
+
hooks?: Record<string, HookGroup[]>;
|
|
58
|
+
[k: string]: unknown;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function registerInitCommand(program: Command, emit: EmitContext, binName?: string): void {
|
|
62
|
+
program
|
|
63
|
+
.command("init")
|
|
64
|
+
.description(
|
|
65
|
+
"Bootstrap harnery in this project: create .harnery/ and wire the harness " +
|
|
66
|
+
"hooks (idempotent; safe to re-run). Use --dry-run to preview.",
|
|
67
|
+
)
|
|
68
|
+
.option("--harness <id>", "claude-code | cursor | codex", "claude-code")
|
|
69
|
+
.option("--dry-run", "Show what would change without writing")
|
|
70
|
+
.option("--project-root <path>", "Project root (default: git toplevel, else cwd)")
|
|
71
|
+
.action((opts: InitOpts) => {
|
|
72
|
+
const harness = opts.harness as HarnessId;
|
|
73
|
+
const spec = HARNESS_SPECS[harness];
|
|
74
|
+
if (!spec) {
|
|
75
|
+
emit.text(`Unknown harness '${opts.harness}'. Expected: claude-code | cursor | codex.`);
|
|
76
|
+
emit.setExitCode(1);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const projectRoot = resolve(opts.projectRoot ?? gitTopLevel() ?? process.cwd());
|
|
81
|
+
const dryRun = opts.dryRun === true;
|
|
82
|
+
const actions: string[] = [];
|
|
83
|
+
|
|
84
|
+
// ── 1. coord root ──────────────────────────────────────────────────────
|
|
85
|
+
const coordDir = resolve(projectRoot, ".harnery");
|
|
86
|
+
if (existsSync(coordDir)) {
|
|
87
|
+
actions.push("· .harnery/ already exists");
|
|
88
|
+
} else if (dryRun) {
|
|
89
|
+
actions.push("+ would create .harnery/ (+ .harnery/.gitignore)");
|
|
90
|
+
} else {
|
|
91
|
+
mkdirSync(coordDir, { recursive: true });
|
|
92
|
+
// Runtime state is machine-local; don't let consumers commit heartbeats.
|
|
93
|
+
writeFileSync(resolve(coordDir, ".gitignore"), "*\n!.gitignore\n");
|
|
94
|
+
actions.push("+ created .harnery/ (+ .harnery/.gitignore)");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ── 1b. stamp the host bin name ────────────────────────────────────────
|
|
98
|
+
// The coord binaries (agent-hook/agent-coord) and web UI run as harnery
|
|
99
|
+
// itself, so they can't see a consumer CLI's name; they read it back from
|
|
100
|
+
// config.jsonc. Standalone `harn` is the resolver's default, so only a
|
|
101
|
+
// consumer (binName ≠ "harn") needs the stamp.
|
|
102
|
+
if (binName && binName !== DEFAULT_BIN_NAME) {
|
|
103
|
+
const configPath = resolve(coordDir, "config.jsonc");
|
|
104
|
+
const stamp = stampBinName(configPath, binName, dryRun);
|
|
105
|
+
if (stamp) actions.push(stamp);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ── 2. harness hooks ───────────────────────────────────────────────────
|
|
109
|
+
const settingsPath = resolve(projectRoot, spec.settingsFile);
|
|
110
|
+
const agentHook = relative(projectRoot, resolve(HARNERY_ROOT, "bin", "agent-hook"));
|
|
111
|
+
|
|
112
|
+
let settings: SettingsFile;
|
|
113
|
+
if (existsSync(settingsPath)) {
|
|
114
|
+
try {
|
|
115
|
+
settings = JSON.parse(readFileSync(settingsPath, "utf8")) as SettingsFile;
|
|
116
|
+
} catch (err) {
|
|
117
|
+
emit.text(
|
|
118
|
+
`✗ ${rel(projectRoot, settingsPath)} exists but isn't valid JSON; refusing to ` +
|
|
119
|
+
`overwrite. Fix it and re-run.\n (${(err as Error).message})`,
|
|
120
|
+
);
|
|
121
|
+
emit.setExitCode(1);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
settings = {};
|
|
126
|
+
}
|
|
127
|
+
const { wired, already } = wireHooks(settings, spec, agentHook, harness);
|
|
128
|
+
|
|
129
|
+
if (wired === 0) {
|
|
130
|
+
actions.push(
|
|
131
|
+
`· all ${spec.events.length} ${harness} hooks already wired in ${rel(projectRoot, settingsPath)}`,
|
|
132
|
+
);
|
|
133
|
+
} else if (dryRun) {
|
|
134
|
+
actions.push(
|
|
135
|
+
`+ would wire ${wired} hook(s) into ${rel(projectRoot, settingsPath)} (${already} already present)`,
|
|
136
|
+
);
|
|
137
|
+
} else {
|
|
138
|
+
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
139
|
+
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`);
|
|
140
|
+
actions.push(
|
|
141
|
+
`+ wired ${wired} hook(s) into ${rel(projectRoot, settingsPath)} (${already} already present)`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
emit.text(render(projectRoot, dryRun, actions));
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Merge agent-hook entries into a harness settings object in place, idempotently.
|
|
151
|
+
* Preserves every existing hook; skips events already wired to
|
|
152
|
+
* `agent-hook <subcommand>`. Honors the harness's entry shape (Claude/Codex nest
|
|
153
|
+
* under an inner `hooks` array; Cursor uses a flat `{ command }`) and ensures the
|
|
154
|
+
* root `version` key when the harness requires one. Pure (no fs/git) so it's
|
|
155
|
+
* unit-testable.
|
|
156
|
+
*
|
|
157
|
+
* The trailing space in the match (`agent-hook ${subcommand} `) is load-bearing:
|
|
158
|
+
* it keeps `stop` from matching `stop-failure`.
|
|
159
|
+
*/
|
|
160
|
+
export function wireHooks(
|
|
161
|
+
settings: SettingsFile,
|
|
162
|
+
spec: HarnessSpec,
|
|
163
|
+
agentHookPath: string,
|
|
164
|
+
harness: HarnessId,
|
|
165
|
+
): { wired: number; already: number } {
|
|
166
|
+
if (spec.rootVersion !== undefined && settings.version === undefined) {
|
|
167
|
+
settings.version = spec.rootVersion;
|
|
168
|
+
}
|
|
169
|
+
if (!settings.hooks) settings.hooks = {};
|
|
170
|
+
let wired = 0;
|
|
171
|
+
let already = 0;
|
|
172
|
+
for (const { settingsKey, subcommand } of spec.events) {
|
|
173
|
+
const command = `bash ${agentHookPath} ${subcommand} --harness ${harness}`;
|
|
174
|
+
const groups = settings.hooks[settingsKey] ?? [];
|
|
175
|
+
const present = groups.some((g) =>
|
|
176
|
+
groupCommands(g).some((c) => c.includes(`agent-hook ${subcommand} `)),
|
|
177
|
+
);
|
|
178
|
+
if (present) {
|
|
179
|
+
already++;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
groups.push(makeEntry(spec.entryShape, command));
|
|
183
|
+
settings.hooks[settingsKey] = groups;
|
|
184
|
+
wired++;
|
|
185
|
+
}
|
|
186
|
+
return { wired, already };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Inverse of {@link wireHooks}: strip every harnery-owned hook entry from a
|
|
191
|
+
* settings object in place, idempotently. A hook is "harnery's" when its command
|
|
192
|
+
* contains `agent-hook ` (the trailing space matches `agent-hook <subcommand>`),
|
|
193
|
+
* so any non-harnery hook the consumer added is preserved. Emptied
|
|
194
|
+
* `hooks[settingsKey]` arrays are dropped; an emptied `hooks` object is dropped
|
|
195
|
+
* entirely. Harness-agnostic (scans every key) so it removes entries left by any
|
|
196
|
+
* harness. Pure (no fs) so it's unit-testable. Returns the count removed and the
|
|
197
|
+
* count of non-harnery hooks left behind.
|
|
198
|
+
*/
|
|
199
|
+
export function unwireHooks(settings: SettingsFile): { removed: number; remaining: number } {
|
|
200
|
+
if (!settings.hooks || typeof settings.hooks !== "object") return { removed: 0, remaining: 0 };
|
|
201
|
+
let removed = 0;
|
|
202
|
+
for (const key of Object.keys(settings.hooks)) {
|
|
203
|
+
const groups = settings.hooks[key];
|
|
204
|
+
if (!Array.isArray(groups)) continue;
|
|
205
|
+
const kept = groups.filter((g) => !groupCommands(g).some((c) => c.includes("agent-hook ")));
|
|
206
|
+
removed += groups.length - kept.length;
|
|
207
|
+
// removing the emptied hook key is the intent (tiny one-shot object)
|
|
208
|
+
if (kept.length === 0) delete settings.hooks[key];
|
|
209
|
+
else settings.hooks[key] = kept;
|
|
210
|
+
}
|
|
211
|
+
let remaining = 0;
|
|
212
|
+
for (const groups of Object.values(settings.hooks)) {
|
|
213
|
+
if (Array.isArray(groups)) remaining += groups.length;
|
|
214
|
+
}
|
|
215
|
+
// drop the now-empty hooks object so callers see a clean shape
|
|
216
|
+
if (Object.keys(settings.hooks).length === 0) delete settings.hooks;
|
|
217
|
+
return { removed, remaining };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** Build a hook entry in the harness's shape. */
|
|
221
|
+
function makeEntry(shape: HookEntryShape, command: string): HookGroup {
|
|
222
|
+
return shape === "cursor" ? { command } : { hooks: [{ type: "command", command }] };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Pull every command string out of a hook entry, regardless of shape. */
|
|
226
|
+
function groupCommands(group: HookGroup): string[] {
|
|
227
|
+
if ("command" in group && typeof group.command === "string") return [group.command];
|
|
228
|
+
if ("hooks" in group && Array.isArray(group.hooks)) {
|
|
229
|
+
return group.hooks.map((h) => h.command).filter((c): c is string => typeof c === "string");
|
|
230
|
+
}
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Idempotently record `binName` in `.harnery/config.jsonc`, preserving any
|
|
236
|
+
* existing JSONC comments and the `files` section. Returns an action line, or
|
|
237
|
+
* null when nothing changed. Three cases:
|
|
238
|
+
* - file absent → write a minimal commented stub;
|
|
239
|
+
* - `binName` already present + matching → no-op;
|
|
240
|
+
* - present-but-different value → comment-safe in-place value swap;
|
|
241
|
+
* - key absent → splice it in as the first key (comment-safe).
|
|
242
|
+
*/
|
|
243
|
+
export function stampBinName(configPath: string, binName: string, dryRun: boolean): string | null {
|
|
244
|
+
const rel = (p: string) => relative(dirname(dirname(configPath)), p) || p;
|
|
245
|
+
const quoted = JSON.stringify(binName);
|
|
246
|
+
|
|
247
|
+
if (!existsSync(configPath)) {
|
|
248
|
+
if (dryRun) return `+ would stamp binName "${binName}" into ${rel(configPath)}`;
|
|
249
|
+
writeFileSync(
|
|
250
|
+
configPath,
|
|
251
|
+
`{\n // Host CLI bin name, surfaced in agent-facing prompts + nudges.\n "binName": ${quoted}\n}\n`,
|
|
252
|
+
);
|
|
253
|
+
return `+ stamped binName "${binName}" into ${rel(configPath)}`;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
let raw: string;
|
|
257
|
+
try {
|
|
258
|
+
raw = readFileSync(configPath, "utf8");
|
|
259
|
+
} catch {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
let parsed: { binName?: unknown } & Record<string, unknown>;
|
|
263
|
+
try {
|
|
264
|
+
parsed = (JSON.parse(stripJsonComments(raw)) as typeof parsed) ?? {};
|
|
265
|
+
} catch {
|
|
266
|
+
// Unparseable config: don't clobber it; leave the bin name to env/manual fix.
|
|
267
|
+
return `· ${rel(configPath)} isn't valid JSONC; skipped binName stamp`;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (parsed.binName === binName) return null;
|
|
271
|
+
|
|
272
|
+
if (typeof parsed.binName === "string") {
|
|
273
|
+
// Existing value differs; swap it in place (keeps comments + layout).
|
|
274
|
+
const next = raw.replace(/("binName"\s*:\s*)"(?:[^"\\]|\\.)*"/, `$1${quoted}`);
|
|
275
|
+
if (dryRun) return `~ would update binName → "${binName}" in ${rel(configPath)}`;
|
|
276
|
+
writeFileSync(configPath, next);
|
|
277
|
+
return `~ updated binName → "${binName}" in ${rel(configPath)}`;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// No binName key yet; splice it as the first key.
|
|
281
|
+
const keys = Object.keys(parsed);
|
|
282
|
+
let next: string;
|
|
283
|
+
if (keys.length === 0) {
|
|
284
|
+
next = `{\n "binName": ${quoted}\n}\n`;
|
|
285
|
+
} else {
|
|
286
|
+
// Insert after the first structural `{` (skipping leading ws + comments).
|
|
287
|
+
const at = firstBraceIndex(raw);
|
|
288
|
+
if (at < 0) return `· ${rel(configPath)} has no object literal; skipped binName stamp`;
|
|
289
|
+
next = `${raw.slice(0, at + 1)}\n "binName": ${quoted},${raw.slice(at + 1)}`;
|
|
290
|
+
}
|
|
291
|
+
if (dryRun) return `+ would add binName "${binName}" to ${rel(configPath)}`;
|
|
292
|
+
writeFileSync(configPath, next);
|
|
293
|
+
return `+ added binName "${binName}" to ${rel(configPath)}`;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** Index of the first structural `{`, skipping leading whitespace + comments. */
|
|
297
|
+
function firstBraceIndex(raw: string): number {
|
|
298
|
+
let i = 0;
|
|
299
|
+
while (i < raw.length) {
|
|
300
|
+
const ch = raw[i];
|
|
301
|
+
if (ch === " " || ch === "\t" || ch === "\n" || ch === "\r") {
|
|
302
|
+
i++;
|
|
303
|
+
} else if (ch === "/" && raw[i + 1] === "/") {
|
|
304
|
+
while (i < raw.length && raw[i] !== "\n") i++;
|
|
305
|
+
} else if (ch === "/" && raw[i + 1] === "*") {
|
|
306
|
+
i += 2;
|
|
307
|
+
while (i < raw.length && !(raw[i] === "*" && raw[i + 1] === "/")) i++;
|
|
308
|
+
i += 2;
|
|
309
|
+
} else if (ch === "{") {
|
|
310
|
+
return i;
|
|
311
|
+
} else {
|
|
312
|
+
return -1;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return -1;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function render(projectRoot: string, dryRun: boolean, actions: string[]): string {
|
|
319
|
+
const head = dryRun ? "harn init (dry run): no changes written" : "harn init";
|
|
320
|
+
const tail = dryRun
|
|
321
|
+
? "\nRe-run without --dry-run to apply."
|
|
322
|
+
: "\nDone. Start a session and check `harn agents whoami`.";
|
|
323
|
+
return `${head}\n root: ${projectRoot}\n${actions.map((a) => ` ${a}`).join("\n")}${tail}`;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function gitTopLevel(): string | null {
|
|
327
|
+
const r = spawnSync("git", ["rev-parse", "--show-toplevel"], { encoding: "utf8" });
|
|
328
|
+
const out = r.status === 0 ? r.stdout.trim() : "";
|
|
329
|
+
return out || null;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function rel(root: string, p: string): string {
|
|
333
|
+
const r = relative(root, p);
|
|
334
|
+
return r || p;
|
|
335
|
+
}
|