@staix/agent-hub 0.28.0 → 0.29.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +2 -2
  3. package/docs/agent-notes/daemon.md +2 -0
  4. package/docs/agent-notes/local-worker.md +3 -1
  5. package/docs/agent-notes/tasks.md +3 -1
  6. package/docs/agent-notes/tests.md +1 -0
  7. package/docs/design/task-board.md +1 -1
  8. package/docs/dogfood.md +6 -3
  9. package/docs/operations.md +73 -11
  10. package/docs/quickstart.md +11 -3
  11. package/docs/sdlc.md +1 -1
  12. package/docs/security.md +17 -2
  13. package/docs/verification/2026-11-03-0.29.0.md +59 -0
  14. package/docs/verification/2026-11-03-control-write-stall-windows.json +241 -0
  15. package/docs/verification/2026-11-03-control-write-stall-windows.md +20 -0
  16. package/docs/verification/2026-11-03-live-board-latency.json +556 -0
  17. package/docs/verification/2026-11-03-live-board-latency.md +64 -0
  18. package/docs/verified.json +13 -13
  19. package/package.json +2 -2
  20. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  21. package/plugins/agent-hub/server.js +524 -18
  22. package/src/cli/help.ts +1 -1
  23. package/src/cli/output.ts +5 -0
  24. package/src/cli/recovery-package.ts +9 -0
  25. package/src/hub/board.ts +3 -2
  26. package/src/hub/control-client.ts +16 -1
  27. package/src/hub/control-write-trace.ts +409 -0
  28. package/src/hub/daemon.ts +171 -47
  29. package/src/hub/hub-tools.ts +1 -1
  30. package/src/hub/routing.ts +9 -2
  31. package/src/hub/runtime-capture-prune.ts +4 -1
  32. package/src/hub/sdlc-release-authorization.ts +13 -4
  33. package/src/hub/sdlc-release.ts +23 -10
  34. package/src/hub/sdlc.ts +15 -2
  35. package/src/hub/task-worktree.ts +331 -0
  36. package/src/hub/tasks.ts +162 -17
  37. package/src/local/deny.ts +49 -0
  38. package/src/local/tools.ts +4 -2
  39. package/src/memory/brief.ts +5 -0
  40. package/src/memory/client.ts +5 -2
