@cluesmith/codev 3.2.4 → 3.3.1
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/dashboard-dist/assets/index-BZRTEMtH.css +32 -0
- package/dashboard-dist/assets/{index-BZ1x7x1X.js → index-D3XaKpZW.js} +46 -44
- package/dashboard-dist/assets/index-D3XaKpZW.js.map +1 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +154 -0
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/cleanup.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.js +16 -0
- package/dist/agent-farm/commands/cleanup.js.map +1 -1
- package/dist/agent-farm/commands/inbox.d.ts +42 -0
- package/dist/agent-farm/commands/inbox.d.ts.map +1 -0
- package/dist/agent-farm/commands/inbox.js +129 -0
- package/dist/agent-farm/commands/inbox.js.map +1 -0
- package/dist/agent-farm/commands/interrupt.d.ts +20 -0
- package/dist/agent-farm/commands/interrupt.d.ts.map +1 -0
- package/dist/agent-farm/commands/interrupt.js +65 -0
- package/dist/agent-farm/commands/interrupt.js.map +1 -0
- package/dist/agent-farm/commands/reset/constants.d.ts +52 -0
- package/dist/agent-farm/commands/reset/constants.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/constants.js +52 -0
- package/dist/agent-farm/commands/reset/constants.js.map +1 -0
- package/dist/agent-farm/commands/reset/context.d.ts +230 -0
- package/dist/agent-farm/commands/reset/context.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/context.js +428 -0
- package/dist/agent-farm/commands/reset/context.js.map +1 -0
- package/dist/agent-farm/commands/reset/index.d.ts +192 -0
- package/dist/agent-farm/commands/reset/index.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/index.js +488 -0
- package/dist/agent-farm/commands/reset/index.js.map +1 -0
- package/dist/agent-farm/commands/reset/receipt.d.ts +97 -0
- package/dist/agent-farm/commands/reset/receipt.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/receipt.js +149 -0
- package/dist/agent-farm/commands/reset/receipt.js.map +1 -0
- package/dist/agent-farm/commands/reset/reorient.d.ts +117 -0
- package/dist/agent-farm/commands/reset/reorient.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/reorient.js +313 -0
- package/dist/agent-farm/commands/reset/reorient.js.map +1 -0
- package/dist/agent-farm/commands/reset.d.ts +34 -0
- package/dist/agent-farm/commands/reset.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset.js +309 -0
- package/dist/agent-farm/commands/reset.js.map +1 -0
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +49 -8
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts +105 -6
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +289 -66
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +13 -1
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/commands/status.d.ts.map +1 -1
- package/dist/agent-farm/commands/status.js +80 -8
- package/dist/agent-farm/commands/status.js.map +1 -1
- package/dist/agent-farm/commands/tower.d.ts.map +1 -1
- package/dist/agent-farm/commands/tower.js +13 -0
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/db/index.d.ts +1 -1
- package/dist/agent-farm/db/index.d.ts.map +1 -1
- package/dist/agent-farm/db/index.js +80 -1
- package/dist/agent-farm/db/index.js.map +1 -1
- package/dist/agent-farm/db/mailbox.d.ts +222 -0
- package/dist/agent-farm/db/mailbox.d.ts.map +1 -0
- package/dist/agent-farm/db/mailbox.js +304 -0
- package/dist/agent-farm/db/mailbox.js.map +1 -0
- package/dist/agent-farm/db/schema.d.ts +1 -1
- package/dist/agent-farm/db/schema.d.ts.map +1 -1
- package/dist/agent-farm/db/schema.js +35 -0
- package/dist/agent-farm/db/schema.js.map +1 -1
- package/dist/agent-farm/db/types.d.ts +45 -0
- package/dist/agent-farm/db/types.d.ts.map +1 -1
- package/dist/agent-farm/db/types.js.map +1 -1
- package/dist/agent-farm/lib/builder-lookup.d.ts +1 -1
- package/dist/agent-farm/lib/builder-lookup.js +2 -2
- package/dist/agent-farm/lib/builder-lookup.js.map +1 -1
- package/dist/agent-farm/lib/reconnect-backoff.d.ts +64 -0
- package/dist/agent-farm/lib/reconnect-backoff.d.ts.map +1 -0
- package/dist/agent-farm/lib/reconnect-backoff.js +57 -0
- package/dist/agent-farm/lib/reconnect-backoff.js.map +1 -0
- package/dist/agent-farm/lib/tower-client.d.ts +16 -6
- package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tower-client.js +37 -6
- package/dist/agent-farm/lib/tower-client.js.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts +69 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +225 -30
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/canvas-relay.d.ts +60 -0
- package/dist/agent-farm/servers/canvas-relay.d.ts.map +1 -0
- package/dist/agent-farm/servers/canvas-relay.js +376 -0
- package/dist/agent-farm/servers/canvas-relay.js.map +1 -0
- package/dist/agent-farm/servers/cron-delivery.d.ts +72 -0
- package/dist/agent-farm/servers/cron-delivery.d.ts.map +1 -0
- package/dist/agent-farm/servers/cron-delivery.js +80 -0
- package/dist/agent-farm/servers/cron-delivery.js.map +1 -0
- package/dist/agent-farm/servers/delayed-send.d.ts +85 -0
- package/dist/agent-farm/servers/delayed-send.d.ts.map +1 -0
- package/dist/agent-farm/servers/delayed-send.js +165 -0
- package/dist/agent-farm/servers/delayed-send.js.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts +67 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.js +113 -0
- package/dist/agent-farm/servers/gate-profiles.js.map +1 -0
- package/dist/agent-farm/servers/mailbox-delivery.d.ts +370 -0
- package/dist/agent-farm/servers/mailbox-delivery.d.ts.map +1 -0
- package/dist/agent-farm/servers/mailbox-delivery.js +617 -0
- package/dist/agent-farm/servers/mailbox-delivery.js.map +1 -0
- package/dist/agent-farm/servers/mailbox-wiring.d.ts +125 -0
- package/dist/agent-farm/servers/mailbox-wiring.d.ts.map +1 -0
- package/dist/agent-farm/servers/mailbox-wiring.js +425 -0
- package/dist/agent-farm/servers/mailbox-wiring.js.map +1 -0
- package/dist/agent-farm/servers/message-write.d.ts +53 -1
- package/dist/agent-farm/servers/message-write.d.ts.map +1 -1
- package/dist/agent-farm/servers/message-write.js +63 -0
- package/dist/agent-farm/servers/message-write.js.map +1 -1
- package/dist/agent-farm/servers/overview.d.ts +19 -0
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +100 -4
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/render-gate.d.ts +141 -0
- package/dist/agent-farm/servers/render-gate.d.ts.map +1 -0
- package/dist/agent-farm/servers/render-gate.js +251 -0
- package/dist/agent-farm/servers/render-gate.js.map +1 -0
- package/dist/agent-farm/servers/session-submit.d.ts +90 -0
- package/dist/agent-farm/servers/session-submit.d.ts.map +1 -0
- package/dist/agent-farm/servers/session-submit.js +127 -0
- package/dist/agent-farm/servers/session-submit.js.map +1 -0
- package/dist/agent-farm/servers/tower-cron.d.ts +10 -7
- package/dist/agent-farm/servers/tower-cron.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-cron.js +58 -53
- package/dist/agent-farm/servers/tower-cron.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts +14 -2
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +78 -16
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-messages.d.ts +38 -1
- package/dist/agent-farm/servers/tower-messages.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-messages.js +106 -1
- package/dist/agent-farm/servers/tower-messages.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts +16 -4
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +826 -145
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +188 -34
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +23 -2
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +134 -127
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.js +63 -4
- package/dist/agent-farm/servers/tower-tunnel.js.map +1 -1
- package/dist/agent-farm/servers/tower-types.d.ts +2 -1
- package/dist/agent-farm/servers/tower-types.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.d.ts +64 -1
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.js +168 -1
- package/dist/agent-farm/servers/tower-utils.js.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts +6 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.js +95 -57
- package/dist/agent-farm/servers/tower-websocket.js.map +1 -1
- package/dist/agent-farm/servers/write-queue.d.ts +35 -0
- package/dist/agent-farm/servers/write-queue.d.ts.map +1 -0
- package/dist/agent-farm/servers/write-queue.js +56 -0
- package/dist/agent-farm/servers/write-queue.js.map +1 -0
- package/dist/agent-farm/types.d.ts +39 -0
- package/dist/agent-farm/types.d.ts.map +1 -1
- package/dist/agent-farm/utils/agent-names.d.ts +2 -2
- package/dist/agent-farm/utils/agent-names.d.ts.map +1 -1
- package/dist/agent-farm/utils/agent-names.js +3 -3
- package/dist/agent-farm/utils/agent-names.js.map +1 -1
- package/dist/agent-farm/utils/architect-name.d.ts +2 -2
- package/dist/agent-farm/utils/architect-name.d.ts.map +1 -1
- package/dist/agent-farm/utils/architect-name.js +3 -3
- package/dist/agent-farm/utils/architect-name.js.map +1 -1
- package/dist/agent-farm/utils/config.d.ts +13 -0
- package/dist/agent-farm/utils/config.d.ts.map +1 -1
- package/dist/agent-farm/utils/config.js +33 -1
- package/dist/agent-farm/utils/config.js.map +1 -1
- package/dist/agent-farm/utils/harness.d.ts +103 -7
- package/dist/agent-farm/utils/harness.d.ts.map +1 -1
- package/dist/agent-farm/utils/harness.js +126 -19
- package/dist/agent-farm/utils/harness.js.map +1 -1
- package/dist/agent-farm/utils/message-format.d.ts +8 -0
- package/dist/agent-farm/utils/message-format.d.ts.map +1 -1
- package/dist/agent-farm/utils/message-format.js +20 -0
- package/dist/agent-farm/utils/message-format.js.map +1 -1
- package/dist/agent-farm/utils/server-utils.d.ts +80 -4
- package/dist/agent-farm/utils/server-utils.d.ts.map +1 -1
- package/dist/agent-farm/utils/server-utils.js +286 -5
- package/dist/agent-farm/utils/server-utils.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -32
- package/dist/cli.js.map +1 -1
- package/dist/commands/consult/cli-options.d.ts +34 -0
- package/dist/commands/consult/cli-options.d.ts.map +1 -0
- package/dist/commands/consult/cli-options.js +67 -0
- package/dist/commands/consult/cli-options.js.map +1 -0
- package/dist/commands/consult/index.d.ts +56 -2
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +272 -28
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/consult/metrics.d.ts +42 -0
- package/dist/commands/consult/metrics.d.ts.map +1 -1
- package/dist/commands/consult/metrics.js +129 -9
- package/dist/commands/consult/metrics.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +71 -19
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/porch/checks.d.ts +23 -0
- package/dist/commands/porch/checks.d.ts.map +1 -1
- package/dist/commands/porch/checks.js +60 -0
- package/dist/commands/porch/checks.js.map +1 -1
- package/dist/commands/porch/config.d.ts +20 -0
- package/dist/commands/porch/config.d.ts.map +1 -1
- package/dist/commands/porch/config.js +20 -0
- package/dist/commands/porch/config.js.map +1 -1
- package/dist/commands/porch/index.js +21 -28
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/next.d.ts.map +1 -1
- package/dist/commands/porch/next.js +2 -41
- package/dist/commands/porch/next.js.map +1 -1
- package/dist/lib/config.d.ts +69 -3
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +67 -3
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/consult-lanes.d.ts +149 -0
- package/dist/lib/consult-lanes.d.ts.map +1 -0
- package/dist/lib/consult-lanes.js +360 -0
- package/dist/lib/consult-lanes.js.map +1 -0
- package/dist/lib/forge-contracts.d.ts +9 -0
- package/dist/lib/forge-contracts.d.ts.map +1 -1
- package/dist/lib/forge-contracts.js.map +1 -1
- package/dist/lib/github.d.ts +15 -1
- package/dist/lib/github.d.ts.map +1 -1
- package/dist/lib/github.js +18 -1
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/prompt-behavior-metrics.d.ts +67 -0
- package/dist/lib/prompt-behavior-metrics.d.ts.map +1 -0
- package/dist/lib/prompt-behavior-metrics.js +290 -0
- package/dist/lib/prompt-behavior-metrics.js.map +1 -0
- package/dist/lib/skeleton.d.ts +22 -1
- package/dist/lib/skeleton.d.ts.map +1 -1
- package/dist/lib/skeleton.js +120 -0
- package/dist/lib/skeleton.js.map +1 -1
- package/dist/lib/test-env.d.ts +74 -0
- package/dist/lib/test-env.d.ts.map +1 -0
- package/dist/lib/test-env.js +92 -0
- package/dist/lib/test-env.js.map +1 -0
- package/dist/terminal/attach-replay.d.ts +39 -0
- package/dist/terminal/attach-replay.d.ts.map +1 -0
- package/dist/terminal/attach-replay.js +76 -0
- package/dist/terminal/attach-replay.js.map +1 -0
- package/dist/terminal/pty-manager.d.ts +2 -0
- package/dist/terminal/pty-manager.d.ts.map +1 -1
- package/dist/terminal/pty-manager.js +51 -23
- package/dist/terminal/pty-manager.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +201 -1
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +327 -46
- package/dist/terminal/pty-session.js.map +1 -1
- package/dist/terminal/ring-buffer.d.ts +39 -6
- package/dist/terminal/ring-buffer.d.ts.map +1 -1
- package/dist/terminal/ring-buffer.js +74 -6
- package/dist/terminal/ring-buffer.js.map +1 -1
- package/dist/terminal/session-manager.d.ts +53 -0
- package/dist/terminal/session-manager.d.ts.map +1 -1
- package/dist/terminal/session-manager.js +94 -9
- package/dist/terminal/session-manager.js.map +1 -1
- package/dist/terminal/session-screen.d.ts +116 -0
- package/dist/terminal/session-screen.d.ts.map +1 -0
- package/dist/terminal/session-screen.js +180 -0
- package/dist/terminal/session-screen.js.map +1 -0
- package/dist/terminal/shellper-main.js +2 -1
- package/dist/terminal/shellper-main.js.map +1 -1
- package/dist/terminal/shellper-process.d.ts +1 -1
- package/dist/terminal/shellper-process.d.ts.map +1 -1
- package/dist/terminal/shellper-process.js +17 -8
- package/dist/terminal/shellper-process.js.map +1 -1
- package/dist/terminal/shellper-replay-buffer.d.ts +69 -7
- package/dist/terminal/shellper-replay-buffer.d.ts.map +1 -1
- package/dist/terminal/shellper-replay-buffer.js +167 -31
- package/dist/terminal/shellper-replay-buffer.js.map +1 -1
- package/package.json +13 -8
- package/scripts/forge/gitea/pr-view.sh +4 -1
- package/scripts/forge/github/pr-view.sh +1 -1
- package/scripts/forge/gitlab/pr-view.sh +4 -1
- package/skeleton/.claude/skills/afx/SKILL.md +68 -1
- package/skeleton/.claude/skills/arch-init/SKILL.md +22 -9
- package/skeleton/.claude/skills/arch-save/SKILL.md +183 -0
- package/skeleton/.claude/skills/codev/SKILL.md +31 -0
- package/skeleton/.claude/skills/runnable-worktrees/SKILL.md +119 -0
- package/skeleton/.codex/skills/afx/SKILL.md +68 -1
- package/skeleton/.codex/skills/arch-init/SKILL.md +22 -9
- package/skeleton/.codex/skills/arch-save/SKILL.md +183 -0
- package/skeleton/.codex/skills/codev/SKILL.md +31 -0
- package/skeleton/.codex/skills/runnable-worktrees/SKILL.md +119 -0
- package/skeleton/protocols/air/builder-prompt.md +28 -47
- package/skeleton/protocols/air/consult-types/impl-review.md +17 -34
- package/skeleton/protocols/air/consult-types/pr-review.md +14 -37
- package/skeleton/protocols/air/prompts/implement.md +20 -73
- package/skeleton/protocols/air/prompts/pr.md +22 -54
- package/skeleton/protocols/air/protocol.md +40 -71
- package/skeleton/protocols/aspir/builder-prompt.md +29 -66
- package/skeleton/protocols/aspir/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/aspir/consult-types/phase-review.md +17 -44
- package/skeleton/protocols/aspir/consult-types/plan-review.md +14 -38
- package/skeleton/protocols/aspir/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/aspir/consult-types/spec-review.md +13 -33
- package/skeleton/protocols/aspir/prompts/implement.md +27 -196
- package/skeleton/protocols/aspir/prompts/plan.md +21 -85
- package/skeleton/protocols/aspir/prompts/review.md +29 -228
- package/skeleton/protocols/aspir/prompts/specify.md +25 -111
- package/skeleton/protocols/aspir/protocol.json +10 -0
- package/skeleton/protocols/aspir/protocol.md +36 -82
- package/skeleton/protocols/bugfix/builder-prompt.md +23 -45
- package/skeleton/protocols/bugfix/consult-types/impl-review.md +21 -45
- package/skeleton/protocols/bugfix/consult-types/pr-review.md +18 -52
- package/skeleton/protocols/bugfix/prompts/fix.md +16 -61
- package/skeleton/protocols/bugfix/prompts/investigate.md +18 -62
- package/skeleton/protocols/bugfix/prompts/pr.md +22 -57
- package/skeleton/protocols/bugfix/protocol.md +44 -50
- package/skeleton/protocols/experiment/builder-prompt.md +25 -58
- package/skeleton/protocols/experiment/protocol.md +22 -188
- package/skeleton/protocols/experiment/templates/notes.md +11 -71
- package/skeleton/protocols/maintain/builder-prompt.md +24 -45
- package/skeleton/protocols/maintain/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/maintain/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/maintain/prompts/maintain.md +1 -1
- package/skeleton/protocols/maintain/protocol.md +32 -266
- package/skeleton/protocols/maintain/templates/maintenance-run.md +11 -0
- package/skeleton/protocols/pir/builder-prompt.md +31 -64
- package/skeleton/protocols/pir/consult-types/impl-review.md +17 -50
- package/skeleton/protocols/pir/consult-types/pr-review.md +11 -40
- package/skeleton/protocols/pir/prompts/implement.md +2 -3
- package/skeleton/protocols/pir/prompts/plan.md +1 -4
- package/skeleton/protocols/pir/prompts/review.md +2 -2
- package/skeleton/protocols/pir/protocol.md +54 -177
- package/skeleton/protocols/research/builder-prompt.md +27 -58
- package/skeleton/protocols/research/protocol.md +28 -153
- package/skeleton/protocols/spike/builder-prompt.md +30 -48
- package/skeleton/protocols/spike/protocol.md +24 -107
- package/skeleton/protocols/spike/templates/findings.md +9 -39
- package/skeleton/protocols/spir/builder-prompt.md +33 -62
- package/skeleton/protocols/spir/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/spir/consult-types/phase-review.md +17 -44
- package/skeleton/protocols/spir/consult-types/plan-review.md +14 -38
- package/skeleton/protocols/spir/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/spir/consult-types/spec-review.md +13 -33
- package/skeleton/protocols/spir/prompts/implement.md +26 -195
- package/skeleton/protocols/spir/prompts/plan.md +20 -84
- package/skeleton/protocols/spir/prompts/review.md +28 -227
- package/skeleton/protocols/spir/prompts/specify.md +24 -110
- package/skeleton/protocols/spir/protocol.json +10 -0
- package/skeleton/protocols/spir/protocol.md +84 -633
- package/skeleton/protocols/spir/templates/plan.md +28 -147
- package/skeleton/protocols/spir/templates/review.md +21 -80
- package/skeleton/protocols/spir/templates/spec.md +24 -118
- package/skeleton/resources/commands/agent-farm.md +262 -0
- package/skeleton/resources/commands/consult.md +236 -8
- package/skeleton/resources/commands/overview.md +1 -0
- package/skeleton/roles/architect.md +67 -317
- package/skeleton/roles/builder.md +76 -191
- package/skeleton/templates/AGENTS.md +2 -0
- package/skeleton/templates/CLAUDE.md +2 -0
- package/templates/3d-viewer.html +32 -4
- package/templates/open.html +58 -12
- package/templates/tower.html +65 -9
- package/templates/vendor/three-3MFLoader.js +1478 -0
- package/templates/vendor/three-STLLoader.js +410 -0
- package/templates/vendor/three-TrackballControls.js +828 -0
- package/templates/vendor/three-fflate.module.js +2474 -0
- package/templates/vendor/three.module.js +53044 -0
- package/dashboard-dist/assets/index-BZ1x7x1X.js.map +0 -1
- package/dashboard-dist/assets/index-DB1KBSNE.css +0 -32
- package/dist/agent-farm/servers/send-buffer.d.ts +0 -59
- package/dist/agent-farm/servers/send-buffer.d.ts.map +0 -1
- package/dist/agent-farm/servers/send-buffer.js +0 -116
- package/dist/agent-farm/servers/send-buffer.js.map +0 -1
- package/skeleton/porch/prompts/defend.md +0 -108
- package/skeleton/porch/prompts/diagnose.md +0 -70
- package/skeleton/porch/prompts/evaluate.md +0 -132
- package/skeleton/porch/prompts/fix.md +0 -59
- package/skeleton/porch/prompts/implement.md +0 -88
- package/skeleton/porch/prompts/plan.md +0 -74
- package/skeleton/porch/prompts/pr.md +0 -84
- package/skeleton/porch/prompts/review.md +0 -249
- package/skeleton/porch/prompts/specify.md +0 -53
- package/skeleton/porch/prompts/test.md +0 -63
- package/skeleton/protocols/aspir/templates/plan.md +0 -184
- package/skeleton/protocols/aspir/templates/review.md +0 -120
- package/skeleton/protocols/aspir/templates/spec.md +0 -154
|
@@ -1,232 +1,117 @@
|
|
|
1
1
|
# Role: Builder
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
You implement one project in an isolated git worktree, and you own it end to end: artifacts,
|
|
4
|
+
code, tests, PR.
|
|
4
5
|
|
|
5
|
-
## Two
|
|
6
|
+
## Two modes
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
| Mode | How you know | How you work |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| **Strict** (default) | spawned without `--soft` | Porch orchestrates. `porch next` gives you tasks; `porch done` signals completion. |
|
|
11
|
+
| **Soft** | spawned with `--soft` | You follow the protocol yourself; the architect verifies compliance. |
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
| **Strict** (default) | `afx spawn XXXX` | Porch orchestrates - runs autonomously to completion |
|
|
12
|
-
| **Soft** | `afx spawn XXXX --soft` | AI follows protocol - architect verifies compliance |
|
|
13
|
+
In strict mode porch drives the loop — run it, do the work it hands you, run it again. Do not
|
|
14
|
+
hand-run consultations it would run, advance plan phases yourself, or skip the 3-way review.
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
Never hand-edit `status.yaml` — only porch commands modify project state.
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
## Gates
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
Porch stops at human approval gates (`spec-approval`, `plan-approval`, `pr`). When it does:
|
|
21
|
+
say so, **stop**, and wait.
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
Never treat a porch gate as approved without an explicit human decision — a gate message is a notification to the human, not authorization.
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
porch
|
|
25
|
-
|
|
26
|
-
# 2. Run the protocol loop
|
|
27
|
-
porch run
|
|
28
|
-
|
|
29
|
-
# 3. If porch hits a gate, STOP and wait for human approval
|
|
30
|
-
# 4. After gate approval, run porch again
|
|
31
|
-
# 5. Repeat until project is complete
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Porch handles:
|
|
35
|
-
- Spawning Claude to create artifacts (spec, plan, code)
|
|
36
|
-
- Running 3-way consultations (Gemini, Codex, Claude)
|
|
37
|
-
- Iterating based on feedback
|
|
38
|
-
- Enforcing phase transitions
|
|
39
|
-
|
|
40
|
-
### Gates: When to STOP
|
|
41
|
-
|
|
42
|
-
Porch has two human approval gates:
|
|
43
|
-
|
|
44
|
-
| Gate | When | What to do |
|
|
45
|
-
|------|------|------------|
|
|
46
|
-
| `spec-approval` | After spec is written | **STOP** and wait |
|
|
47
|
-
| `plan-approval` | After plan is written | **STOP** and wait |
|
|
48
|
-
|
|
49
|
-
When porch outputs:
|
|
50
|
-
```
|
|
51
|
-
GATE: spec-approval
|
|
52
|
-
Human approval required. STOP and wait.
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
You must:
|
|
56
|
-
1. Output a clear message: "Spec ready for approval. Waiting for human."
|
|
57
|
-
2. **STOP working**
|
|
58
|
-
3. Wait for the human to run `porch approve XXXX spec-approval`
|
|
59
|
-
4. After approval, run `porch run` again
|
|
60
|
-
|
|
61
|
-
### What You DON'T Do in Strict Mode
|
|
62
|
-
|
|
63
|
-
- **Don't manually follow SPIR steps** - Porch handles this
|
|
64
|
-
- **Don't run consult directly** - Porch runs 3-way reviews
|
|
65
|
-
- **Don't edit status.yaml phase/iteration** - Only porch modifies state
|
|
66
|
-
- **Don't call porch approve** - Only humans approve gates
|
|
67
|
-
- **Don't skip gates** - Always stop and wait for approval
|
|
68
|
-
|
|
69
|
-
## Soft Mode
|
|
70
|
-
|
|
71
|
-
Spawned with: `afx spawn XXXX --soft` or `afx spawn --task "..."`
|
|
72
|
-
|
|
73
|
-
In soft mode, you follow the protocol document yourself. The architect monitors your work and verifies you're adhering to the protocol correctly.
|
|
74
|
-
|
|
75
|
-
### Startup Sequence
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
# Read the spec and/or plan
|
|
79
|
-
cat codev/specs/XXXX-*.md
|
|
80
|
-
cat codev/plans/XXXX-*.md
|
|
81
|
-
|
|
82
|
-
# (The full protocol text is inlined in your spawn prompt under the
|
|
83
|
-
# "## Protocol Reference (full text)" heading; no need to fetch it.)
|
|
84
|
-
|
|
85
|
-
# Start implementing
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### The SPIR Protocol (Specify → Plan → Implement → Review (→ Verify))
|
|
89
|
-
|
|
90
|
-
1. **Specify**: Read or create the spec at `codev/specs/XXXX-name.md`
|
|
91
|
-
2. **Plan**: Read or create the plan at `codev/plans/XXXX-name.md`
|
|
92
|
-
3. **Implement**: Write code following the plan phases
|
|
93
|
-
4. **Review**: Write lessons learned and create PR
|
|
94
|
-
5. **Verify** (optional): After PR merge, verify the feature works in the integrated codebase
|
|
95
|
-
|
|
96
|
-
### Consultations
|
|
97
|
-
|
|
98
|
-
Run 3-way consultations at checkpoints:
|
|
99
|
-
```bash
|
|
100
|
-
# After writing spec
|
|
101
|
-
consult -m gemini --protocol spir --type spec &
|
|
102
|
-
consult -m codex --protocol spir --type spec &
|
|
103
|
-
consult -m claude --protocol spir --type spec &
|
|
104
|
-
wait
|
|
105
|
-
|
|
106
|
-
# After writing plan
|
|
107
|
-
consult -m gemini --protocol spir --type plan &
|
|
108
|
-
consult -m codex --protocol spir --type plan &
|
|
109
|
-
consult -m claude --protocol spir --type plan &
|
|
110
|
-
wait
|
|
111
|
-
|
|
112
|
-
# After implementation
|
|
113
|
-
consult -m gemini --protocol spir --type pr &
|
|
114
|
-
consult -m codex --protocol spir --type pr &
|
|
115
|
-
consult -m claude --protocol spir --type pr &
|
|
116
|
-
wait
|
|
117
|
-
```
|
|
25
|
+
Approval reaches you as a message from the architect. Then *you* run
|
|
26
|
+
`porch approve <id> <gate>`; the architect does not run it for you. Defer to your protocol's phase
|
|
27
|
+
prompts on who types `porch approve`.
|
|
118
28
|
|
|
119
29
|
## Deliverables
|
|
120
30
|
|
|
121
|
-
|
|
122
|
-
- Plan at `codev/plans/XXXX-name.md`
|
|
123
|
-
- Review at `codev/reviews/XXXX-name.md`
|
|
124
|
-
- Implementation code with tests
|
|
125
|
-
- PR ready for architect review
|
|
126
|
-
|
|
127
|
-
## Communication
|
|
31
|
+
Same base filename in three directories, plus code and tests:
|
|
128
32
|
|
|
129
|
-
### With the Architect
|
|
130
|
-
|
|
131
|
-
If you're blocked or need help:
|
|
132
|
-
```bash
|
|
133
|
-
afx send architect "Question about the spec..."
|
|
134
33
|
```
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
```bash
|
|
139
|
-
porch status # (strict mode) Your project status
|
|
140
|
-
afx status # All builders
|
|
34
|
+
codev/specs/<id>-<name>.md what and why
|
|
35
|
+
codev/plans/<id>-<name>.md how and in what order
|
|
36
|
+
codev/reviews/<id>-<name>.md what was learned
|
|
141
37
|
```
|
|
142
38
|
|
|
143
|
-
##
|
|
39
|
+
## Your thread
|
|
144
40
|
|
|
145
|
-
|
|
41
|
+
Keep a free-text log at `codev/state/<builder-id>_thread.md` — the cohort's shared situational
|
|
42
|
+
awareness, readable by architects and sibling builders. `<builder-id>` is `basename "$(pwd)"`.
|
|
43
|
+
Write at phase boundaries and whenever a future reader would want to know what happened:
|
|
44
|
+
decisions, blockers, surprises. No schema, no cadence requirement.
|
|
146
45
|
|
|
147
|
-
**
|
|
46
|
+
**Commit it with your PR.** Leaving it uncommitted by accident is a bug, not a choice.
|
|
148
47
|
|
|
149
|
-
|
|
48
|
+
## Telling the architect things
|
|
150
49
|
|
|
151
|
-
|
|
50
|
+
They are not watching. Send a message at each of these:
|
|
152
51
|
|
|
153
|
-
|
|
52
|
+
| When | What |
|
|
53
|
+
|---|---|
|
|
54
|
+
| Gate reached | `afx send architect "Project <id>: <gate> ready for approval"` |
|
|
55
|
+
| PR ready | `afx send architect "PR #N ready for review"` |
|
|
56
|
+
| PR merged | `afx send architect "Project <id> complete. Entering verify phase."` |
|
|
57
|
+
| Blocked | `afx send architect "Blocked on X — need guidance"` |
|
|
154
58
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
- **Sibling builders**: read each other's threads via `cat ../<sibling-id>/codev/state/<sibling-id>_thread.md` from your own worktree (the parent `.builders/` directory is shared between all builders in the workspace).
|
|
158
|
-
- **Post-merge**: after your PR merges, your thread lands in `codev/state/` on `main` (parallel to `codev/reviews/`) and becomes part of the historical review record.
|
|
59
|
+
When blocked, state the problem and the options you see, then wait. Don't guess past a decision
|
|
60
|
+
that isn't yours.
|
|
159
61
|
|
|
160
|
-
|
|
62
|
+
## Waiting on external work
|
|
161
63
|
|
|
162
|
-
**
|
|
64
|
+
**A wait is a claim that a producer exists.** Before waiting on a file, a build, or a sibling's
|
|
65
|
+
output, confirm the process meant to produce it is alive. A builder once waited 45 minutes on a
|
|
66
|
+
file whose producer had already died — that wait was not slow, it was unsatisfiable.
|
|
163
67
|
|
|
164
|
-
|
|
68
|
+
**Run waits as background tasks that end your turn.** Every message sent to you — including an
|
|
69
|
+
order to stop — queues unread until your current turn ends. A turn that never ends is a builder
|
|
70
|
+
nobody can redirect, and you will not notice, because from inside it everything looks fine.
|
|
71
|
+
Never chain foreground poll loops.
|
|
165
72
|
|
|
166
|
-
|
|
73
|
+
If you are wedged anyway, the architect can end your turn with `afx interrupt <your-id>`, or
|
|
74
|
+
`afx refresh <your-id>` to have you save state and re-orient. Worth knowing so you can suggest
|
|
75
|
+
them.
|
|
167
76
|
|
|
168
|
-
|
|
169
|
-
|------|-------------|
|
|
170
|
-
| **Gate reached** | `afx send architect "Project XXXX: <gate-name> ready for approval"` |
|
|
171
|
-
| **PR ready** | `afx send architect "PR #N ready for review"` |
|
|
172
|
-
| **PR merged** | `afx send architect "Project XXXX complete. PR merged. Entering verify phase."` |
|
|
173
|
-
| **Blocked/stuck** | `afx send architect "Blocked on X — need guidance"` |
|
|
174
|
-
| **Escalation needed** | `afx send architect "Issue too complex — recommend escalating to SPIR"` |
|
|
77
|
+
## PRs
|
|
175
78
|
|
|
176
|
-
|
|
79
|
+
Plan phases are **git commits inside one PR**, not a PR each. Open the PR during or after the
|
|
80
|
+
final phase unless the architect asks for one earlier — they may, to review a slice or get
|
|
81
|
+
feedback mid-flight. Record them with `porch done <id> --pr <N> --branch <name>` and
|
|
82
|
+
`porch done <id> --merged <N>`.
|
|
177
83
|
|
|
178
|
-
|
|
84
|
+
For sequential PRs, branch from the integration branch without checking it out — a worktree
|
|
85
|
+
cannot check out a branch that is checked out elsewhere:
|
|
179
86
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
1. **Output a clear blocker message** describing the problem and options
|
|
183
|
-
2. **Use `afx send architect "..."` to notify the Architect**
|
|
184
|
-
3. **Wait for guidance** before proceeding
|
|
185
|
-
|
|
186
|
-
Example:
|
|
187
|
-
```
|
|
188
|
-
## BLOCKED: Spec 0077
|
|
189
|
-
Can't find the auth helper mentioned in spec. Options:
|
|
190
|
-
1. Create a new auth helper
|
|
191
|
-
2. Use a third-party library
|
|
192
|
-
3. Spec needs clarification
|
|
193
|
-
Waiting for Architect guidance.
|
|
87
|
+
```bash
|
|
88
|
+
git fetch origin main && git checkout -b <next-branch> origin/main
|
|
194
89
|
```
|
|
195
90
|
|
|
196
|
-
##
|
|
91
|
+
## Worktree discipline
|
|
197
92
|
|
|
198
|
-
|
|
93
|
+
Your worktree is nested inside the main checkout and, at the branch base, byte-identical to it.
|
|
94
|
+
So a path that drops the `.builders/<id>/` segment silently reads and writes **main's** copy —
|
|
95
|
+
reads succeed, writes succeed, and nothing corrects you until a later `git add` fails.
|
|
199
96
|
|
|
200
|
-
-
|
|
201
|
-
|
|
97
|
+
- Absolute paths for file writes must be rooted at your worktree. A guard blocks writes outside
|
|
98
|
+
it; if you see that denial, re-root the path.
|
|
99
|
+
- In Bash, prefer relative paths — `cwd` is your worktree, so a relative path cannot be anchored
|
|
100
|
+
to the wrong root.
|
|
202
101
|
|
|
203
|
-
##
|
|
102
|
+
## Scope
|
|
204
103
|
|
|
205
|
-
|
|
206
|
-
|
|
104
|
+
Build what the spec says. If part of it is blocked, finish everything else and say plainly what
|
|
105
|
+
you left out and why — scaling the work down is the architect's call.
|
|
207
106
|
|
|
208
|
-
-
|
|
209
|
-
at the canonical repo root instead of your worktree, you drop the `.builders/<id>/`
|
|
210
|
-
segment and write into the **main checkout** — a real, writable directory. The
|
|
211
|
-
write *succeeds silently* and pollutes `main`; you only notice later when a
|
|
212
|
-
`git add` in your worktree fails with a pathspec error.
|
|
213
|
-
- Wrong-rooted **reads** also succeed silently (identical trees), so nothing
|
|
214
|
-
corrects the mistake until that first failed write.
|
|
107
|
+
Never `git add -A` / `--all` / `.` — stage each file explicitly by path.
|
|
215
108
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
`~/.claude`); if you see that denial, re-root the path under your worktree.
|
|
220
|
-
- **Bash `cwd` is your worktree — prefer relative paths there.** A relative path
|
|
221
|
-
cannot be anchored to the wrong root, which closes the Bash write surface
|
|
222
|
-
(`>`, `cp`, `tee`, `sed -i`) the Write/Edit guard does not cover.
|
|
109
|
+
If the issue carries a **Baked Decisions** section, those are fixed. Don't relitigate them in
|
|
110
|
+
your spec, plan, or implementation; if one looks seriously wrong, raise it with `afx send`. If
|
|
111
|
+
two contradict each other, don't pick — flag the contradiction and wait.
|
|
223
112
|
|
|
224
|
-
##
|
|
113
|
+
## Flaky tests
|
|
225
114
|
|
|
226
|
-
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
- **(Strict mode)** Run porch, don't bypass it
|
|
230
|
-
- **(Strict mode)** Stop at gates - Human approval is required
|
|
231
|
-
- **(Strict mode)** NEVER edit status.yaml directly
|
|
232
|
-
- **(Strict mode)** NEVER call porch approve
|
|
115
|
+
If a pre-existing test fails intermittently and unrelated to your change: skip it with an
|
|
116
|
+
annotation naming it flaky, document it under `## Flaky Tests` in your review, and continue.
|
|
117
|
+
Never edit `status.yaml` or bypass a porch check to route around it.
|
|
@@ -134,6 +134,8 @@ Agents within a workspace communicate through `afx send`. Four addressing forms
|
|
|
134
134
|
| `afx send architect:<name> "msg"` | Explicit per-architect addressing. **Architects (including `main`)**: open address grammar — any architect can address any other architect (sibling-architect messaging). **Builders**: allowed ONLY when `<name>` matches the builder's own spawning architect; mismatches are rejected by Tower's spoofing check. From a builder, this is an explicit form of the affinity routing, NOT an override. | Any sender (with the spoofing constraint above for builders). |
|
|
135
135
|
| `afx send <workspace>:architect "msg"` | Cross-workspace addressing (e.g. `afx send marketmaker:architect "..."`). | Any sender. |
|
|
136
136
|
|
|
137
|
+
**Send outcomes (delivered vs held)**: `afx send` reports the real first outcome. **delivered** means the message was written to the recipient's prompt after a clean render-gate pass; **held** means the prompt wasn't clear, so the message was persisted in Tower's durable mailbox and delivers automatically once the prompt is clean — with a why-held reason (`busy`, `no-profile`, or `no-live-pty`) and a mailbox id. A held message is never force-injected onto a busy line, so it can't corrupt a half-typed draft, and held rows survive a Tower restart. List held messages with `afx inbox`, read one (including its body) with `afx inbox show <id>`, and clear one with `afx inbox dismiss <id>`; `afx send --interrupt` is the explicit bypass.
|
|
138
|
+
|
|
137
139
|
**Sibling-architect messaging**: when a workspace hosts more than one architect (added via `afx workspace add-architect --name <name>`), sibling architects message each other via the `architect:<name>` form. Example: `main` running `afx send architect:ob-refine "PR-iter-2 feedback ready"` lands on the `ob-refine` architect's terminal. This works because sender = architect bypasses the spoofing check.
|
|
138
140
|
|
|
139
141
|
**Builder spoofing-check**: a builder may only address its own spawning architect via `architect:<name>`. The spoofing check is enforced by Tower's message router; attempts to address a different architect from a builder are rejected.
|
|
@@ -132,6 +132,8 @@ Agents within a workspace communicate through `afx send`. Four addressing forms
|
|
|
132
132
|
| `afx send architect:<name> "msg"` | Explicit per-architect addressing. **Architects (including `main`)**: open address grammar — any architect can address any other architect (sibling-architect messaging). **Builders**: allowed ONLY when `<name>` matches the builder's own spawning architect; mismatches are rejected by Tower's spoofing check. From a builder, this is an explicit form of the affinity routing, NOT an override. | Any sender (with the spoofing constraint above for builders). |
|
|
133
133
|
| `afx send <workspace>:architect "msg"` | Cross-workspace addressing (e.g. `afx send marketmaker:architect "..."`). | Any sender. |
|
|
134
134
|
|
|
135
|
+
**Send outcomes (delivered vs held)**: `afx send` reports the real first outcome. **delivered** means the message was written to the recipient's prompt after a clean render-gate pass; **held** means the prompt wasn't clear, so the message was persisted in Tower's durable mailbox and delivers automatically once the prompt is clean — with a why-held reason (`busy`, `no-profile`, or `no-live-pty`) and a mailbox id. A held message is never force-injected onto a busy line, so it can't corrupt a half-typed draft, and held rows survive a Tower restart. List held messages with `afx inbox`, read one (including its body) with `afx inbox show <id>`, and clear one with `afx inbox dismiss <id>`; `afx send --interrupt` is the explicit bypass.
|
|
136
|
+
|
|
135
137
|
**Sibling-architect messaging**: when a workspace hosts more than one architect (added via `afx workspace add-architect --name <name>`), sibling architects message each other via the `architect:<name>` form. Example: `main` running `afx send architect:ob-refine "PR-iter-2 feedback ready"` lands on the `ob-refine` architect's terminal. This works because sender = architect bypasses the spoofing check.
|
|
136
138
|
|
|
137
139
|
**Builder spoofing-check**: a builder may only address its own spawning architect via `architect:<name>`. The spoofing check is enforced by Tower's message router; attempts to address a different architect from a builder are rejected.
|
package/templates/3d-viewer.html
CHANGED
|
@@ -218,12 +218,18 @@
|
|
|
218
218
|
</div>
|
|
219
219
|
</div>
|
|
220
220
|
|
|
221
|
-
<!-- Three.js ES Modules
|
|
221
|
+
<!-- Three.js ES Modules — vendored locally (three@0.160.0), served same-origin
|
|
222
|
+
from the annotator's vendor/ route. NO remote code runs in this page: it is
|
|
223
|
+
key-injected (advisory GHSA-xvjp-7748-v88v), so loading executable modules
|
|
224
|
+
from a CDN would expose window.__CODEV_TOWER_KEY__ to that CDN. -->
|
|
222
225
|
<script type="importmap">
|
|
223
226
|
{
|
|
224
227
|
"imports": {
|
|
225
|
-
"three": "
|
|
226
|
-
"three/addons/": "
|
|
228
|
+
"three": "vendor/three.module.js",
|
|
229
|
+
"three/addons/loaders/STLLoader.js": "vendor/three-STLLoader.js",
|
|
230
|
+
"three/addons/loaders/3MFLoader.js": "vendor/three-3MFLoader.js",
|
|
231
|
+
"three/addons/controls/TrackballControls.js": "vendor/three-TrackballControls.js",
|
|
232
|
+
"fflate": "vendor/three-fflate.module.js"
|
|
227
233
|
}
|
|
228
234
|
}
|
|
229
235
|
</script>
|
|
@@ -234,6 +240,24 @@
|
|
|
234
240
|
import { ThreeMFLoader } from 'three/addons/loaders/3MFLoader.js';
|
|
235
241
|
import { TrackballControls } from 'three/addons/controls/TrackballControls.js';
|
|
236
242
|
|
|
243
|
+
// Request authentication (advisory GHSA-xvjp-7748-v88v): Tower injects the
|
|
244
|
+
// shared local key into this page same-origin; model/mtime requests send it
|
|
245
|
+
// via the codev-tower-key header. Three.js loaders carry it through
|
|
246
|
+
// loader.setRequestHeader(authHeaders()).
|
|
247
|
+
function getWebKey() {
|
|
248
|
+
if (window.__CODEV_TOWER_KEY__) {
|
|
249
|
+
try { localStorage.setItem('codev-tower-key', window.__CODEV_TOWER_KEY__); } catch (e) {}
|
|
250
|
+
return window.__CODEV_TOWER_KEY__;
|
|
251
|
+
}
|
|
252
|
+
return localStorage.getItem('codev-tower-key');
|
|
253
|
+
}
|
|
254
|
+
function authHeaders(extra) {
|
|
255
|
+
const key = getWebKey();
|
|
256
|
+
const headers = extra ? Object.assign({}, extra) : {};
|
|
257
|
+
if (key) headers['codev-tower-key'] = key;
|
|
258
|
+
return headers;
|
|
259
|
+
}
|
|
260
|
+
|
|
237
261
|
// Configuration (injected by server with proper escaping)
|
|
238
262
|
const FILE_PATH = {{FILE_PATH_JSON}}; // JSON-encoded by server
|
|
239
263
|
const FILE_NAME = '{{FILE}}';
|
|
@@ -370,6 +394,7 @@
|
|
|
370
394
|
|
|
371
395
|
function loadSTL() {
|
|
372
396
|
const loader = new STLLoader();
|
|
397
|
+
loader.setRequestHeader(authHeaders());
|
|
373
398
|
|
|
374
399
|
loader.load(
|
|
375
400
|
'api/model',
|
|
@@ -412,6 +437,7 @@
|
|
|
412
437
|
|
|
413
438
|
function load3MF() {
|
|
414
439
|
const loader = new ThreeMFLoader();
|
|
440
|
+
loader.setRequestHeader(authHeaders());
|
|
415
441
|
|
|
416
442
|
loader.load(
|
|
417
443
|
'api/model',
|
|
@@ -715,7 +741,7 @@
|
|
|
715
741
|
|
|
716
742
|
async function checkForChanges() {
|
|
717
743
|
try {
|
|
718
|
-
const res = await fetch('api/mtime');
|
|
744
|
+
const res = await fetch('api/mtime', { headers: authHeaders() });
|
|
719
745
|
if (res.ok) {
|
|
720
746
|
const data = await res.json();
|
|
721
747
|
if (lastMtime === null) {
|
|
@@ -769,6 +795,7 @@
|
|
|
769
795
|
|
|
770
796
|
function reloadSTL() {
|
|
771
797
|
const loader = new STLLoader();
|
|
798
|
+
loader.setRequestHeader(authHeaders());
|
|
772
799
|
loader.load('api/model?t=' + Date.now(), (geometry) => {
|
|
773
800
|
// Center geometry in XY
|
|
774
801
|
geometry.computeBoundingBox();
|
|
@@ -811,6 +838,7 @@
|
|
|
811
838
|
|
|
812
839
|
function reload3MF() {
|
|
813
840
|
const loader = new ThreeMFLoader();
|
|
841
|
+
loader.setRequestHeader(authHeaders());
|
|
814
842
|
loader.load('api/model?t=' + Date.now(), (group) => {
|
|
815
843
|
// 3MF uses Z-up natively, which matches our coordinate system
|
|
816
844
|
|
package/templates/open.html
CHANGED
|
@@ -569,6 +569,51 @@
|
|
|
569
569
|
<script src="vendor/prism-markup.min.js"></script>
|
|
570
570
|
|
|
571
571
|
<script>
|
|
572
|
+
// Request authentication (advisory GHSA-xvjp-7748-v88v): Tower injects the
|
|
573
|
+
// shared local key into this page same-origin; every data/media fetch sends
|
|
574
|
+
// it via the codev-tower-key header. Media is fetched as an authenticated blob
|
|
575
|
+
// (img/video/pdf src cannot carry a header) and displayed via an object URL,
|
|
576
|
+
// revoked when replaced or on unload to avoid blob leaks.
|
|
577
|
+
function getWebKey() {
|
|
578
|
+
if (window.__CODEV_TOWER_KEY__) {
|
|
579
|
+
try { localStorage.setItem('codev-tower-key', window.__CODEV_TOWER_KEY__); } catch (e) {}
|
|
580
|
+
return window.__CODEV_TOWER_KEY__;
|
|
581
|
+
}
|
|
582
|
+
return localStorage.getItem('codev-tower-key');
|
|
583
|
+
}
|
|
584
|
+
function authHeaders(extra) {
|
|
585
|
+
const key = getWebKey();
|
|
586
|
+
const headers = extra ? Object.assign({}, extra) : {};
|
|
587
|
+
if (key) headers['codev-tower-key'] = key;
|
|
588
|
+
return headers;
|
|
589
|
+
}
|
|
590
|
+
function setMediaSrc(el, objectUrl) {
|
|
591
|
+
if (el.__objUrl) URL.revokeObjectURL(el.__objUrl);
|
|
592
|
+
el.__objUrl = objectUrl;
|
|
593
|
+
el.src = objectUrl;
|
|
594
|
+
}
|
|
595
|
+
async function loadMedia(el, path) {
|
|
596
|
+
try {
|
|
597
|
+
const res = await fetch(path, { headers: authHeaders() });
|
|
598
|
+
if (!res.ok) throw new Error('status ' + res.status);
|
|
599
|
+
const blob = await res.blob();
|
|
600
|
+
setMediaSrc(el, URL.createObjectURL(blob));
|
|
601
|
+
} catch (e) {
|
|
602
|
+
if (typeof el.onerror === 'function') el.onerror();
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
function revokeAllMediaUrls() {
|
|
606
|
+
['image-display', 'video-display', 'pdf-display'].forEach(function(id) {
|
|
607
|
+
const el = document.getElementById(id);
|
|
608
|
+
if (el && el.__objUrl) URL.revokeObjectURL(el.__objUrl);
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
// pagehide fires on mobile / bfcache navigations where beforeunload does not.
|
|
612
|
+
// Skip revocation when the page is going into the bfcache (persisted): the
|
|
613
|
+
// object URLs must survive so restored media still renders on pageshow.
|
|
614
|
+
window.addEventListener('pagehide', function(e) { if (!e.persisted) revokeAllMediaUrls(); });
|
|
615
|
+
window.addEventListener('beforeunload', revokeAllMediaUrls);
|
|
616
|
+
|
|
572
617
|
// State
|
|
573
618
|
let fileLines = [];
|
|
574
619
|
let currentLine = null;
|
|
@@ -673,8 +718,8 @@
|
|
|
673
718
|
img.style.display = 'none';
|
|
674
719
|
};
|
|
675
720
|
|
|
676
|
-
//
|
|
677
|
-
img
|
|
721
|
+
// Fetch as an authenticated blob (img.src cannot carry the key header).
|
|
722
|
+
loadMedia(img, 'api/image?t=' + Date.now());
|
|
678
723
|
}
|
|
679
724
|
|
|
680
725
|
// Initialize video viewer
|
|
@@ -707,8 +752,8 @@
|
|
|
707
752
|
video.style.display = 'none';
|
|
708
753
|
};
|
|
709
754
|
|
|
710
|
-
//
|
|
711
|
-
video
|
|
755
|
+
// Fetch as an authenticated blob (video.src cannot carry the key header).
|
|
756
|
+
loadMedia(video, 'api/video?t=' + Date.now());
|
|
712
757
|
}
|
|
713
758
|
|
|
714
759
|
// Initialize PDF viewer
|
|
@@ -726,9 +771,10 @@
|
|
|
726
771
|
const pdfViewer = document.getElementById('pdf-viewer');
|
|
727
772
|
pdfViewer.style.display = 'block';
|
|
728
773
|
|
|
729
|
-
// Load PDF via raw endpoint
|
|
774
|
+
// Load PDF via raw endpoint as an authenticated blob (embed.src cannot
|
|
775
|
+
// carry the key header).
|
|
730
776
|
const embed = document.getElementById('pdf-display');
|
|
731
|
-
embed
|
|
777
|
+
loadMedia(embed, 'api/pdf?t=' + Date.now());
|
|
732
778
|
}
|
|
733
779
|
|
|
734
780
|
// Update image info display (in both header and controls)
|
|
@@ -1339,7 +1385,7 @@
|
|
|
1339
1385
|
try {
|
|
1340
1386
|
const response = await fetch('save', {
|
|
1341
1387
|
method: 'POST',
|
|
1342
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1388
|
+
headers: authHeaders({ 'Content-Type': 'application/json' }),
|
|
1343
1389
|
body: JSON.stringify({
|
|
1344
1390
|
file: filePath,
|
|
1345
1391
|
content: fileLines.join('\n')
|
|
@@ -1457,7 +1503,7 @@
|
|
|
1457
1503
|
try {
|
|
1458
1504
|
const response = await fetch('save', {
|
|
1459
1505
|
method: 'POST',
|
|
1460
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1506
|
+
headers: authHeaders({ 'Content-Type': 'application/json' }),
|
|
1461
1507
|
body: JSON.stringify({ file: filePath, content })
|
|
1462
1508
|
});
|
|
1463
1509
|
|
|
@@ -1778,7 +1824,7 @@
|
|
|
1778
1824
|
if (hasUnsavedChanges || editMode) return;
|
|
1779
1825
|
|
|
1780
1826
|
try {
|
|
1781
|
-
const res = await fetch('api/mtime');
|
|
1827
|
+
const res = await fetch('api/mtime', { headers: authHeaders() });
|
|
1782
1828
|
if (res.ok) {
|
|
1783
1829
|
const data = await res.json();
|
|
1784
1830
|
if (lastMtime === null) {
|
|
@@ -1797,21 +1843,21 @@
|
|
|
1797
1843
|
// For images and videos, just reload the source
|
|
1798
1844
|
if (isImageFile) {
|
|
1799
1845
|
const img = document.getElementById('image-display');
|
|
1800
|
-
img
|
|
1846
|
+
loadMedia(img, 'api/image?t=' + Date.now());
|
|
1801
1847
|
showNotification('Image reloaded');
|
|
1802
1848
|
return;
|
|
1803
1849
|
}
|
|
1804
1850
|
|
|
1805
1851
|
if (isVideoFile) {
|
|
1806
1852
|
const video = document.getElementById('video-display');
|
|
1807
|
-
video
|
|
1853
|
+
loadMedia(video, 'api/video?t=' + Date.now());
|
|
1808
1854
|
showNotification('Video reloaded');
|
|
1809
1855
|
return;
|
|
1810
1856
|
}
|
|
1811
1857
|
|
|
1812
1858
|
// For text files, fetch new content
|
|
1813
1859
|
try {
|
|
1814
|
-
const res = await fetch('file');
|
|
1860
|
+
const res = await fetch('file', { headers: authHeaders() });
|
|
1815
1861
|
if (res.ok) {
|
|
1816
1862
|
const content = await res.text();
|
|
1817
1863
|
currentContent = content;
|