@cluesmith/codev 3.3.0 → 3.3.2
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-JCbkpAcV.js → index-D3XaKpZW.js} +45 -43
- package/dashboard-dist/assets/index-D3XaKpZW.js.map +1 -0
- package/dashboard-dist/index.html +1 -1
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +99 -36
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/reset/constants.d.ts +119 -1
- package/dist/agent-farm/commands/reset/constants.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/constants.js +119 -1
- package/dist/agent-farm/commands/reset/constants.js.map +1 -1
- package/dist/agent-farm/commands/reset/context.d.ts +20 -2
- package/dist/agent-farm/commands/reset/context.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/context.js +44 -3
- package/dist/agent-farm/commands/reset/context.js.map +1 -1
- package/dist/agent-farm/commands/reset/index.d.ts +7 -7
- package/dist/agent-farm/commands/reset/index.js +8 -8
- package/dist/agent-farm/commands/reset/index.js.map +1 -1
- package/dist/agent-farm/commands/reset/receipt.d.ts +1 -1
- package/dist/agent-farm/commands/reset/receipt.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/receipt.js +19 -8
- package/dist/agent-farm/commands/reset/receipt.js.map +1 -1
- package/dist/agent-farm/commands/reset/reorient.d.ts +1 -1
- package/dist/agent-farm/commands/reset/reorient.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/reorient.js +12 -5
- package/dist/agent-farm/commands/reset/reorient.js.map +1 -1
- package/dist/agent-farm/commands/reset/self.d.ts +335 -0
- package/dist/agent-farm/commands/reset/self.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/self.js +636 -0
- package/dist/agent-farm/commands/reset/self.js.map +1 -0
- package/dist/agent-farm/commands/reset.d.ts +18 -3
- package/dist/agent-farm/commands/reset.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset.js +55 -33
- package/dist/agent-farm/commands/reset.js.map +1 -1
- package/dist/agent-farm/commands/self-refresh.d.ts +60 -0
- package/dist/agent-farm/commands/self-refresh.d.ts.map +1 -0
- package/dist/agent-farm/commands/self-refresh.js +506 -0
- package/dist/agent-farm/commands/self-refresh.js.map +1 -0
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +27 -2
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts +7 -0
- 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/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/lib/reconnect-backoff.d.ts +10 -0
- package/dist/agent-farm/lib/reconnect-backoff.d.ts.map +1 -1
- package/dist/agent-farm/lib/reconnect-backoff.js +10 -0
- package/dist/agent-farm/lib/reconnect-backoff.js.map +1 -1
- package/dist/agent-farm/lib/tower-client.d.ts +12 -0
- package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tower-client.js +12 -0
- package/dist/agent-farm/lib/tower-client.js.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +7 -3
- 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/gate-profiles.d.ts +1 -1
- package/dist/agent-farm/servers/gate-profiles.js +1 -1
- package/dist/agent-farm/servers/mailbox-delivery.d.ts +141 -13
- package/dist/agent-farm/servers/mailbox-delivery.d.ts.map +1 -1
- package/dist/agent-farm/servers/mailbox-delivery.js +172 -16
- package/dist/agent-farm/servers/mailbox-delivery.js.map +1 -1
- package/dist/agent-farm/servers/mailbox-wiring.d.ts +24 -2
- package/dist/agent-farm/servers/mailbox-wiring.d.ts.map +1 -1
- package/dist/agent-farm/servers/mailbox-wiring.js +92 -32
- package/dist/agent-farm/servers/mailbox-wiring.js.map +1 -1
- package/dist/agent-farm/servers/message-write.d.ts +58 -18
- package/dist/agent-farm/servers/message-write.d.ts.map +1 -1
- package/dist/agent-farm/servers/message-write.js +73 -28
- 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 +78 -1
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/render-gate.d.ts +13 -0
- package/dist/agent-farm/servers/render-gate.d.ts.map +1 -1
- package/dist/agent-farm/servers/render-gate.js +21 -0
- package/dist/agent-farm/servers/render-gate.js.map +1 -1
- package/dist/agent-farm/servers/session-submit.d.ts +221 -28
- package/dist/agent-farm/servers/session-submit.d.ts.map +1 -1
- package/dist/agent-farm/servers/session-submit.js +334 -43
- package/dist/agent-farm/servers/session-submit.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +269 -64
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +25 -3
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +6 -0
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +30 -5
- 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 +14 -0
- package/dist/agent-farm/servers/tower-tunnel.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 +90 -37
- package/dist/agent-farm/servers/tower-websocket.js.map +1 -1
- package/dist/agent-farm/types.d.ts +37 -2
- package/dist/agent-farm/types.d.ts.map +1 -1
- package/dist/agent-farm/utils/harness.d.ts +3 -3
- package/dist/agent-farm/utils/harness.js +1 -1
- package/dist/agent-farm/utils/message-format.d.ts +67 -3
- package/dist/agent-farm/utils/message-format.d.ts.map +1 -1
- package/dist/agent-farm/utils/message-format.js +127 -14
- package/dist/agent-farm/utils/message-format.js.map +1 -1
- package/dist/agent-farm/utils/server-utils.d.ts +86 -4
- package/dist/agent-farm/utils/server-utils.d.ts.map +1 -1
- package/dist/agent-farm/utils/server-utils.js +303 -5
- package/dist/agent-farm/utils/server-utils.js.map +1 -1
- package/dist/commands/porch/context-refresh.d.ts +181 -0
- package/dist/commands/porch/context-refresh.d.ts.map +1 -0
- package/dist/commands/porch/context-refresh.js +270 -0
- package/dist/commands/porch/context-refresh.js.map +1 -0
- package/dist/commands/porch/index.d.ts +6 -0
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +46 -0
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/next.d.ts +0 -9
- package/dist/commands/porch/next.d.ts.map +1 -1
- package/dist/commands/porch/next.js +133 -4
- package/dist/commands/porch/next.js.map +1 -1
- package/dist/commands/porch/protocol.d.ts.map +1 -1
- package/dist/commands/porch/protocol.js +102 -0
- package/dist/commands/porch/protocol.js.map +1 -1
- package/dist/commands/porch/types.d.ts +61 -0
- package/dist/commands/porch/types.d.ts.map +1 -1
- 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 +17 -0
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/self-refresh-invocation.d.ts +60 -0
- package/dist/lib/self-refresh-invocation.d.ts.map +1 -0
- package/dist/lib/self-refresh-invocation.js +64 -0
- package/dist/lib/self-refresh-invocation.js.map +1 -0
- package/dist/lib/test-env.d.ts +50 -0
- package/dist/lib/test-env.d.ts.map +1 -1
- package/dist/lib/test-env.js +76 -0
- package/dist/lib/test-env.js.map +1 -1
- 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.map +1 -1
- package/dist/terminal/pty-manager.js +35 -17
- package/dist/terminal/pty-manager.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +81 -12
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +113 -25
- package/dist/terminal/pty-session.js.map +1 -1
- package/dist/terminal/session-screen.d.ts +25 -0
- package/dist/terminal/session-screen.d.ts.map +1 -1
- package/dist/terminal/session-screen.js +53 -8
- package/dist/terminal/session-screen.js.map +1 -1
- package/package.json +10 -7
- 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 +54 -0
- package/skeleton/.claude/skills/arch-save/SKILL.md +8 -2
- package/skeleton/.claude/skills/builder-refresh/SKILL.md +138 -0
- package/skeleton/.codex/skills/afx/SKILL.md +54 -0
- package/skeleton/.codex/skills/arch-save/SKILL.md +8 -2
- package/skeleton/.codex/skills/builder-refresh/SKILL.md +138 -0
- package/skeleton/protocol-schema.json +17 -0
- package/skeleton/protocols/air/protocol.json +1 -1
- package/skeleton/protocols/aspir/protocol.json +5 -1
- package/skeleton/protocols/bugfix/protocol.json +1 -1
- package/skeleton/protocols/experiment/protocol.json +1 -1
- package/skeleton/protocols/maintain/protocol.json +1 -1
- package/skeleton/protocols/pir/builder-prompt.md +3 -2
- package/skeleton/protocols/pir/prompts/implement.md +1 -1
- package/skeleton/protocols/pir/prompts/plan.md +1 -1
- package/skeleton/protocols/pir/prompts/review.md +1 -1
- package/skeleton/protocols/pir/protocol.json +1 -1
- package/skeleton/protocols/pir/protocol.md +4 -4
- package/skeleton/protocols/protocol-schema.json +17 -0
- package/skeleton/protocols/research/protocol.json +1 -1
- package/skeleton/protocols/spike/protocol.json +1 -1
- package/skeleton/protocols/spir/protocol.json +5 -1
- package/skeleton/resources/commands/agent-farm.md +14 -11
- package/skeleton/roles/builder.md +3 -4
- package/templates/3d-viewer.html +32 -4
- package/templates/open.html +58 -12
- package/templates/tower.html +26 -7
- 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-JCbkpAcV.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "
|
|
2
|
+
"$schema": "../protocol-schema.json",
|
|
3
3
|
"name": "aspir",
|
|
4
4
|
"version": "1.0.0",
|
|
5
5
|
"description": "ASPIR: Autonomous SPIR — Specify → Plan → Implement → Review without human approval gates",
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
"required": false,
|
|
9
9
|
"default_for": ["--project", "-p"]
|
|
10
10
|
},
|
|
11
|
+
"context_refresh": {
|
|
12
|
+
"on_enter": ["plan", "implement", "review"],
|
|
13
|
+
"on_plan_phase_advance": true
|
|
14
|
+
},
|
|
11
15
|
"phases": [
|
|
12
16
|
{
|
|
13
17
|
"id": "specify",
|
|
@@ -42,8 +42,9 @@ the code directly in the worktree (you see it via `git diff`), typing into your
|
|
|
42
42
|
`afx send <your-builder-id>` (queued — check next turn), or a comment on the GitHub issue
|
|
43
43
|
(re-fetch with `gh issue view <N> --comments`).
|
|
44
44
|
|
|
45
|
-
Revise, recommit, ask whether more remains. **The gate stays pending until the human
|
|
46
|
-
`porch approve
|
|
45
|
+
Revise, recommit, ask whether more remains. **The gate stays pending until the human approves. When
|
|
46
|
+
the architect relays that approval, run `porch approve <id> <gate> --a-human-explicitly-approved-this`
|
|
47
|
+
to record it and continue — never on your own initiative.**
|
|
47
48
|
|
|
48
49
|
## Resumption After Crash
|
|
49
50
|
|
|
@@ -140,7 +140,7 @@ Then **stay in the interactive session**. Do not exit. Wait for the user's next
|
|
|
140
140
|
|
|
141
141
|
- **Don't write `codev/reviews/<id>-<slug>.md` in this phase** — it's the next phase's artifact, with a different shape (retrospective with arch + lessons updates)
|
|
142
142
|
- Don't add features not in the plan — scope creep is a `BLOCKED` signal, not a free expansion
|
|
143
|
-
- Don't run `porch approve`
|
|
143
|
+
- Don't run `porch approve` on your own initiative — only when the architect relays the human's approval
|
|
144
144
|
- Don't push to the default branch — only to your builder branch
|
|
145
145
|
- Don't squash commits — let the merge commit preserve history
|
|
146
146
|
- Don't open the PR yet — that's the `review` phase
|
|
@@ -114,7 +114,7 @@ Then **stay in the interactive session**. Do not exit. Wait for the user's next
|
|
|
114
114
|
## What NOT to Do
|
|
115
115
|
|
|
116
116
|
- Don't write code — that's the implement phase
|
|
117
|
-
- Don't run `porch approve`
|
|
117
|
+
- Don't run `porch approve` on your own initiative — only when the architect relays the human's approval
|
|
118
118
|
- Don't post the plan content as a GitHub issue comment — the plan lives in the file, not the issue thread. A one-line pointer comment on the issue is fine if you think it helps the discussion.
|
|
119
119
|
- Don't exit the interactive session at the gate
|
|
120
120
|
|
|
@@ -240,7 +240,7 @@ Together with the `--pr` record from step 4a and the `--merged` record from step
|
|
|
240
240
|
|
|
241
241
|
- **Don't merge before the `pr` gate is approved** (steps 8–9). Neither a consultation APPROVE verdict nor user-in-pane prose ("looks good", "lgtm", "merge it") authorizes `gh pr merge` — only porch reporting `gate_status: approved` for the `pr` gate does.
|
|
242
242
|
- Don't skip porch's PR/merge records (steps 4a, 9). The `--pr` record (step 4a) lets the gate-pending state link to the actual PR; the `--merged` record (step 9) closes the lifecycle in porch state. Skipping either leaves `history:` empty and downstream tooling blind.
|
|
243
|
-
- Don't run `porch approve` for any gate
|
|
243
|
+
- Don't run `porch approve` for any gate on your own initiative — only when the architect relays the human's approval
|
|
244
244
|
- Don't push to the default branch — only merge via PR
|
|
245
245
|
- Don't skip the Architecture Updates / Lessons Learned sections — porch checks enforce their presence (the section must exist; explaining "no changes needed" in one line is fine)
|
|
246
246
|
- **Don't run `consult` commands yourself** — porch handles consultations via the `verify` block. Manually invoking `consult` causes the consultation to run twice.
|
|
@@ -32,14 +32,14 @@ protocol is safe and needs no porch change.
|
|
|
32
32
|
| `dev-approval` | pre-PR | **PIR's distinctive gate** — reviews the *running* worktree via `afx dev` |
|
|
33
33
|
| `pr` | post-PR | Reviews on GitHub, then approves; porch wakes the builder to merge |
|
|
34
34
|
|
|
35
|
-
The `pr` gate
|
|
36
|
-
builder
|
|
37
|
-
ambiguous prose.
|
|
35
|
+
The `pr` gate holds the merge behind porch state: the human approves, the architect relays that
|
|
36
|
+
approval, and the builder records it with `porch approve pr` before porch hands over the merge task.
|
|
38
37
|
|
|
39
38
|
**Gates do not notify the architect automatically.** Porch broadcasts `overview-changed` over
|
|
40
39
|
SSE; the VSCode Builders tree renders the blocked state with a bell and raises a toast. CLI
|
|
41
40
|
users see it via the builder pane or `porch pending`. The builder's job at any gate is: write
|
|
42
|
-
the artifact, commit, signal, wait —
|
|
41
|
+
the artifact, commit, signal, wait — then run `porch approve` when the architect relays the human's
|
|
42
|
+
approval, never on your own initiative.
|
|
43
43
|
|
|
44
44
|
## Rejection is iteration, not a command
|
|
45
45
|
|
|
@@ -33,6 +33,23 @@
|
|
|
33
33
|
"hooks": {
|
|
34
34
|
"$ref": "#/definitions/protocolHooks"
|
|
35
35
|
},
|
|
36
|
+
"context_refresh": {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"description": "Boundaries at which builders automatically refresh their context (Spec 1470). Absent means no refreshes.",
|
|
39
|
+
"additionalProperties": false,
|
|
40
|
+
"properties": {
|
|
41
|
+
"on_enter": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"description": "Protocol phase ids to refresh on entry to. Each must name a phase this protocol declares.",
|
|
44
|
+
"uniqueItems": true,
|
|
45
|
+
"items": { "type": "string" }
|
|
46
|
+
},
|
|
47
|
+
"on_plan_phase_advance": {
|
|
48
|
+
"type": "boolean",
|
|
49
|
+
"description": "Refresh when advancing from one plan phase to the next. Requires a 'per_plan_phase' phase. Excludes the first plan phase, which coincides with entering the phase itself."
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
36
53
|
"signals": {
|
|
37
54
|
"type": "object",
|
|
38
55
|
"description": "Signal definitions for state transitions",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "
|
|
2
|
+
"$schema": "../protocol-schema.json",
|
|
3
3
|
"name": "spir",
|
|
4
4
|
"alias": "spider",
|
|
5
5
|
"version": "2.2.0",
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
"required": false,
|
|
10
10
|
"default_for": ["--project", "-p"]
|
|
11
11
|
},
|
|
12
|
+
"context_refresh": {
|
|
13
|
+
"on_enter": ["plan", "implement", "review"],
|
|
14
|
+
"on_plan_phase_advance": true
|
|
15
|
+
},
|
|
12
16
|
"phases": [
|
|
13
17
|
{
|
|
14
18
|
"id": "specify",
|
|
@@ -501,12 +501,12 @@ afx send 0042 "That producer died — stop waiting and report."
|
|
|
501
501
|
|
|
502
502
|
---
|
|
503
503
|
|
|
504
|
-
### afx
|
|
504
|
+
### afx refresh
|
|
505
505
|
|
|
506
|
-
|
|
506
|
+
Refresh a builder's context: have it save its working state, clear the conversation, then re-orient it.
|
|
507
507
|
|
|
508
508
|
```bash
|
|
509
|
-
afx
|
|
509
|
+
afx refresh <builder> [options]
|
|
510
510
|
```
|
|
511
511
|
|
|
512
512
|
**Arguments:**
|
|
@@ -522,10 +522,13 @@ afx reset <builder> [options]
|
|
|
522
522
|
- `--min-bytes <n>` - Minimum state-file size to accept as substantive (default 1000)
|
|
523
523
|
- `--quiet-window <ms>` - Terminal silence that counts as turn-ended (default 1500)
|
|
524
524
|
|
|
525
|
+
**Deprecated alias:** `afx reset` still runs this command and prints a one-line notice to stderr.
|
|
526
|
+
It will be removed in a future release — use `afx refresh`.
|
|
527
|
+
|
|
525
528
|
**Description:**
|
|
526
529
|
|
|
527
530
|
Long-running builders exhaust their context window. `afx spawn --resume` reattaches the *same*
|
|
528
|
-
conversation, so a deep session resumes deep — it does not give the builder a fresh window. `afx
|
|
531
|
+
conversation, so a deep session resumes deep — it does not give the builder a fresh window. `afx refresh`
|
|
529
532
|
does, without losing what the builder knows.
|
|
530
533
|
|
|
531
534
|
The sequence:
|
|
@@ -533,7 +536,7 @@ The sequence:
|
|
|
533
536
|
1. Assemble the re-orientation and write it to `.builder-reorient.md` in the worktree.
|
|
534
537
|
2. Ask the builder to write its complete working state to `.builder-state.md`, stamped with a one-time
|
|
535
538
|
nonce.
|
|
536
|
-
3. Wait for that file and **verify** it: correct nonce (not a stale file from an earlier
|
|
539
|
+
3. Wait for that file and **verify** it: correct nonce (not a stale file from an earlier refresh),
|
|
537
540
|
substantive size, and stable across two observations (not still being written).
|
|
538
541
|
4. Wait for the terminal to fall silent, so the clear is not typed mid-turn. If it does not settle, send
|
|
539
542
|
**one** ESC and wait again.
|
|
@@ -556,19 +559,19 @@ then `afx spawn <id> --resume`).
|
|
|
556
559
|
|
|
557
560
|
```bash
|
|
558
561
|
# See exactly what would be sent, without touching the builder
|
|
559
|
-
afx
|
|
562
|
+
afx refresh 0042 --dry-run
|
|
560
563
|
|
|
561
|
-
# Standard
|
|
562
|
-
afx
|
|
564
|
+
# Standard refresh
|
|
565
|
+
afx refresh 0042
|
|
563
566
|
|
|
564
567
|
# Add context that post-dates the builder's saved state
|
|
565
|
-
afx
|
|
568
|
+
afx refresh 0042 --note "PR #90 merged while you were mid-phase. Rebase before continuing."
|
|
566
569
|
|
|
567
570
|
# The builder is wedged mid-turn and not reading messages
|
|
568
|
-
afx
|
|
571
|
+
afx refresh 0042 --interrupt-first
|
|
569
572
|
|
|
570
573
|
# A builder that legitimately needs longer to write its state
|
|
571
|
-
afx
|
|
574
|
+
afx refresh 0042 --timeout 600
|
|
572
575
|
```
|
|
573
576
|
|
|
574
577
|
---
|
|
@@ -23,9 +23,8 @@ say so, **stop**, and wait.
|
|
|
23
23
|
Never treat a porch gate as approved without an explicit human decision — a gate message is a notification to the human, not authorization.
|
|
24
24
|
|
|
25
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
|
|
27
|
-
prompts
|
|
28
|
-
via Cmd+K G or their own shell). Defer to your protocol's phase prompts on who types `porch approve`.
|
|
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`.
|
|
29
28
|
|
|
30
29
|
## Deliverables
|
|
31
30
|
|
|
@@ -72,7 +71,7 @@ nobody can redirect, and you will not notice, because from inside it everything
|
|
|
72
71
|
Never chain foreground poll loops.
|
|
73
72
|
|
|
74
73
|
If you are wedged anyway, the architect can end your turn with `afx interrupt <your-id>`, or
|
|
75
|
-
`afx
|
|
74
|
+
`afx refresh <your-id>` to have you save state and re-orient. Worth knowing so you can suggest
|
|
76
75
|
them.
|
|
77
76
|
|
|
78
77
|
## PRs
|
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;
|
package/templates/tower.html
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
<meta name="theme-color" content="#252525">
|
|
9
9
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🗼</text></svg>">
|
|
10
10
|
<title>Agent Farm Tower</title>
|
|
11
|
+
<!-- CODEV_TOWER_KEY_INJECTION -->
|
|
11
12
|
<style>
|
|
12
13
|
* {
|
|
13
14
|
box-sizing: border-box;
|
|
@@ -989,21 +990,39 @@
|
|
|
989
990
|
let runningInstances = [];
|
|
990
991
|
let recentInstances = [];
|
|
991
992
|
|
|
992
|
-
// Auth helper:
|
|
993
|
+
// Auth helper: resolve the shared local key. Prefer the value Tower injects
|
|
994
|
+
// same-origin at serve time (window.__CODEV_TOWER_KEY__); fall back to any
|
|
995
|
+
// previously stored value. The injected value is persisted so later loads
|
|
996
|
+
// and manual navigations keep working.
|
|
997
|
+
function getWebKey() {
|
|
998
|
+
if (window.__CODEV_TOWER_KEY__) {
|
|
999
|
+
try { localStorage.setItem('codev-tower-key', window.__CODEV_TOWER_KEY__); } catch (e) {}
|
|
1000
|
+
return window.__CODEV_TOWER_KEY__;
|
|
1001
|
+
}
|
|
1002
|
+
return localStorage.getItem('codev-tower-key');
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
// Auth helper: get headers with the auth key if available
|
|
993
1006
|
function getAuthHeaders() {
|
|
994
|
-
const key =
|
|
995
|
-
return key ? { '
|
|
1007
|
+
const key = getWebKey();
|
|
1008
|
+
return key ? { 'codev-tower-key': key } : {};
|
|
996
1009
|
}
|
|
997
1010
|
|
|
998
1011
|
// Auth helper: make authenticated fetch request
|
|
999
1012
|
async function authFetch(url, options = {}) {
|
|
1013
|
+
const hadKey = !!getWebKey();
|
|
1000
1014
|
const headers = { ...getAuthHeaders(), ...(options.headers || {}) };
|
|
1001
1015
|
const response = await fetch(url, { ...options, headers });
|
|
1002
1016
|
|
|
1003
|
-
// If 401, clear key
|
|
1017
|
+
// If 401, clear a now-stale key. Only reload when we actually sent a key:
|
|
1018
|
+
// a reload re-fetches the shell and picks up a freshly injected key. With
|
|
1019
|
+
// no key to begin with, the shell has none to inject, so reloading would
|
|
1020
|
+
// loop forever (advisory GHSA-xvjp-7748-v88v) — surface the error instead.
|
|
1004
1021
|
if (response.status === 401) {
|
|
1005
|
-
localStorage.removeItem('codev-
|
|
1006
|
-
|
|
1022
|
+
localStorage.removeItem('codev-tower-key');
|
|
1023
|
+
if (hadKey) {
|
|
1024
|
+
location.reload();
|
|
1025
|
+
}
|
|
1007
1026
|
throw new Error('Unauthorized');
|
|
1008
1027
|
}
|
|
1009
1028
|
return response;
|
|
@@ -1011,7 +1030,7 @@
|
|
|
1011
1030
|
|
|
1012
1031
|
// Logout function
|
|
1013
1032
|
function logout() {
|
|
1014
|
-
localStorage.removeItem('codev-
|
|
1033
|
+
localStorage.removeItem('codev-tower-key');
|
|
1015
1034
|
window.location.href = './';
|
|
1016
1035
|
}
|
|
1017
1036
|
|