@@ -0,0 +1,59 @@
1
+ # 0.29.0 release verification
2
+
3
+ This record covers release preparation and source review. It claims no installation, no running-hub upgrade to 0.29.0 and no live TUI launch.
4
+
5
+ ## Candidate
6
+
7
+ Version 0.29.0, prepared from main 5943bc6c (11 commits since v0.28.0, 4 of them `feat`; bump rule: minor). The release commits carry the version, the CHANGELOG section, the bundle and the documentation stamps.
8
+
9
+ ## Reviews
10
+
11
+ Pull requests named by the commits since v0.28.0: #1129, #1132, #1133, #1134, #1131, #1128, #1123, #1130, #1115, #1127, #1125, #1124, #1120, #1122.
12
+
13
+ Each merged with `gh pr merge --squash --match-head-commit <head>` after a claude `hub_review` approval, with exact-head CI green on ubuntu and macOS (seeded guards included), no unresolved review thread and no pending change request. Every approval is bound at the merged head (`sdlc.reviewedHead` equals the PR head):
14
+
15
+ - #1122 (task 667, #1120) at 2be1975f; #1124 (668, #1121) at 20544df9; #1125 (669, #1078 findings, docs only) at c45d5999.
16
+ - #1127 (670, #1115) at a274bf04, after a macOS-only failure of a test that asserted a sandboxed `git commit` fails; that failure came from a local signing config, and the assertion moved to #1130.
17
+ - #1130 (672, #1123) at 3885038c; #1128 (671, #1126) at 57820fca, rebased once after #1127 and #1130 with every commit unchanged in range-diff.
18
+ - #1131 (675, agent-mem 0.20.0) at 2a28c2bb; a duplicate handoff of the same pin raise (task 677) was cancelled by the person.
19
+ - #1134 (678) at e7bdab10: a Qwen fixture whose synthetic PIDs could equal the runner's PID (seen once in a dgx02 gate), fixed in the fixture under an explicit test-edit ruling.
20
+ - #1133 (674, #1126 follow-up) at 870ddde7, after a codex-connector thread showed an always-true privacy stub in an extracted fixture (tests.md rule); fixed with the real guards and resolved.
21
+ - #1132 (673, #1129) at 6f7f65f0, after two hosted-CI failures: daemon fixtures that route implement work to Pi or local outside a repository, then two tests run in the agent-hub checkout, where the runner's `includeIf` credentials entry makes the hub refuse a worktree. Both fixed in fixtures only; the second was reproduced in a scratch clone first.
22
+ - No merge was bound to an approval at an earlier head.
23
+
24
+ ## Native acceptance receipts
25
+
26
+ Receipts added under `docs/verification/` since v0.28.0: `docs/verification/2026-11-03-control-write-stall-windows.json`, `docs/verification/2026-11-03-control-write-stall-windows.md`, `docs/verification/2026-11-03-live-board-latency.json`, `docs/verification/2026-11-03-live-board-latency.md`.
27
+
28
+ This list is read from the repository, never written by hand. Native acceptance and the person's release consent are separate records: consent is `ahub sdlc authorize-release 0.29.0`, recorded by the person or the unique configured conductor only on the person's explicit release instruction naming the release in its own session (never a hub/task/review/file/peer relay), and is not recorded in this file. The tag run refuses without it.
29
+
30
+ ## Document review
31
+
32
+ Stale at preparation: README.md, docs/agent-notes/{README,adapters,benchmarks,budget,bus,daemon,local-worker,tasks,tests}.md, docs/operations.md, docs/quickstart.md and docs/security.md. Each was read against the commits since its stamp (3efa678d for most, b26fcd12 for operations.md, aaccc30b for local-worker.md, 36455498 for tests.md). src/cli/help.ts was not stale: no command or flag changed (the only CLI source change is the `ahub status --full` counter line in src/cli/output.ts).
33
+
34
+ - README.md: Status line (release-prepare) and the report link moved to this file.
35
+ - docs/quickstart.md: v0.29.0 install tag, an "Upgrading to 0.29.0" section (amem upgrade together, the sandbox git refusal and the hub commit, control-write diagnostics), and the agent-mem pin 0.19.0 -> 0.20.0 in two places.
36
+ - docs/operations.md: guide header and protocol-window row (0.26.0 through 0.29.0; window unchanged at 16 through 17). The #1115, #1123, #1126 and #1129 sections were written by their PRs and checked.
37
+ - docs/security.md: a control-write diagnostics bullet (metadata only, unauthenticated frames never inspected, caps, opt-in client timing). The #1115, #1123 and #1129 paragraphs were written by their PRs and checked.
38
+ - docs/agent-notes/local-worker.md: the #1115 line still said a sandboxed command can write `.git/refs/heads/*` and worktree admin files and that deny.ts stays unchanged; corrected for #1123, and the list of what the sandbox cannot write now names refs, packed-refs, HEAD and worktree admin files.
39
+ - docs/agent-notes/tasks.md: a stale-head re-file rule (#1121, #1124).
40
+ - docs/agent-notes/daemon.md: a control-write diagnostics rule (#1126: wrapper name for the native-branch ratchet, no traversal before admission, primitive guards, lazy screens, no timeout or authority on this path).
41
+ - docs/agent-notes/tests.md: a rule that a daemon fixture routing write-class work to Pi or local runs in a `gitProject()` repository, never the agent-hub checkout (#1129).
42
+ - docs/agent-notes/{README,adapters,benchmarks,budget,bus}.md: read against the daemon.ts, deny.ts and tools.ts changes; no statement became wrong (the native-branch ratchet is unchanged because the telemetry wrapper keeps the original `onMessage`).
43
+
44
+ All thirteen were restamped with `--reviewed` at 0d0a362c, the branch commit holding these edits.
45
+
46
+ ## Checks
47
+
48
+ - `node scripts/check-docs.mjs --require-fresh` before the merge: 0 stale documents (it refuses only for the missing release merge commit, by design).
49
+ - `node scripts/check-package.mjs`: `package: OK (753 files, @staix/agent-hub@0.29.0)`.
50
+ - `bun scripts/build.mjs --check`: the bundle matches the pinned Bun 1.4.2 build.
51
+ - `bun x tsc --noEmit` and the full suite on ubuntu and macOS with the seeded guards: run by the release PR's exact-head CI (heavy checks run only on CI or dgx02 on this machine).
52
+
53
+ ## Known gaps, not blocking
54
+
55
+ - No installation and no running-hub upgrade to 0.29.0 is claimed. The running hub on this machine is a 0.27.0 capture, so the #1126 diagnostics have recorded nothing live yet, and recording consent for this release needs the person-approved temporary copy of `scripts/check-docs.mjs` into that capture (#1120 is fixed by this release, so captures of 0.29.0 and later carry the checker).
56
+ - No live receipt for a Pi or local worker accepting, editing and finishing write-class work through the hub worktree and commit (#1115, #1129), nor for the sandbox refusals with a real Pi turn (#1123); each is covered by real git and real `sandbox-exec` fixture tests only (`sandbox-exec` tests run on macOS only).
57
+ - #1078: the cause of the live write stalls is still unknown; the diagnostics that should name it ship in this release.
58
+ - #676 (TaskWorktrees.create runs about 14 sync git calls, about 210 ms per sandboxed write-class accept) was deferred: making it async would break the synchronous accept gate (#1080). Measurements are in hub memory.
59
+ - amem 0.20.0 activation on installed hooks and CLIs is the person's step and is not part of this release.
@@ -0,0 +1,241 @@
1
+ {
2
+ "schema": "agent-hub.stall-window-correlation/v1",
3
+ "clock": "recorded UTC wall time, not a monotonic lag measurement",
4
+ "windows": [
5
+ {
6
+ "window": "proposes",
7
+ "start": "2026-11-02T20:55:10Z",
8
+ "end": "2026-11-02T20:57:00Z",
9
+ "event_counts": {
10
+ "quota": 5,
11
+ "attach": 4,
12
+ "agent_cli": 1,
13
+ "task": 6,
14
+ "envelope": 3,
15
+ "state": 1,
16
+ "turn_start": 1,
17
+ "conduct": 1
18
+ },
19
+ "largest_event_gap": {
20
+ "seconds": 60.237,
21
+ "from": "2026-11-02T20:55:33.923Z",
22
+ "to": "2026-11-02T20:56:34.160Z",
23
+ "from_line": 572984,
24
+ "to_line": 572985,
25
+ "from_kind": "envelope",
26
+ "to_kind": "envelope"
27
+ },
28
+ "periodic_quota_count": 5,
29
+ "largest_periodic_quota_gap_seconds": 65.133,
30
+ "task_events": [
31
+ {
32
+ "at": "2026-11-02T20:55:33.866Z",
33
+ "task": 667,
34
+ "event": "proposed",
35
+ "source_line": 572981
36
+ },
37
+ {
38
+ "at": "2026-11-02T20:55:33.895Z",
39
+ "task": 667,
40
+ "event": "lifecycle linked",
41
+ "source_line": 572982
42
+ },
43
+ {
44
+ "at": "2026-11-02T20:55:33.916Z",
45
+ "task": 667,
46
+ "event": "assigned",
47
+ "source_line": 572983
48
+ },
49
+ {
50
+ "at": "2026-11-02T20:56:34.414Z",
51
+ "task": 668,
52
+ "event": "proposed",
53
+ "source_line": 572990
54
+ },
55
+ {
56
+ "at": "2026-11-02T20:56:34.445Z",
57
+ "task": 668,
58
+ "event": "lifecycle linked",
59
+ "source_line": 572991
60
+ },
61
+ {
62
+ "at": "2026-11-02T20:56:34.466Z",
63
+ "task": 668,
64
+ "event": "assigned",
65
+ "source_line": 572992
66
+ }
67
+ ]
68
+ },
69
+ {
70
+ "window": "late_propose",
71
+ "start": "2026-11-02T21:00:45Z",
72
+ "end": "2026-11-02T21:02:30Z",
73
+ "event_counts": {
74
+ "quota": 42,
75
+ "tokens": 2,
76
+ "usage": 2,
77
+ "progress": 1
78
+ },
79
+ "largest_event_gap": {
80
+ "seconds": 5.004,
81
+ "from": "2026-11-02T21:02:01.805Z",
82
+ "to": "2026-11-02T21:02:06.809Z",
83
+ "from_line": 573128,
84
+ "to_line": 573129,
85
+ "from_kind": "quota",
86
+ "to_kind": "quota"
87
+ },
88
+ "periodic_quota_count": 21,
89
+ "largest_periodic_quota_gap_seconds": 5.014,
90
+ "task_events": []
91
+ },
92
+ {
93
+ "window": "review_667",
94
+ "start": "2026-11-02T21:31:30Z",
95
+ "end": "2026-11-02T21:33:00Z",
96
+ "event_counts": {
97
+ "quota": 30,
98
+ "tokens": 6,
99
+ "usage": 8,
100
+ "progress": 3,
101
+ "task": 6,
102
+ "envelope": 12,
103
+ "attach": 12,
104
+ "state": 5,
105
+ "turn_start": 3,
106
+ "turn_end": 2,
107
+ "agent_cli": 1,
108
+ "cohort": 1,
109
+ "split": 1,
110
+ "overlap": 1
111
+ },
112
+ "largest_event_gap": {
113
+ "seconds": 4.818,
114
+ "from": "2026-11-02T21:31:42.684Z",
115
+ "to": "2026-11-02T21:31:47.502Z",
116
+ "from_line": 573825,
117
+ "to_line": 573826,
118
+ "from_kind": "quota",
119
+ "to_kind": "progress"
120
+ },
121
+ "periodic_quota_count": 14,
122
+ "largest_periodic_quota_gap_seconds": 5.225,
123
+ "task_events": [
124
+ {
125
+ "at": "2026-11-02T21:31:47.586Z",
126
+ "task": 668,
127
+ "event": "accepted",
128
+ "source_line": 573827
129
+ },
130
+ {
131
+ "at": "2026-11-02T21:32:03.597Z",
132
+ "task": 667,
133
+ "event": "done",
134
+ "source_line": 573849
135
+ },
136
+ {
137
+ "at": "2026-11-02T21:32:03.721Z",
138
+ "task": 667,
139
+ "event": "memory reference started",
140
+ "source_line": 573851
141
+ },
142
+ {
143
+ "at": "2026-11-02T21:32:42.925Z",
144
+ "task": 667,
145
+ "event": "approved",
146
+ "source_line": 573897
147
+ },
148
+ {
149
+ "at": "2026-11-02T21:32:43.509Z",
150
+ "task": 670,
151
+ "event": "ready",
152
+ "source_line": 573904
153
+ },
154
+ {
155
+ "at": "2026-11-02T21:32:43.542Z",
156
+ "task": 670,
157
+ "event": "assigned",
158
+ "source_line": 573905
159
+ }
160
+ ]
161
+ },
162
+ {
163
+ "window": "review_668",
164
+ "start": "2026-11-02T21:49:30Z",
165
+ "end": "2026-11-02T21:51:00Z",
166
+ "event_counts": {
167
+ "quota": 22,
168
+ "progress": 6,
169
+ "tokens": 9,
170
+ "usage": 9,
171
+ "task": 5,
172
+ "envelope": 11,
173
+ "attach": 4,
174
+ "state": 5,
175
+ "turn_start": 3,
176
+ "turn_end": 2,
177
+ "stale": 1,
178
+ "cohort": 1,
179
+ "split": 1,
180
+ "overlap": 1
181
+ },
182
+ "largest_event_gap": {
183
+ "seconds": 5.015,
184
+ "from": "2026-11-02T21:50:01.150Z",
185
+ "to": "2026-11-02T21:50:06.165Z",
186
+ "from_line": 574463,
187
+ "to_line": 574464,
188
+ "from_kind": "quota",
189
+ "to_kind": "quota"
190
+ },
191
+ "periodic_quota_count": 13,
192
+ "largest_periodic_quota_gap_seconds": 5.336,
193
+ "task_events": [
194
+ {
195
+ "at": "2026-11-02T21:50:12.802Z",
196
+ "task": 668,
197
+ "event": "done",
198
+ "source_line": 574466
199
+ },
200
+ {
201
+ "at": "2026-11-02T21:50:12.936Z",
202
+ "task": 668,
203
+ "event": "memory reference started",
204
+ "source_line": 574468
205
+ },
206
+ {
207
+ "at": "2026-11-02T21:50:33.167Z",
208
+ "task": 668,
209
+ "event": "approved",
210
+ "source_line": 574500
211
+ },
212
+ {
213
+ "at": "2026-11-02T21:50:33.760Z",
214
+ "task": 669,
215
+ "event": "ready",
216
+ "source_line": 574507
217
+ },
218
+ {
219
+ "at": "2026-11-02T21:50:33.782Z",
220
+ "task": 669,
221
+ "event": "assigned",
222
+ "source_line": 574508
223
+ }
224
+ ]
225
+ }
226
+ ],
227
+ "nearby_proposal_context": {
228
+ "gap_seconds": 68.894,
229
+ "from": "2026-11-02T20:56:34.474Z",
230
+ "to": "2026-11-02T20:57:43.368Z",
231
+ "from_line": 572993,
232
+ "to_line": 572994,
233
+ "end_kind": "memory_brief",
234
+ "task": 668,
235
+ "native_items": 4,
236
+ "fail_items": 4,
237
+ "legacy_items": 0,
238
+ "following_offer_at": "2026-11-02T20:57:43.369Z",
239
+ "interpretation": "A nearby gap ending at a brief record, not a measured memory-call duration or proven cause."
240
+ }
241
+ }
@@ -0,0 +1,20 @@
1
+ # Timed control-write stall windows, 2026-11-03
2
+
3
+ Task #671, issue #1126, Refs #1078. Read-only correlation of the running hub's hub.log and events.jsonl, all timestamps UTC on 2026-11-02. No request was sent to the daemon and its database/configuration were not opened or changed. Only metadata, counts and timestamps are retained here and in the [aggregate JSON](2026-11-03-control-write-stall-windows.json).
4
+
5
+ The records are wall-clock observations, not an event-loop-delay measurement. A long gap is consistent with an unavailable loop, process suspension or blocked logging; it does not identify a blocking function. Conversely, periodic callbacks continuing to record rules out a single uninterrupted block spanning that entire interval, without ruling out short blocks or asynchronous waits.
6
+
7
+ | Reported stall | Recorded activity | Interpretation and limit |
8
+ | --- | --- | --- |
9
+ | Proposes around 20:56:04-20:56:34 | Task 667 proposed at 20:55:33.866, linked at .895, assigned at .916. Its assigned-status envelope was recorded at .923. The next event, its Jcode task-offer envelope, is at 20:56:34.160, a 60.237 s gap (events lines 572984-572985). Jcode busy at .282 and turn_start at .339; conductor proposal audit at .368; task 668 proposed at .414, linked at .445 and assigned at .466. | The gap begins before the supplied 30-second window and lies between assignment and offer publication. No event of any kind was recorded inside it. The periodic Claude quota stream also has a 65.133 s gap. This is evidence to investigate that delivery/publication boundary, not proof of a specific snapshot, Git, memory or native-adapter cause. |
10
+ | Propose around 21:01-21:02 | No propose is recorded in 21:00:45-21:02:30. The nearest earlier one is task 670 at 21:00:17.480, linked .524 and blocked .555; conductor audit .572. Claude native turn end/turn restart occur at 21:00:24, then another end at 21:00:30. At 21:01:33.464, hub.log reports memory sync refused by the configured privacy policy for 20 long-term entries. | The supplied proposal cannot be matched in this window from these records. Quota callbacks continue about every 5 s, with maximum Claude interval 5.014 s and maximum all-event gap 5.004 s in the selected range. The memory-sync refusal is concurrent evidence only; no duration or request correlation establishes it as the cause. |
11
+ | Review of task 667 around 21:32 | Review-stage SDLC advice at 21:31:59.453; Claude busy/turn_start at 21:32:02.845/.900. Task done at 03.597, memory-reference bookkeeping at 03.721. Jcode turn ends at 10.639, restarts at 10.734 and ends at 14.939. Approval-stage SDLC advice at 42.894; approved event at 42.925, followed by notices and release/assignment of task 670. A memory-sync privacy refusal was recorded earlier at 21:31:33.465. | Quota and other events continue during the wait: maximum selected all-event gap 4.818 s; maximum Claude quota interval 5.225 s. A continuous 30-second blocked loop is not shown. External metadata/readiness waits remain plausible, but no per-call start/end span identifies them. The memory-reference event is board bookkeeping, not a measured capture duration. |
12
+ | Review of task 668 around 21:50 | Done at 21:50:12.802, memory-reference bookkeeping at .936, review envelope at 13.424, Claude busy/turn_start at 13.669/.734. Codex turn ends at 16.972, restarts at 17.603 and ends at 26.495. At 17.602, hub.log reports snapshot burst budget exhausted and boundary evidence unknown. Approval-stage SDLC advice at 33.149; approved at 33.167, followed by release/assignment of task 669. | Maximum selected all-event gap 5.015 s; maximum Claude quota interval 5.336 s. The snapshot refusal is observable, but the log has no duration and cannot account for a 30-second wait by itself. Periodic activity continues. |
13
+
14
+ Wider proposal context adds a second gap: task 668's assigned-status envelope at 20:56:34.474 is followed by no event until a memory_brief record at 20:57:43.368 (68.894 s, lines 572993-572994). That record reports four native items, all fail notes, without their identities or content. Its offer follows at .369 and the conductor audit at .563. This is a candidate memory-brief boundary, not a measured 68.894-second memory call. The existing plan-fail lookup is evaluated before Briefs.forTask, so the new instrumentation wraps that lookup as well as the brief itself; its existing reads and limits are unchanged.
15
+
16
+ No check start/end, digest/inference duration, or Git start/end record in these selected windows identifies a slow operation. That is missing instrumentation, not proof those operations did not run. The first proposal and the two reviews exhibit different recorded behavior and should not be assigned one cause merely because callers saw the same timeout.
17
+
18
+ Source inspection found no event-loop lag probe or correlated control receive/reply spans in the 0.27.0 path. The change for #1126 adds a bounded monotonic probe, metadata-only request and phase spans, and a slow-request hub.log line. It must retain recently completed intervals: a synchronous blocking span can finish before the delayed timer callback runs. Still-open asynchronous spans are reported as overlapping waits, not as proven CPU causes. Unknown/untracked occupancy remains unknown. Raw request, task prose, paths, actor/session/rid identifiers and external output stay out of telemetry.
19
+
20
+ The new instrumentation has not been activated on the live daemon by this task. Its purpose is to name the observed boundary on the next naturally occurring stall; it does not retroactively prove the cause of these four reports or change a timeout to hide one.