@staix/agent-hub 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/README.md +15 -7
- package/docs/agent-notes/README.md +13 -0
- package/docs/agent-notes/adapters.md +7 -3
- package/docs/agent-notes/budget.md +1 -0
- package/docs/agent-notes/bus.md +10 -4
- package/docs/agent-notes/daemon.md +16 -8
- package/docs/agent-notes/local-worker.md +1 -0
- package/docs/agent-notes/tasks.md +10 -4
- package/docs/agent-notes/tests.md +8 -4
- package/docs/design/adapters.md +108 -0
- package/docs/design/agent-hub-architecture.md +58 -0
- package/docs/design/bus.md +147 -1
- package/docs/design/task-board.md +100 -0
- package/docs/dogfood.md +29 -8
- package/docs/events.md +3 -0
- package/docs/memory.md +17 -1
- package/docs/operations.md +410 -86
- package/docs/profiles.md +35 -0
- package/docs/quickstart.md +25 -5
- package/docs/sdlc.md +1 -1
- package/docs/security.md +182 -62
- package/docs/smoke.md +13 -2
- package/docs/specs/2026-09-19-agent-hub-design.md +84 -14
- package/docs/specs/2026-09-19-multi-project-design.md +7 -2
- package/docs/specs/2026-10-12-office-view-design.md +86 -3
- package/docs/verification/2026-11-03-0.30.0.md +54 -0
- package/docs/verification/2026-11-03-agy-1.4.12-launcher-nonce.md +42 -0
- package/docs/verification/2026-11-03-agy-1.4.12.md +90 -0
- package/docs/verification/2026-11-03-agy-tui-close.md +49 -0
- package/docs/verification/2026-11-03-grok-1.0.62-t0.md +150 -0
- package/docs/verification/2026-11-03-pi-150-compat.md +40 -0
- package/docs/verification/2026-11-03-pi-title-api.md +26 -0
- package/docs/verification/2026-11-03-qwen-0265-acp.md +55 -0
- package/docs/verification/2026-11-03-qwen-0265-dual-output.md +40 -0
- package/docs/verification/2026-11-04-1171-channel-client-evidence.md +31 -0
- package/docs/verification/2026-11-05-0.31.0.md +182 -0
- package/docs/verification/2026-11-05-claude-implementer-2.1.318.md +70 -0
- package/docs/verification/2026-11-05-hardcoded-values-classification-rules.md +257 -0
- package/docs/verification/2026-11-05-hardcoded-values-ratchet.md +55 -0
- package/docs/verification/2026-11-06-rooms-presence-cost.md +152 -0
- package/docs/verification/claude-shell-wrapper-native.py +1 -1
- package/docs/verification/dogfood/2026-11-03.md +3095 -0
- package/docs/verification/pi-150-model-free.ts +57 -0
- package/docs/verification/pi-150-native.mjs +21 -0
- package/docs/verification/pi-150-title-api.mjs +31 -0
- package/docs/verified.json +14 -14
- package/package.json +3 -4
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +4565 -3617
- package/src/adapters/acp.ts +5 -4
- package/src/adapters/channel-peer.ts +72 -3
- package/src/adapters/claude-channel-evidence.ts +52 -0
- package/src/adapters/claude-channel.ts +61 -18
- package/src/adapters/claude-implementer.ts +29 -7
- package/src/adapters/claude-print-child.ts +12 -2
- package/src/adapters/codex-appserver.ts +13 -12
- package/src/adapters/compat.ts +13 -13
- package/src/adapters/definitions/builtin-metadata.ts +13 -13
- package/src/adapters/definitions/qwen.ts +1 -0
- package/src/adapters/local-worker.ts +82 -23
- package/src/adapters/pi.ts +140 -16
- package/src/adapters/registry-types.ts +16 -0
- package/src/adapters/registry.ts +4 -0
- package/src/adapters/reviewer-print.ts +50 -11
- package/src/broker/server.ts +44 -13
- package/src/broker/store.ts +38 -8
- package/src/cli/answer-args.ts +50 -0
- package/src/cli/attention.ts +17 -2
- package/src/cli/autonomy.ts +66 -1
- package/src/cli/backlog-return-args.ts +37 -0
- package/src/cli/console-question.ts +110 -0
- package/src/cli/console-state.ts +82 -17
- package/src/cli/console.ts +54 -1
- package/src/cli/handoff-args.ts +15 -5
- package/src/cli/handoff-output.ts +15 -2
- package/src/cli/help.ts +10 -5
- package/src/cli/identity.ts +21 -4
- package/src/cli/main.ts +167 -16
- package/src/cli/memory.ts +107 -3
- package/src/cli/output.ts +29 -6
- package/src/cli/pet.ts +4 -4
- package/src/cli/results-args.ts +30 -0
- package/src/cli/runtime-version-warning.ts +50 -0
- package/src/cli/status-lines.ts +41 -1
- package/src/cli/tail-render.ts +1 -0
- package/src/cli/upgrade-interactive.ts +14 -2
- package/src/cli/worktree-tidy.ts +158 -0
- package/src/cli/worktrees-output.ts +43 -0
- package/src/hub/action-class.ts +9 -1
- package/src/hub/board.ts +396 -20
- package/src/hub/bus.ts +497 -57
- package/src/hub/completion-detail.ts +50 -0
- package/src/hub/completions-store.ts +168 -0
- package/src/hub/completions.ts +120 -0
- package/src/hub/conductor.ts +4 -3
- package/src/hub/config-apply.ts +8 -5
- package/src/hub/config-reload.ts +10 -1
- package/src/hub/control-client.ts +40 -4
- package/src/hub/daemon.ts +1795 -142
- package/src/hub/delivery-failure.ts +14 -0
- package/src/hub/delivery-hints.ts +14 -4
- package/src/hub/delivery-journal.ts +751 -42
- package/src/hub/delivery-superseded.ts +4 -1
- package/src/hub/dogfood-read.ts +62 -9
- package/src/hub/envelope.ts +3 -3
- package/src/hub/events.ts +6 -0
- package/src/hub/handoff.ts +145 -6
- package/src/hub/hub-tools.ts +66 -11
- package/src/hub/manager.ts +67 -3
- package/src/hub/memory-policy.ts +44 -1
- package/src/hub/memory-sync-policy.ts +109 -0
- package/src/hub/memory-sync-state.ts +145 -0
- package/src/hub/no-writes.ts +1 -1
- package/src/hub/operational-settings.ts +11 -2
- package/src/hub/operational-view.ts +12 -1
- package/src/hub/peer-doing.ts +33 -3
- package/src/hub/peers.ts +32 -2
- package/src/hub/planning.ts +6 -1
- package/src/hub/question-desk.ts +201 -0
- package/src/hub/question-detach.ts +6 -0
- package/src/hub/questions.ts +260 -0
- package/src/hub/research-evidence.ts +106 -0
- package/src/hub/restart.ts +14 -0
- package/src/hub/review-anchor.ts +181 -0
- package/src/hub/review-brief.ts +13 -0
- package/src/hub/review-comments.ts +115 -0
- package/src/hub/review-findings.ts +7 -2
- package/src/hub/review-material.ts +76 -0
- package/src/hub/routing.ts +3 -1
- package/src/hub/settings.ts +3 -0
- package/src/hub/task-sweep.ts +2 -0
- package/src/hub/tasks.ts +607 -71
- package/src/hub/ui.ts +2 -0
- package/src/hub/worktree-prs.ts +100 -0
- package/src/hub/worktree-shelf.ts +246 -0
- package/src/memory/capture.ts +5 -2
- package/src/pet/config.ts +25 -13
- package/src/pi/extension.ts +43 -3
- package/src/rooms/link.ts +209 -21
- package/src/rooms/remote-peer.ts +186 -19
- package/src/rooms/service.ts +338 -22
- package/src/rooms/store.ts +437 -65
- package/src/rooms/wire.ts +24 -6
- package/src/ui/index.html +271 -17
- package/src/ui/needs.ts +10 -4
- package/src/ui/office-model.ts +64 -8
- package/src/ui/office-space.ts +1 -0
- package/src/ui/plugin-questions.ts +56 -0
- package/src/ui/plugin-results.ts +81 -0
- package/src/ui/plugin.ts +219 -28
- package/src/pet/window.html +0 -114
- package/src/pet/window.jxa.js +0 -122
- package/src/pet/window.ts +0 -154
|
@@ -803,7 +803,9 @@ atomically install that candidate against its persisted pin. Replaying an old
|
|
|
803
803
|
candidate must never reset the minimum epoch or a grace deadline.
|
|
804
804
|
|
|
805
805
|
A frame's public header is `{v,type,room,epoch,sender,recipients,seq}` plus nonce,
|
|
806
|
-
ciphertext and signature.
|
|
806
|
+
ciphertext and signature. Presence may add the signed optional `ephemeral: true`
|
|
807
|
+
header (#1204 T1); every other value for that optional field refuses. Recipients
|
|
808
|
+
are hub fingerprints, not local peer ids.
|
|
807
809
|
The body is opaque encrypted bytes, including any eventual local addressing,
|
|
808
810
|
kind, trace and text. Frame AAD is exactly UTF-8 `room|epoch|sender|seq`. A
|
|
809
811
|
sender-specific AES key is HKDF-derived from the epoch root and room/epoch/sender/
|
|
@@ -974,7 +976,14 @@ survive queue ACKs/restart: the last accepted digest or an identical retained ol
|
|
|
974
976
|
packet is idempotent without requeueing; conflicting or
|
|
975
977
|
unknown lower sequences refuse. FIFO uses SQLite admission row order, never lexical
|
|
976
978
|
sequence strings or clock ties. Full queues refuse new packets without evicting
|
|
977
|
-
accepted ones.
|
|
979
|
+
accepted durable ones. Ephemeral presence replaces only prior ephemeral rows of
|
|
980
|
+
that sender and retains only currently ready recipients; disconnect/restart
|
|
981
|
+
removes those recipients, while sender floors and durable work remain. The same
|
|
982
|
+
queue/byte caps still apply. A frame-level `queue_full` includes its verified
|
|
983
|
+
digest. Links retain the sealed frame and retry after 250 ms, doubling to 30 s,
|
|
984
|
+
with one frame awaiting storage acceptance so later sequences cannot overtake it.
|
|
985
|
+
Applications stay in the local outbox; T2 owns receipt persistence and deadline/
|
|
986
|
+
restart replay changes. Prior-epoch grace may expire a packet before its ordinary TTL.
|
|
978
987
|
|
|
979
988
|
One packet per recipient socket is in flight. `{v:1,type:"received",digest}` removes
|
|
980
989
|
only that identity from the packet's remaining recipients, then returns
|
|
@@ -1114,6 +1123,16 @@ not project config or synced memory. A hub stop closes links and retains members
|
|
|
1114
1123
|
A person may explicitly import a pinned signed roster to reactivate a left room;
|
|
1115
1124
|
automatic link traffic cannot reactivate it.
|
|
1116
1125
|
|
|
1126
|
+
|
|
1127
|
+
The optional ephemeral field is used only after an opted-in connection receives
|
|
1128
|
+
`ephemeral: true` in the broker ready control. The upgrade header is
|
|
1129
|
+
`x-agent-hub-ephemeral: 1`; brokers preserve the old closed ready shape for
|
|
1130
|
+
clients that do not opt in. Missing advertisement means legacy presence frames,
|
|
1131
|
+
with dedupe/backoff still active. The broker withholds ephemeral frames from older member hubs
|
|
1132
|
+
until upgraded; application chat stays wire-compatible. See the [compatibility
|
|
1133
|
+
ceiling](../design/bus.md#room-wire-compatibility-1204-t1); #1204 T4 owns full codec
|
|
1134
|
+
feature negotiation.
|
|
1135
|
+
|
|
1117
1136
|
### Durable state and outbound link
|
|
1118
1137
|
|
|
1119
1138
|
`<hub-state>/rooms/rooms.db` is schema version 1, SQLite DELETE/EXTRA with exclusive
|
|
@@ -1152,9 +1171,12 @@ at most 8 pending packets/2 MiB per link, 1 MiB packet/backpressure limits and a
|
|
|
1152
1171
|
minutes and do not block local work. Stop, leave, replacement and rotation fence
|
|
1153
1172
|
all awaited work by link generation.
|
|
1154
1173
|
|
|
1174
|
+
With latest-per-sender coalescing, A awaiting C can have its queued request replaced by A's broadcast reply to B, so C sees the request only on A's next state change or reconnect; task #736 idle refresh or per-(sender,recipient) coalescing is the upgrade path.
|
|
1175
|
+
|
|
1155
1176
|
Presence is an encrypted, signed frame containing only exposed peer ids and closed
|
|
1156
1177
|
idle/busy/paused/offline states. It is sent on connection and coalesced peer-state
|
|
1157
|
-
changes,
|
|
1178
|
+
changes, skipping identical snapshots except explicit peer refresh exchanges,
|
|
1179
|
+
never titles, bodies, private task context or credentials. Unknown payload
|
|
1158
1180
|
types and unexposed ids refuse before replay commit. Broker ACKs are transport
|
|
1159
1181
|
facts only. A canonical room/recipient-bound frame that is refused or stale is
|
|
1160
1182
|
recorded in a durable metadata-only drop ledger before transport retirement ACK.
|
|
@@ -1256,15 +1278,20 @@ exposed local peer's queue**. It does not mean native or model execution. Person
|
|
|
1256
1278
|
views say **completed (admitted)**. Broker `stored` means accepted ciphertext
|
|
1257
1279
|
only; a transport retirement ACK is not application completion.
|
|
1258
1280
|
|
|
1259
|
-
|
|
1281
|
+
Schema5 retains a nullable canonical outgoing content hash. Cross-root reuse of
|
|
1282
|
+
a retained application requires matching content and peer/recipient, no disposition
|
|
1283
|
+
or permanent hold, and inherited creation/expiry times; legacy NULL refuses it.
|
|
1284
|
+
Schema5 of the private `rooms.db` migrates schema1 through 4 without replacing identity,
|
|
1260
1285
|
pins, counters, floors or retained traffic. A receiver commits its crypto inbox,
|
|
1261
1286
|
then application `pending -> dispatching` before publishing into the separate
|
|
1262
1287
|
Bus journal. A crash or failure in that cross-DB publication window becomes
|
|
1263
|
-
`needs_review`, with no automatic republish or fabricated receipt.
|
|
1264
|
-
`dispatching`/`accepted` rows
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1288
|
+
`needs_review`, with no automatic receiver republish or fabricated receipt.
|
|
1289
|
+
Sender `dispatching`/`accepted` rows recover from validated durable intent under
|
|
1290
|
+
the same application and delivery ids, retaining their original queue expiry.
|
|
1291
|
+
A valid late signed receipt may settle an unresolved ordinary sender hold;
|
|
1292
|
+
invocation uncertainty remains person-settled. Person dispositions and invalidated
|
|
1293
|
+
recipient bindings remain authoritative. Signed
|
|
1294
|
+
remote safe refusals are terminal; native poison-envelope policy is unchanged.
|
|
1268
1295
|
|
|
1269
1296
|
Signed seq/floors are the permanent primary replay protection. Duplicate seqs
|
|
1270
1297
|
are retired without a second admission; a known identical completed application
|
|
@@ -1275,6 +1302,9 @@ oldest settled rows are evicted first. Pending, dispatching and unresolved
|
|
|
1275
1302
|
`needs_review` are never evicted. An all-unsettled cap refuses with the room and
|
|
1276
1303
|
count. Outside retention or after settled eviction, there is no historical
|
|
1277
1304
|
app-id dedupe claim; an old signed frame is still refused by its seq floor.
|
|
1305
|
+
Automatic resend can reach this settled-eviction ceiling and repeat admission
|
|
1306
|
+
under a fresh ciphertext sequence: exactly once within dedupe ceiling. Pinning
|
|
1307
|
+
retryable identities or #737 receipt confirmation is the upgrade path.
|
|
1278
1308
|
|
|
1279
1309
|
The trace high-water mark is kept for the tombstone retention (30 days / 10,000
|
|
1280
1310
|
per room, settled rows evicted first); outside it there is no historical trace
|
|
@@ -1288,16 +1318,17 @@ Offline Bus queues count toward the 200-per-room ceiling before transport starts
|
|
|
1288
1318
|
`hub_send` refuses beyond it. Original host deadlines survive handoff and restart.
|
|
1289
1319
|
Unknown legacy deadlines fail closed to `needs_review`. Machine-local
|
|
1290
1320
|
`rooms.ack_timeout_s` defaults to 600 (1..86,400); `rooms.queue_ttl_h` defaults to
|
|
1291
|
-
24 (1..168). A single deadline-driven host timer handles
|
|
1292
|
-
|
|
1321
|
+
24 (1..168). A single deadline-driven host timer handles ACK retries and queue
|
|
1322
|
+
expiry. Only validated durable sender intent is retried automatically; missing
|
|
1323
|
+
or corrupt local evidence remains held. Explicit terminal-history retries without
|
|
1293
1324
|
recipient proof refuse; the person can author a fresh message deliberately.
|
|
1294
1325
|
An expired or missing original enqueue deadline also refuses a person retry
|
|
1295
1326
|
before any disposition is recorded; a retry never invents a fresh TTL.
|
|
1296
1327
|
|
|
1297
1328
|
The ACK deadline starts at durable application handoff, before a broker `stored`
|
|
1298
|
-
reply, and is never extended by that reply.
|
|
1299
|
-
|
|
1300
|
-
|
|
1329
|
+
reply, and is never extended by that reply. Its expiry schedules another attempt
|
|
1330
|
+
under the same application id, without resetting the original queue TTL. Queue
|
|
1331
|
+
expiry or a permanent refusal ends automatic sending. Known pre-admission capacity or journal-unavailable refusals retain
|
|
1301
1332
|
their pending plaintext for the next online/disposition retry without preventing
|
|
1302
1333
|
later room packets and receipts from being processed. Status reads apply no
|
|
1303
1334
|
disposition. Settled chat plaintext rows are pruned independently of presence
|
|
@@ -2782,6 +2813,12 @@ push `accepted` and show none of them.
|
|
|
2782
2813
|
sources add protocol 15 (0.12.17 through 0.12.19); the transition from a real
|
|
2783
2814
|
0.12.19 hub is not yet proven.
|
|
2784
2815
|
|
|
2816
|
+
## Amendment: inherited Claude channel marker requires direct-parent evidence (issue #1171)
|
|
2817
|
+
|
|
2818
|
+
- `AGENTHUB_CHANNEL=1` alone does not enable push. Claude Code child processes, including `daemon run` and `bg-spare`, inherit it without the development-channel flag. The plugin's direct parent must have a bounded, readable `ps -ww` row whose leading argv tokens are `claude --dangerously-load-development-channels` and one exact supported target (`plugin:agent-hub@agent-hub` or `server:agent-hub`). Print/background/daemon forms, a repeated development-channel flag, unreadable or malformed output, a changed parent pid, and unknown targets fail closed to tools-only.
|
|
2819
|
+
- The classifier is conservative because `ps` renders a flattened command line; matching is restricted to the prefix and remaining tokens are checked for known mode-changing forms. This is same-user process observation, not authentication. No client-side Claude channel capability was found in the inspected Claude Code 2.1.318 client path, and the server's own advertised capability is not proof. Unknown evidence keeps messages queued for `hub_inbox`.
|
|
2820
|
+
- `status.json` reports `attachMode` and a closed `attachEvidence` label for an attached Claude peer; human `ahub status` shows the same pair. Older clients that omit the evidence field retain their prior attachment behavior and display `unreported`.
|
|
2821
|
+
|
|
2785
2822
|
## Amendment: channel queue visibility and explicit pull (issue #493)
|
|
2786
2823
|
|
|
2787
2824
|
- A channel session's `hub_inbox` reads the daemon queue through the same
|
|
@@ -3945,6 +3982,8 @@ run has no hub command lineage.
|
|
|
3945
3982
|
|
|
3946
3983
|
## Amendment: standalone attention window (#391 Task B, supersedes #280 dashboard pet)
|
|
3947
3984
|
|
|
3985
|
+
Historical surface, retired by #1012. Current presentation contract: [console surfaces](../design/agent-hub-architecture.md#console-presentation-surfaces).
|
|
3986
|
+
|
|
3948
3987
|
The #280 phase-4 dashboard pet is replaced by an optional standalone macOS JXA
|
|
3949
3988
|
window. Task B adds the window first; #391 Task A removes the existing in-page
|
|
3950
3989
|
character and retains shared attention counts/navigation. Terminal characters
|
|
@@ -6452,3 +6491,34 @@ Each pack supplies criterion ids in its rubric and exactly one advisory check en
|
|
|
6452
6491
|
## Amendment: research campaigns, experiment receipts and runner attestation (#930, #932, #1018)
|
|
6453
6492
|
|
|
6454
6493
|
The implementation contract for #929 R1 and R3 and for #1018 is `docs/specs/2026-11-01-research-campaigns-design.md`: campaign, protocol, attempt and receipt schemas and bounds; the provenance levels `declared`, `host-observed`, `runner-attested` and `person-attested`; the Board tables; the person-only activation, attestation and runner registration; the `ahub study` and `hub_study_*` / `hub_experiment_*` wire names; the `research_records` recovery feature; and the delivery slices (#596 to #602). Slices that must differ amend that document in their own PR.
|
|
6494
|
+
|
|
6495
|
+
## Amendment: anchored review packages (#1056)
|
|
6496
|
+
|
|
6497
|
+
The current contract is recorded in [Task Board](../design/task-board.md#anchored-review-packages-1056). Optional finding anchors use the published acon review shape, with stricter hub UTF-8 write bounds. Person drafts are board-local until one explicit console-authorized Send creates one immutable package and one count-only history entry. Owner completion can claim sent comment IDs resolved without claiming person verification. Placement is recomputed over guarded task-scoped Git/projection material; stored anchors never move.
|
|
6498
|
+
|
|
6499
|
+
The acon plugin uses `ActionMeta` and `host.ui.review` from the published DOM-free 0.1.3 contract as types only; there is no new runtime dependency or renderer. A private/PII view withholds text, and trusted package markers exclude quote/body content from logs, tails, incoming labels and memory capture without making a public task private. Recovery sections are optional for older snapshots. The owner's live document package-format confirmation remains a separate manual check; fixture and code evidence do not claim that confirmation.
|
|
6500
|
+
|
|
6501
|
+
### Receipt publication ordering (#1204 T2)
|
|
6502
|
+
|
|
6503
|
+
A chat ciphertext transport ACK follows the signed receipt ciphertext's local
|
|
6504
|
+
durable RoomStore outbox commit. The receipt replays after reconnect or restart
|
|
6505
|
+
until the broker confirms storage. Waiting for broker storage before the chat ACK
|
|
6506
|
+
would deadlock at capacity one. No receipt or native completion is inferred from
|
|
6507
|
+
socket send alone.
|
|
6508
|
+
ACK after durable local commit of either the receipt or the inbox entry.
|
|
6509
|
+
Deferred application admission retains the durable crypto inbox entry, ACKs the
|
|
6510
|
+
chat to free broker capacity, and later commits its final receipt to the same
|
|
6511
|
+
durable outbox when admission resumes.
|
|
6512
|
+
|
|
6513
|
+
A session keeps its refresh request pending for every asked recipient until a
|
|
6514
|
+
validated presence from that member arrives. Later non-reply snapshots retain
|
|
6515
|
+
requestReply while anyone is pending; replies never carry requestReply. The set
|
|
6516
|
+
is bounded by the current roster and resets at reconnect or membership change.
|
|
6517
|
+
|
|
6518
|
+
Room application retries preserve the application id, canonical delivery id and
|
|
6519
|
+
original queue TTL, using a fresh authenticated ciphertext sequence where needed.
|
|
6520
|
+
The ACK timeout schedules resend rather than uncertainty; queue expiry or a
|
|
6521
|
+
permanent refusal remains inspectable. A signed late receipt may settle an
|
|
6522
|
+
unresolved ordinary remote hold once without overriding a person disposition.
|
|
6523
|
+
Invocation uncertainty retains its person-only ledger hold. Receiver application
|
|
6524
|
+
deduplication, current identity/privacy fences and all caps remain.
|
|
@@ -99,8 +99,13 @@ visual redesign, automatic merging and npm publication.
|
|
|
99
99
|
Same-machine cross-project routing is no longer out of scope: work that belongs to another project that runs agent-hub is registered on that project's board.
|
|
100
100
|
|
|
101
101
|
- **Target.** `project` names a project in the machine registry (its canonical root or its id). An unregistered target, the caller's own project and a target whose daemon is not running are refused, the last with the person's action (`ahub up` in that project). Nothing is queued.
|
|
102
|
-
- **Who and what.** The person (`ahub task handoff --project <root|id> [<class>] <title...> [--path <p>]... [--issue <n>] [--task <n>] [--detail <text>]`), or a configured planner or the conductor (`hub_task_handoff`). A feature or behavior change first needs a spec issue in the target repository, passed as `issue`; a mechanical chore goes straight to a task. The request is closed (unknown fields refused), bounded (8 KiB whole) and repository-relative for paths.
|
|
102
|
+
- **Who and what.** The person (`ahub task handoff --project <root|id> [<class>] <title...> [--path <p>]... [--issue <n>] [--task <n>] [--detail <text>] [--duplicate-ok <reason>]`), or a configured planner or the conductor (`hub_task_handoff`). A feature or behavior change first needs a spec issue in the target repository, passed as `issue`; a mechanical chore goes straight to a task. The request is closed (unknown fields refused), bounded (8 KiB whole) and repository-relative for paths.
|
|
103
103
|
- **Transport.** The origin's daemon reads the target's control descriptor (same machine user) and sends `task_handoff` as a console-role control message with origin `{ projectId, peer, taskId? }`. The target's `Tasks` creates an ownerless proposal made by the hub, with the origin recorded in `task_handoff_origin`; its own routing and planner take it from there. The origin peer has no identity or authority in the target: it is a record, never a roster peer.
|
|
104
104
|
- **Follow-back.** On accepted, in review, approved, declined and cancelled the target sends `task_handoff_event`; the origin records it in `task_handoff_outbound` and delivers one `kind: task` envelope to the requesting peer (`agent-hub task 123 approved: PR #N at <sha>`: an event name, a PR number and a full head, never target text). An origin that was down asks the target for the current state of its open handoffs when it starts (`task_handoff_states`). `ahub board --handoffs` and `hub_task_handoffs` list them.
|
|
105
|
+
- **Duplicates and cancel (#1175).** A handoff naming a spec issue (`issue`) that already has an open task on the target's board (proposed, backlog, in progress, in review or changes requested; a `[pii]` row is never named) is refused before any row exists, with the open task ids, unless the sender passes `duplicate_ok` (a reason of up to 300 characters, recorded in the task's detail). An issue number identifies work only together with its repository: `sdlc.repo`, `external {repo, issue}` (an imported backlog row) and a slug `refs.repo` that name another repository than the target's do not count. The target's configured, rostered conductor may cancel a handed-off task that nobody has accepted and that has no execution evidence, with a reason; the origin hears `cancelled` through the follow-back, never the reason. A target from before this check refuses `duplicate_ok` as an unknown field, which the sender reports as "upgrade the target hub or hand off without `duplicate_ok`".
|
|
106
|
+
- **Idempotent request (#1203 T1).** The origin mints a `handoffKey` (UUID v4) per request, or takes the one a retry passes (`--key`, `handoffKey`), and sends it in the `task_handoff` request body to a target that advertises `task_handoff_key`. The target stores it with a digest of what was asked in `task_handoff_origin` (unique per origin project) and writes the proposal and the origin row in one board transaction (`Board.proposeHandoff`). A key it already holds answers with that task (`replayed`) before the duplicate check and before any PII screen; the same key for a different request is refused. A timeout or a closed connection is not a refusal: the origin sends the same key once more, then asks the target by key (`task_handoff_by_key`, answered only to the asking project and only with the fields a live event carries), and otherwise reports the new refusal code `outcome_unknown`, naming the key to retry with. The origin records its outbound row from the reply or the by-key answer, never resetting a row that already exists.
|
|
107
|
+
- **Converging follow-back (#1203 T2).** Each `task_handoff_event` carries `seq`, the target task's flow revision (its history length), to an origin that advertises `task_handoff_seq`. The origin keeps the sequence of the last applied event in the outbound row and ignores an event whose `seq` is not newer: it changes nothing and sends no envelope, decided inside the one board write, so events that arrive out of order (each uses its own connection) cannot move a row backwards. An event without `seq` (an older target) applies as before. The origin's catch-up (`task_handoff_states`, which now also returns `seq`) runs at start, every 5 minutes and when a target's control descriptor changes, over every row that is not cancelled and, for an approved one, was updated within the last 7 days (a reviewer can withdraw an approval; the origin only learns of it through the sequence), with no 200-row cap and in requests of at most 200 task ids. `changes_requested` and `reopened` are events, sent only to an origin that advertises `task_handoff_seq`. A catch-up pass never overlaps another, never holds a board write and stops at shutdown. `ahub board --handoffs` still lists the 200 most recently changed rows; that cap is for display only.
|
|
108
|
+
- **Diagnostics and repair (#1203 T3).** Every failure is visible and repairable by the person. A connection to a target that fails is named by the error's code and never by its message: 4426 (the wire versions share no protocol) is `older_target` and says to upgrade whichever hub is older, 4404 (another hub or instance answers) is the new refusal code `mismatch` and says to check `ahub projects`, a connect timeout says the hub may be stuck (`ahub status`), and only an unreachable hub says "not running" with `ahub up`. A failed notify, catch-up pass or handoff writes one `hub.log` line per target and cause in each window (15 minutes), with a fixed cause phrase and never a task title or the target's text. `ahub task handoff --list` (the person's command, read-only) shows each handoff with its age since the last report and `reachable`, `unreachable` with its cause and next step, or `moved` (the project id is not in the machine registry: it was removed or its root changed, and the id is a hash of the root), read from the registry and the target's descriptor file without opening a connection. `ahub task handoff --sync` (the person or the conductor) runs a catch-up pass now and answers with the refreshed list; it waits for a pass already running and then runs its own, for at most 20 seconds (under the caller's 30 second control timeout, because the pass asks targets one after another): past that it answers with the list as it stands, `syncing: true` and the number of targets still pending, the pass goes on in the background, and the CLI prints "catch-up still running for N targets: run `ahub task handoff --list` in a minute". An agent gets the same list from `hub_task_handoffs` (now with `age`, `ageMs`, `reach` and `cause`) and cannot sync. A catch-up request that gets no usable reply (the target refused it, timed out or dropped the connection) is a failure like any other: its target reads `unreachable` with the cause "no answer to the state request" and the step `ahub status` in that project, one log line is written, and the earlier failure is not cleared. If the pass itself fails, `--sync` answers `synced: false` with that cause instead of `synced: true`.
|
|
109
|
+
- **Follow-back envelope (#1203 T1).** It carries `refs.handoff {project, task}` (the target's project and task) and no `refs.task`, so the bus never judges it against a local task that happens to have the same number; the one-line body is unchanged.
|
|
105
110
|
- **Privacy.** Refused during a private (PII) turn and for a `[pii]` task named with `task`; the target refuses text that matches a PII pattern or that its screen cannot clear. No memory, evidence or turn content crosses beyond the handoff fields.
|
|
106
|
-
- **Compatibility.** The additive daemon
|
|
111
|
+
- **Compatibility.** The additive daemon features `task_handoff` and, from #1203 T1, `task_handoff_key` and `task_handoff_seq` (the latter: a target sends `seq` and the two new events only to an origin that has it; an origin ignores a missing `seq`). `task_handoff_key` (an origin sends no key to a target without it and keeps the earlier behavior, a timeout there is `outcome_unknown` without a retry key, and the request is not repeated). Neither feature bumps the protocol: a new message type is answered as unknown by an older hub, and an optional field is ignored, except `duplicate_ok` and `handoffKey`, which an older target refuses as unknown fields (so the key is sent only to a target that advertises it). An older target is refused with a named "upgrade the target hub" error, and a recovery target without the label is refused while either handoff table holds a row.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: Office view of live agent work in the dashboard
|
|
3
3
|
date: 2026-10-12
|
|
4
4
|
project: agent-hub
|
|
5
|
-
status: phases 1-
|
|
5
|
+
status: phases 1-5 implemented (Flat and Isometric office, backlog wall, release docks and planner marks); AC9 live browser look remains unverified
|
|
6
6
|
issue: 264
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -55,7 +55,8 @@ asset is copied.
|
|
|
55
55
|
latch, the settle rule. No daemon change.
|
|
56
56
|
3. Optional snapshot fields `turn`, `checking`, `links` and what they draw.
|
|
57
57
|
4. The Isometric projection of the same model.
|
|
58
|
-
5. Backlog wall, release docks and the planner's desk,
|
|
58
|
+
5. Backlog wall, release docks and the planner's desk, from the board
|
|
59
|
+
planning fields that #263 and #469 added (decisions below).
|
|
59
60
|
|
|
60
61
|
Phase 1 decisions within the spec:
|
|
61
62
|
|
|
@@ -209,6 +210,73 @@ Phase 4 decisions within the spec:
|
|
|
209
210
|
- Existing theme tokens, public-view privacy, counts/placement classifications,
|
|
210
211
|
animations, reduced motion, keyboard activation and mode cookie remain.
|
|
211
212
|
|
|
213
|
+
Phase 5 decisions within the spec (designed 2026-11-03, hub task 311;
|
|
214
|
+
implemented by hub task 682, with AC9 live browser look still open):
|
|
215
|
+
|
|
216
|
+
- Phase 5 needs no daemon change. `ui_snapshot` already carries everything:
|
|
217
|
+
- every board task, backlog cards included, with `rank`, `priority`,
|
|
218
|
+
`reserved`, `release`, `pinned`, `plannedStart` and `deps` next to the
|
|
219
|
+
public title;
|
|
220
|
+
- `releases[]`, the `tasks.releaseList` rows, with `id`, `name` (already
|
|
221
|
+
`[withheld]` when not nameable), `state`, `order`, `cut` and the scope
|
|
222
|
+
`tasks[]` as `{ id, state, deps }`;
|
|
223
|
+
- `status.roleInfo[peer].flowRoles`, which names the planner.
|
|
224
|
+
The model reads these by allowlist. It never reads a release `goal`, `train`,
|
|
225
|
+
the `afterCut` lists, task `detail`, `lifecycle` or `codeGroup`, and the
|
|
226
|
+
marker test grows to cover them.
|
|
227
|
+
- **Backlog wall.** A room named "Backlog" before To do in the fixed room
|
|
228
|
+
order, with placement `room:backlog`. Today `counts.backlog` is counted and
|
|
229
|
+
placed nowhere; from phase 5 these tasks get placed.
|
|
230
|
+
- Cards are ordered by `rank` ascending (no rank last), then `priority`
|
|
231
|
+
ascending (none last), then id. The cap is 8 cards, as in every room; the
|
|
232
|
+
rest is "+N more", which sets the board's existing `backlog` state filter.
|
|
233
|
+
- A card shows its id and public title, like other room cards. It adds up to
|
|
234
|
+
three marks, each with a shape and text in the accessible name:
|
|
235
|
+
- the reserved peer's colour chip and name;
|
|
236
|
+
- a pin for `pinned`;
|
|
237
|
+
- "waits", when a dep is not approved or `plannedStart` is in the future
|
|
238
|
+
(the date only, never the time).
|
|
239
|
+
- The wall count equals `taskProgress(tasks).counts.backlog`, pinned by the
|
|
240
|
+
existing counts test.
|
|
241
|
+
- A pulled card moves from the wall to To do through the phase-2 transform
|
|
242
|
+
transition, with no new motion code.
|
|
243
|
+
- **Release docks.** A strip below the rooms, beside the Done shelf. It has
|
|
244
|
+
one dock per release in state `planning`, `active` or `frozen`, ordered by
|
|
245
|
+
`order` then id; `shipped` and `dropped` releases get none. The cap is 3
|
|
246
|
+
docks, then "+N releases", which switches the board's View to "By release".
|
|
247
|
+
- A dock shows the release name, its state as a word, `approved / scope`
|
|
248
|
+
from its `tasks[]`, and a thin bar of the same ratio. It also shows the
|
|
249
|
+
`cut` date when set.
|
|
250
|
+
- Cards are not duplicated into docks: a card stays in its room. A card in
|
|
251
|
+
a docked release carries the release's ordinal (1 to 3) as a small tag
|
|
252
|
+
with the name in its accessible name.
|
|
253
|
+
- Activating a dock sets the board's existing `task-release-filter` to that
|
|
254
|
+
release and scrolls to the board, as card activation does for its row.
|
|
255
|
+
- **Planner's desk.** The desk of each peer whose `flowRoles` include
|
|
256
|
+
`planner` gets a planner badge: a shape plus "planner" in its accessible
|
|
257
|
+
name. A count joins it: the backlog cards with no `rank` and no `reserved`,
|
|
258
|
+
that is, the cards still waiting for planning. A peer with no desk gets no
|
|
259
|
+
badge, and the count then appears on the wall's header. The planner is a
|
|
260
|
+
mark on the existing desk. It is not a separate desk and claims no seat.
|
|
261
|
+
- **Isometric.** The wall is an ordinary room tile and the docks are slab
|
|
262
|
+
tiles like the shelf, through the same `officeProject`. Phase 4's fit rule
|
|
263
|
+
applies: cards that do not fit are counted in "+N more".
|
|
264
|
+
- **Privacy.** A PII backlog card is already a `[pii]` stub in the snapshot;
|
|
265
|
+
its reserved chip and marks still show, because they carry ids only. A
|
|
266
|
+
release name that is not nameable stays `[withheld]`.
|
|
267
|
+
- **Page-size bound.** This replaces the issue's original 30 KB office budget,
|
|
268
|
+
which was historical (see the phase 4 accounting) and is long exceeded by
|
|
269
|
+
unrelated features. The served page is `renderDashboard().html` with the
|
|
270
|
+
models injected. Measured on main a51c8fc7 (2026-11-03): 259,254 bytes raw,
|
|
271
|
+
70,237 gzip; `src/ui/index.html` alone is 236,071 bytes.
|
|
272
|
+
- The phase-5 PR measures the served page at its merge base and at its head,
|
|
273
|
+
raw and gzip, and states both deltas in the PR body.
|
|
274
|
+
- Phase 5 may add at most 12,000 bytes raw and 3,500 bytes gzip. Beyond
|
|
275
|
+
that, the PR drops art polish first, then trims the dock bar, before it
|
|
276
|
+
asks the person to raise the bound.
|
|
277
|
+
- No standing page-size test is added. Other dashboard features grow the
|
|
278
|
+
same page, and a global cap would block them for an office budget.
|
|
279
|
+
|
|
212
280
|
## Verification
|
|
213
281
|
|
|
214
282
|
- `test/office-model.test.ts`: mapping fixture, counts equality with
|
|
@@ -239,8 +307,23 @@ Phase 4 decisions within the spec:
|
|
|
239
307
|
and overlap/cohort links against a real daemon, pins `PROTOCOL` (16) and
|
|
240
308
|
`EVENTS_SCHEMA` (1), and proves a PII task keeps its stub, refuses a
|
|
241
309
|
non-local owner and joins no link.
|
|
310
|
+
- Phase 5 (implemented with the model and renderer regression tests):
|
|
311
|
+
- wall placement and order (rank, priority, id) with the cap and "+N more";
|
|
312
|
+
- wall count equals `counts.backlog`;
|
|
313
|
+
- the reserved, pin and waits marks;
|
|
314
|
+
- dock selection by state and order with the 3-dock cap and the approved /
|
|
315
|
+
scope ratio;
|
|
316
|
+
- the release ordinal tag on cards;
|
|
317
|
+
- the planner badge and the unplanned count, including the no-desk fallback
|
|
318
|
+
to the wall header;
|
|
319
|
+
- the marker test extended to release `goal`, `train`, `afterCut`, task
|
|
320
|
+
`lifecycle` and `codeGroup`;
|
|
321
|
+
- in `test/office-view.test.ts`, "+N more", dock activation setting
|
|
322
|
+
`task-release-filter` and the "By release" switch, plus a pulled card
|
|
323
|
+
animating from the wall to To do.
|
|
242
324
|
- The live browser look (two agents working, both themes, console open) is
|
|
243
|
-
recorded in `docs/smoke.md` as unverified for phase 1.
|
|
325
|
+
recorded in `docs/smoke.md` as unverified for phase 1. #273 is closed, so
|
|
326
|
+
AC9's browser look stays with #264 itself.
|
|
244
327
|
|
|
245
328
|
|
|
246
329
|
## Merge review corrections
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# 0.30.0 release verification
|
|
2
|
+
|
|
3
|
+
This record covers release preparation and source review. It claims no installation, no running-hub upgrade to 0.30.0 and no live TUI launch.
|
|
4
|
+
|
|
5
|
+
## Candidate
|
|
6
|
+
|
|
7
|
+
Version 0.30.0, prepared from main 397b1bd7 (20 commits since v0.29.0, 7 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.29.0: #1160, #1159, #1158, #1157, #1156, #1155, #1153, #1150, #1151, #1149, #1152, #1148, #1146, #1142, #1141, #1140, #1138, #1139, #1136.
|
|
12
|
+
|
|
13
|
+
Each merged with `gh pr merge --squash --match-head-commit <head>` after a `hub_review` approval, with exact-head CI green on ubuntu and macOS (19 checks pass, 2 skipped, seeded guards included), no unresolved review thread and no pending change request. Approvals by claude unless named:
|
|
14
|
+
|
|
15
|
+
- #1136 (task 679, agent-mem 0.20.1) at 1346c687; #1138 (680, #1137) at 756d72e5; #1139 (325, #635 T0) at f83ea324; #1141 (681) at a283bf4a; #1151 (683, #1144) at 4930af65; #1152 (682, #264) at e6878d11; #1155 (687, #1154) at 6717f1a1; #1159 (691) at 15d25ae6; #1160 (692) at ea3ee6ab.
|
|
16
|
+
- After one changes_requested round each: #1153 (686, #1147) at fd8a3286; #1156 (688, #1057 T1-T2) at 58afb35b; #1157 (689, #1055) at bd79846b; #1158 (690, #1057 T3) at a56ff7f6.
|
|
17
|
+
- Approved by the person, since claude owned or the hub named the person as reviewer: #1140 (443) at 4b652581, #1142 (311, design) at 0f0e805c, #1149 (685, dogfood receipt) at aa20ae95.
|
|
18
|
+
- Task 684 shipped three PRs under one approval bound at #1146's head d303a050. #1148 and #1150 were read in that review at earlier heads (f281e23b, 3f19f9fc), then rebased for conflicts and merged at 26766aaa and 3da9d6d6 after their own exact-head CI. The commits added after the read are a one-line receipt wording fix (26766aaa, `docs/verification/2026-11-03-pi-150-compat.md`) and a regenerated bundle hunk (3da9d6d6, `plugins/agent-hub/server.js`, 3 lines); every other commit is the reviewed change rebased. These two are the only merges bound to an approval at an earlier head.
|
|
19
|
+
|
|
20
|
+
## Native acceptance receipts
|
|
21
|
+
|
|
22
|
+
Receipts added under `docs/verification/` since v0.29.0: `docs/verification/2026-11-03-agy-1.4.12-launcher-nonce.md`, `docs/verification/2026-11-03-agy-1.4.12.md`, `docs/verification/2026-11-03-agy-tui-close.md`, `docs/verification/2026-11-03-grok-1.0.62-t0.md`, `docs/verification/2026-11-03-pi-150-compat.md`, `docs/verification/2026-11-03-pi-title-api.md`, `docs/verification/2026-11-03-qwen-0265-acp.md`, `docs/verification/2026-11-03-qwen-0265-dual-output.md`, `docs/verification/dogfood/2026-11-03.md`, `docs/verification/pi-150-model-free.ts`, `docs/verification/pi-150-native.mjs`, `docs/verification/pi-150-title-api.mjs`.
|
|
23
|
+
|
|
24
|
+
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.30.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.
|
|
25
|
+
|
|
26
|
+
## Document review
|
|
27
|
+
|
|
28
|
+
`node scripts/check-docs.mjs --require-fresh` reported 14 stale documents. Each was read against `git log 0d0a362c..HEAD -- <its paths>` (`src/cli/help.ts` against its own stamp 3efa678d), the fixes went in as 8612cfd7, and all 14 were restamped at 8612cfd7:
|
|
29
|
+
|
|
30
|
+
- `README.md`: the Operations list names the worktree shelf; the report link points at this file.
|
|
31
|
+
- `docs/quickstart.md`: install line `#v0.30.0`, an "Upgrading to 0.30.0" section, the agent-mem pin 0.20.1 in two places, and an `ahub worktrees` row in the working-day table.
|
|
32
|
+
- `docs/operations.md`: 0.30.0 in the header and the protocol table (protocol unchanged, 16 through 17), agent-mem 0.20.1 in two places that still said 0.18.0, agy 1.4.12 verified with `AGY_CLI_DISABLE_AUTO_UPDATE=1`, a Settings row for `worktrees.quiet_days` and `worktrees.alert_over`, the PII row and `--no-optional-locks` notes in the shelf section, and an Office phase 5 paragraph.
|
|
33
|
+
- `docs/security.md`: agy 1.4.12 receipt, and a worktree shelf paragraph (removal only in the person's CLI, never forced; console-only overrides and refresh; the refusal list; PII rows).
|
|
34
|
+
- `src/cli/help.ts`: `tidy --confirm <fingerprint> [--json]`, which `main.ts` honours. `ahub worktrees` and `ahub title` were already listed and match.
|
|
35
|
+
- `docs/agent-notes/adapters.md`: agy 1.4.12, and the session-title writer rule (#1055).
|
|
36
|
+
- `docs/agent-notes/daemon.md`: the conductor frame of an incoming-label DOING row, the label audience and `session-title-inputs.json`, and a worktree shelf rule.
|
|
37
|
+
- `docs/agent-notes/tasks.md`: `hub_set_title` tool placement, and the plan-sources validation rule (#1144).
|
|
38
|
+
- `docs/agent-notes/tests.md`: the #1057 tests that cut `daemon.ts`, `index.html` and `sdlc.ts` by text.
|
|
39
|
+
- No change needed: `docs/agent-notes/README.md`, `benchmarks.md`, `budget.md`, `bus.md`, `local-worker.md` (each read; the commits in range do not change what they state).
|
|
40
|
+
|
|
41
|
+
## Checks
|
|
42
|
+
|
|
43
|
+
- `node scripts/check-docs.mjs --require-fresh`: `docs: OK (0 stale documents)` after the restamp at 8612cfd7.
|
|
44
|
+
- Full `scripts/check.sh` on dgx02 (`remote_dev.py verify`) at b39870aa (tree 4fef8b16): typecheck (`bun x tsc --noEmit`), the bundle check (`bun scripts/build.mjs --check`), `package: OK (770 files, @staix/agent-hub@0.30.0)`, `roles: OK`, and 11229 pass, 101 skip, 0 fail across 872 files; `check: OK`. Later commits on the release branch change only this report.
|
|
45
|
+
- The release PR's exact-head CI on ubuntu and macOS is the gate for the merge.
|
|
46
|
+
|
|
47
|
+
## Known gaps, not blocking
|
|
48
|
+
|
|
49
|
+
- No installation, running-hub upgrade to 0.30.0 or live TUI launch was done for this record.
|
|
50
|
+
- Office phase 5's live two-agent, both-theme browser look (#264 AC9) is unverified.
|
|
51
|
+
- #1057: the owner confirms `worktrees.quiet_days` after a week of use; the first real `ahub worktrees tidy --confirm` on this repository has not run.
|
|
52
|
+
- #1055 AC7, a live managed Pi restart with a named session, stays in #1143.
|
|
53
|
+
- agy: `hub_send` and a board call through a real-account TUI (#485 AC3) are unverified. qwen-dual 0.26.5 is not promoted (Q2 fails, identically on the 0.26.1 control).
|
|
54
|
+
- `splitBacklog` stores its parts' plans without `validatePlanSources`; acceptance rechecks the stored plan, so an unknown source is still refused before work starts, but a split child can wait in Backlog holding one. Not a release blocker; filed as #1161.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Antigravity 1.4.12 actual-hub nonce leg through the `ahub agy` launcher (#888)
|
|
2
|
+
|
|
3
|
+
Date: 2026-11-03. Task #684, Refs #888. The [1.4.12 receipt of task #681](2026-11-03-agy-1.4.12.md) passed the CLI surface, the synthetic plugin MCP and hook contract and the normal TUI close, and failed the actual-hub nonce leg. This receipt re-runs only that leg, and drives it the way the person's launcher does.
|
|
4
|
+
|
|
5
|
+
**Decision: add 1.4.12 to agy `verified`.** Every account-free leg now has a pass on the same binary: the three legs from the #681 receipt, plus the nonce leg below. The accepted 1.4.x line is unchanged.
|
|
6
|
+
|
|
7
|
+
## Why the #681 nonce leg failed, and what changed
|
|
8
|
+
|
|
9
|
+
The #681 probe wrote its own plugin files and ran the bundle itself. It never asked the daemon for a launch slot (`native_hook_launch begin`), so the bundle's hub-tools socket was not an owned agy launch and joined as a distinct `agy~...` session. That session is not the project's agy and rightly got no preface. This is a defect of that producer, not an agy 1.4.12 regression. Here `ahub --live-test --project <scratch> agy` writes the managed plugin and holds the slot, as the person's launch does.
|
|
10
|
+
|
|
11
|
+
## Environment and isolation
|
|
12
|
+
|
|
13
|
+
- Native: the installed `~/.local/bin/agy`, `--version` `1.4.12`. SHA-256 `34423fc9b0af3841e7646aa72a2d40ffeab8218b22d1cb99eac7355f9eba31e3` before and after the run; the directory held the same two entries (`agy`, `agy.<n>.old`) before and after. The binary was not touched, and `AGY_CLI_DISABLE_AUTO_UPDATE=1` was set on every agy invocation.
|
|
14
|
+
- Launcher: this repository at `9eb10e34e8fa3624669d08828ac0ca65b8ec2041` (agent-hub 0.29.0, agent-mem 0.20.1), `src/cli/main.js --live-test --project <scratch> agy`, Bun 1.4.3, macOS 27.0.1 arm64. The committed plugin bundle was the one the daemon reported.
|
|
15
|
+
- Scratch daemon: started in the probe process with `startDaemon` on a loopback control port, in a disposable Git project under the per-user temporary directory (outside the person's home). Memory and native capture, inference, snapshots, MLX, design specs and Pi auto-start were off; `agy` was on the roster. The nonce `T0_LAUNCHER_NONCE_<uuid>` was held only in the scratch bus preface (`bus.preface("agy", ...)`).
|
|
16
|
+
- Every process had `HOME`, `AGENTHUB_HOME`, `AMEM_HOME`, `AGENTHUB_STATE_DIR`, `AGENTHUB_PROJECT_DIR`, `TMPDIR` and `XDG_CONFIG_HOME` set to scratch paths before any hub module loaded. The shell's live-hub locations were never used and the live hub was never contacted. The inherited agent marker stayed in place, as the live-test procedure requires.
|
|
17
|
+
- **Seatbelt:** agy itself ran under the `profile()` from `src/local/sandbox.ts` plus an explicit read/write deny of the person's home, through a `PATH` shim that `exec`s `sandbox-exec -f <profile> agy`. The launcher (`ahub agy`) and `bun` ran outside it. Checks: under the profile `cat` of the real `~/.gemini/config/config.json` exited 1 with `Operation not permitted`, and `/usr/bin/true` exited 0. The provider was a loopback fixture (`GEMINI_API_KEY=fixture-key`, `GOOGLE_GEMINI_BASE_URL` on loopback). No account and no cloud model call.
|
|
18
|
+
- The five real Gemini config entries (`antigravity-cli/settings.json`, `config/config.json`, `config/mcp_config.json`, `config/import_manifest.json` (absent), legacy `settings.json`) had the same SHA-256 or absence before and after.
|
|
19
|
+
- The daemon stopped, the fixture server stopped, no agy or scratch process remained. The original probe copies were not edited; the new probe lives in the local scratch workspace only.
|
|
20
|
+
|
|
21
|
+
## Result
|
|
22
|
+
|
|
23
|
+
| Observation | Value |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| Launcher exit | 0, after `/exit` and Enter; agy closed by itself and printed its resume line |
|
|
26
|
+
| Managed plugin while the TUI ran | `hooks.json`, `mcp_config.json`, `plugin.json` |
|
|
27
|
+
| Managed plugin after the close | empty: all three removed |
|
|
28
|
+
| Peers on the scratch bus | exactly `agy` (state `idle`); no `agy~...` session |
|
|
29
|
+
| Provider requests | 4; tool declarations 0, 12, 15, 15 (`call_mcp_tool` from the second agent request, the lazy attach of 1.4.7 and 1.4.3) |
|
|
30
|
+
| MCP call | one `call_mcp_tool` for `agent-hub_agent-hub/hub_inbox`; the TUI printed `Called 1 MCP tool (agent-hub_agent-hub/hub_inbox)` |
|
|
31
|
+
| Hub log | `agy read 1 queued message(s) through hub_inbox` (the preface), then `agy -> idle`, later `agy -> offline` |
|
|
32
|
+
| **Nonce readback** | **`nonceInModelRequest: true`**: the nonce from the scratch bus preface appeared in a provider request after the tool call |
|
|
33
|
+
|
|
34
|
+
## Not verified
|
|
35
|
+
|
|
36
|
+
- A real account, a real model's tool choices and agy's own permission prompts (the provider is a fixture).
|
|
37
|
+
- `hub_send` and board calls through the TUI, the IDE form and Linux.
|
|
38
|
+
- Seatbelt around the launcher itself: only agy ran under it.
|
|
39
|
+
|
|
40
|
+
## Promotion
|
|
41
|
+
|
|
42
|
+
`src/adapters/compat.ts` adds `1.4.12` to agy `verified` and points `receipt` at this file; `test/agy-compat-receipt.test.ts` and `test/compat.test.ts` pin both. Other 1.4.x patches stay in-line and unverified; 1.5.0 stays refused.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Antigravity 1.4.12 account-free T0 re-run
|
|
2
|
+
|
|
3
|
+
Date: 2026-11-03. Task #681, Refs #485. This repeats the account-free CLI, print/plugin/hook and interactive-close legs of the [1.4.7 receipt](2026-10-26-agy-1.4.7.md) against the installed 1.4.12.
|
|
4
|
+
|
|
5
|
+
**Decision: do not add 1.4.12 to `verified`.** CLI surface, the synthetic MCP/native-read hook contract and normal TUI close passed. The current-bundle actual-hub nonce leg did not pass. `src/adapters/compat.ts`, `test/agy-compat-receipt.test.ts` and the smoke version line remain unchanged. This receipt does not establish that the failed leg is an agy regression; the host/bundle and producer setup also changed since the 1.4.7 run.
|
|
6
|
+
|
|
7
|
+
## Isolation and exact executable
|
|
8
|
+
|
|
9
|
+
- Native version: `1.4.12`, exit 0. Executable: the installed `~/.local/bin/agy`, SHA-256 `34423fc9b0af3841e7646aa72a2d40ffeab8218b22d1cb99eac7355f9eba31e3`. Its bytes matched before the first invocation, after each producer and after the last invocation. The person's decision was to retain this installed version; no install, update or downgrade was performed.
|
|
10
|
+
- Host: macOS 27.0.1 arm64; native producer/interpreter: Bun 1.4.3. Source and committed bundle: `a51c8fc708eda19cc57c20b1084b3978c2ec5d54`, agent-hub 0.29.0. A local `dot admit`-admitted `bun install --frozen-lockfile` preceded the probes; the installed `@staix/agent-mem` version was asserted equal to the exact 0.20.1 manifest pin.
|
|
11
|
+
- Every agy invocation set `AGY_CLI_DISABLE_AUTO_UPDATE=1`, including CLI surface and `mcp list`, print mode and TUI. Each producer had a fresh controller HOME and each native run a fresh HOME/tool-home/project/temp tree, all under `getconf DARWIN_USER_TEMP_DIR`. No credentials or native settings were copied from the real home.
|
|
12
|
+
- Each native child used the `profile()` implementation from `src/local/sandbox.ts`, followed by an explicit real-home read/write deny. Narrow read/execute exceptions covered only the native executable, Bun and the committed bundle directory. Write grants covered only the scratch paths. Egress was limited to the loopback provider fixture and, for actual-hub runs, the scratch daemon's control port. This is the probe's sandbox, not a claim about ordinary native agy confinement.
|
|
13
|
+
- An explicit controller environment replaced inherited agent markers. `AGENTHUB_HOME`, `AMEM_HOME`, `AGENTHUB_STATE_DIR` and `AGENTHUB_PROJECT_DIR` named scratch locations before hub modules loaded; every native child also had explicit scratch hub paths. The shell's live-hub locations were never used. Scratch daemons had memory/native capture, inference/triage, snapshots, MLX, Pi auto-start and design specs disabled, with agy roster admission enabled.
|
|
14
|
+
- Isolation checks opened the real Gemini settings file read-only and attempted an `O_WRONLY` open of the native binary, without `O_TRUNC` or any write. Both were denied with `Operation not permitted`. Thus even an unexpected write-open guard failure could not have changed binary bytes.
|
|
15
|
+
- The five named real Gemini config entries below matched before and after. Every completed producer removed its native temporary root; both scratch daemons stopped. A fresh final process-table inspection found no remaining native/probe process from this series.
|
|
16
|
+
|
|
17
|
+
## Producer copies and setup corrections
|
|
18
|
+
|
|
19
|
+
The three originals under `scratchpad/temp/agent-hub-267/` were hashed before copying and again after the series; all were unchanged. Only new copies under `scratchpad/temp/agent-hub-681/` were adapted:
|
|
20
|
+
|
|
21
|
+
- `actual-hub-adapted.ts`: current worktree/Bun/bundle paths, disabled updater, explicit scratch hub paths, disabled unrelated daemon features, captured hook rows.
|
|
22
|
+
- `native-hooks-adapted.ts`: current paths and isolation above; hooks moved in the copy from the older project-level `.agents/hooks.json` location to the fixture plugin's `.agents/plugins/agent-hub/hooks.json`. The MCP server remained a synthetic stand-in, never this project's hub.
|
|
23
|
+
- `tui-actual.ts`: current paths/isolation, two prompt steps and a normal `/exit` plus Enter close. The copied harness recorded `signalFallbackNeeded` separately; only a still-running child could receive a fallback signal.
|
|
24
|
+
- The CLI surface helper reused the copied actual-hub producer's profile and bounded child cleanup. One initial setup observation used Bun's `userInfo().homedir` under the isolated HOME, which named the scratch home rather than the real home. It was discarded as real-home guard evidence. All copies then pinned the controller's actual real-home path in the deny/hash inventory; the corrected CLI guards above tested the actual real files.
|
|
25
|
+
|
|
26
|
+
No source, timeout ceiling, native approval rule or product identity guard was changed to make a native leg pass. The CLI/print child bound remained 25 seconds. `/exit` was given its bounded normal-close window, with fallback recorded rather than counted as a pass.
|
|
27
|
+
|
|
28
|
+
## CLI surface
|
|
29
|
+
|
|
30
|
+
| Probe | Observation |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| `--version` | `1.4.12`, exit 0 |
|
|
33
|
+
| `--help` and `help` | Exit 0; flags the launcher uses/refuses are still present, including `--continue`, `--conversation`, `--disable-slash-commands`, `--input-format`, `--output-format`, `--print`, `--prompt-interactive`, `--project`, `--remote-control` and `--sandbox` |
|
|
34
|
+
| `--acp` | Exit 2, `flags provided but not defined: -acp` |
|
|
35
|
+
| `--new` | Exit 2, `flags provided but not defined: -new` |
|
|
36
|
+
| Subcommands | `agent`, `agents`, `changelog`, `help`, `install`, `mcp`, `mic-serve`, `models`, `plugin`, `plugins`, `remote-control`, `update`; no ACP subcommand |
|
|
37
|
+
| Workspace-plugin `mcp list` | Exit 0, `No MCP servers configured.`, while the subsequent synthetic fixture run successfully discovered and called the plugin's tools |
|
|
38
|
+
|
|
39
|
+
## Synthetic plugin MCP and hook contract: passed
|
|
40
|
+
|
|
41
|
+
The print-mode loopback Gemini fixture replayed two MCP calls and a native read. No real account or cloud model turn was used. The MCP server returned fixture text only; its `hub_review` response was not a board review or approval.
|
|
42
|
+
|
|
43
|
+
- Native process exit 0, empty stderr. Plugin-local discovery recorded `server/discover`, `initialize`, `notifications/initialized`, `tools/list`, `tools/call`, `tools/call`.
|
|
44
|
+
- The two calls were `hub_task_show` with `id: 1` and `hub_review` with fixture-only arguments. Native `call_mcp_tool` retained `ServerName`, `ToolName` and `Arguments`; no `toolSummary`/`toolAction` was supplied.
|
|
45
|
+
- The native read remained `read_file` with `Path`, `StartLine` and `EndLine`, reading the scratch canary. No decoder change was made.
|
|
46
|
+
- All six plugin-local phases fired: `SessionStart`, `PreInvocation`, `PreToolUse`, `PostToolUse`, `PostInvocation`, `Stop`. Tool phases used `matcher: ".*"` with a nested hooks array.
|
|
47
|
+
- Shared hook stdin fields remained `artifactDirectoryPath`, `conversationId`, `lastUserInput`, `modelName`, `transcriptPath`, `workspacePaths`. Invocation phases added `initialNumSteps` and `invocationNum`; tool phases included `stepIdx` and `toolCall: {name, args}`, with an empty `error` on successful post-tool events.
|
|
48
|
+
- `Stop` reported `executionNum: 0`, `terminationReason: NO_TOOL_CALL`, empty `error`, and `fullyIdle: true`. The fixture's `SessionStart`/`PreInvocation` `injectSteps` ephemeral messages were accepted.
|
|
49
|
+
- Init listed 60 tools and `permission_mode: request-review`. The provider-facing declaration set remained the same 15 as 1.4.7: `ask_question`, `call_mcp_tool`, `define_subagent`, `edit_file`, `invoke_subagent`, `list_resources`, `manage_subagents`, `manage_task`, `read_file`, `read_resource`, `run_command`, `schedule`, `search_web`, `send_message`, `write_file`.
|
|
50
|
+
- Native output SHA-256: `be8d2db8393eea858058990ca90a7535c4440466d425a5f2b43d5c46a0fc9d81`. Real config inventory matched; the temporary root was removed.
|
|
51
|
+
|
|
52
|
+
## Actual scratch-hub nonce readback: failed
|
|
53
|
+
|
|
54
|
+
The actual-hub producer used the committed bundle and a nonce held only in the scratch bus preface. Its success criterion was delivery of that nonce into a later loopback provider request, not merely a native exit 0 or a tool declaration.
|
|
55
|
+
|
|
56
|
+
| Attempt | Observed result |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| Original copied bundle argv (`bun run <bundle>`) | Exit 0, empty stderr, three provider requests, one `call_mcp_tool` for `agent-hub_agent-hub/hub_inbox`; all six hooks fired. The bundle joined as a distinct `agy~...` session, returned a notice that it was not the project's agy, and did not return the canonical agy preface. `nonceInModelRequest: false`. |
|
|
59
|
+
| Explicit bundle-cwd variant (`bun --cwd <scratch-project> run <bundle>`) | Exit 0, empty stderr, two provider requests, zero MCP calls; only session/invocation/Stop hooks fired. `nonceInModelRequest: false`. |
|
|
60
|
+
|
|
61
|
+
The explicit-cwd variant addressed the current channel-project contract's requirement that the bundle process run at the project root; it did not bypass that identity check or force a model call to an undeclared tool. It still did not establish nonce readback. The first attempt's native output SHA-256 was `ba584c0ca2d301570576ae12699cffa2b41150d340fa0f8670c9a39cc0979558`; the explicit-cwd variant's was `037da39333e4439f03d9acb09ed998ef725d225837c5ba32cabceed07d44256e`.
|
|
62
|
+
|
|
63
|
+
These are recorded as failed acceptance evidence for this re-run. No claim is made that the identity notice or absent tool is caused by the 1.4.12 binary: this producer was originally written for an older hub, and the current bundle's project/session admission is another variable. No additional native retry was used to manufacture a green result.
|
|
64
|
+
|
|
65
|
+
## Interactive TUI and normal close
|
|
66
|
+
|
|
67
|
+
The explicit bundle-cwd variant was used for the interactive PTY, with fresh-HOME onboarding, then two prompts and `/exit` followed by Enter.
|
|
68
|
+
|
|
69
|
+
- The native TUI exited on its own with code 0 and printed its resume command. `signalFallbackNeeded: false`; no signal was sent to close it. The scratch daemon stopped and the native temporary root was removed.
|
|
70
|
+
- Provider declaration counts were 0, 12 and 12. Neither prompt exposed `call_mcp_tool`; MCP call count was zero and `nonceInModelRequest` was false. Only `SessionStart`, invocation phases and `Stop` were observed in this actual-bundle TUI run. Thus the normal-close sub-leg passed, while interactive actual-hub delivery did not.
|
|
71
|
+
- PTY output SHA-256: `e096b2f2f84d665c4c4dc7be7b2408c585f9743a1f5839410a93040e4abf2945`.
|
|
72
|
+
- This directly launches the native TUI in a disposable fixture. It does not verify `ahub agy`'s launch-slot release or managed-file cleanup, which belongs to the separate #443 receipt.
|
|
73
|
+
|
|
74
|
+
## Real configuration inventory
|
|
75
|
+
|
|
76
|
+
The controller hashed only the following named real `~/.gemini` files, without publishing their contents. The recorded digest/absence matched after every producer and at the end; this is not an inventory of every possible native file.
|
|
77
|
+
|
|
78
|
+
| File | Before and after SHA-256/absence |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| `antigravity-cli/settings.json` | `bb14f0a81a8239c6b988873e63fdd4f55fd6c822dc695c5138e5253424df276d` |
|
|
81
|
+
| `config/config.json` | `b8c51361bf83a00ae5e38b3108b48ffa3b4cfc7c4e9d9b7d16e04f74725f3c14` |
|
|
82
|
+
| `config/mcp_config.json` | `d8e397af03b5b032f21d0aa967086f0c78b33c87b76f2e9898ae0a144df7de02` |
|
|
83
|
+
| `config/import_manifest.json` | Absent |
|
|
84
|
+
| Legacy `settings.json` | `66c879018049d90632634790fe0b0eae54616a144e594c5db1b40b7c8be8c7b9` |
|
|
85
|
+
|
|
86
|
+
## Evidence boundary and follow-up
|
|
87
|
+
|
|
88
|
+
The native print/hook fixture and normal close are established above; real-account behavior, a real model's tool choices, permission-prompt overrides, Stop continuation, IDE behavior and Linux native behavior remain unverified. Most importantly, actual-hub nonce delivery on the current bundle is not established. Diagnose the disposable producer's project identity/MCP startup path before another promotion attempt; preserve the real-home deny, updater-off environment, live-hub path override and nonce assertion.
|
|
89
|
+
|
|
90
|
+
The changed repository gate runs on the committed receipt head via dgx02; its exact SHA and result are recorded in the PR/task submission. Hosted CI is a separate gate. This receipt leaves 1.4.12 as an unverified, in-line patch, with the accepted 1.4.x line and existing verified versions unchanged.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Antigravity TUI close through `ahub agy` (#485)
|
|
2
|
+
|
|
3
|
+
Date: 2026-11-03. Refs #485, task #443. This is the launcher leg the [1.4.7 receipt](2026-10-26-agy-1.4.7.md) left open: the hub's own `ahub agy` launch, the launch slot while the TUI runs, and what the launcher does when the TUI is closed normally. The earlier receipts closed agy by hand under a probe. This one runs the real `ahub agy` against a real scratch daemon.
|
|
4
|
+
|
|
5
|
+
## Environment and isolation
|
|
6
|
+
|
|
7
|
+
- Hub CLI and daemon: `ahub` 0.29.0, started with `ahub --live-test --project <scratch> up --no-agents --no-console` in a disposable Git project under the per-user temporary directory (outside the person's home). The scratch `status.json` named the scratch project root as `cwd`. The CLI's own `status` was refused for the agent identity, so that file was read instead. `jcode` was put on the scratch roster for a moment while diagnosing this and removed again. Memory and inference were off in the scratch config. `agy` was on that project's roster; no other peer was started.
|
|
8
|
+
- Every command had `HOME`, `AGENTHUB_HOME`, `AGENTHUB_STATE_DIR`, `AGENTHUB_PROJECT_DIR`, `TMPDIR` and `XDG_CONFIG_HOME` set to scratch paths. The inherited agent markers were left in place, as the live-test procedure requires, and the launcher ran under `--live-test` delegation. The live hub of this repository was not contacted.
|
|
9
|
+
- agy ran the interactive TUI on a PTY with `GEMINI_API_KEY=fixture-key` and `GOOGLE_GEMINI_BASE_URL` pointing at a loopback fixture provider (the 1.4.7 receipt's design: fixed `hub_inbox` call once the model lists `call_mcp_tool`, then a fixed text answer). No account and no cloud model call. Fresh-HOME onboarding was answered with the same keys (Enter, Down, Right, Enter, Enter). The scratch settings pre-allowed `mcp(agent-hub_agent-hub/hub_inbox)`.
|
|
10
|
+
- **No Seatbelt was used around `ahub agy`** (the 1.4.7 receipt did use it). Isolation here rests on the scratch environment above and on the real-config hashes below.
|
|
11
|
+
- Bystander files the launcher must not touch were placed in the scratch project: `.agents/plugins/other/plugin.json` and `.agents/rules/r.md`.
|
|
12
|
+
- The person's real Gemini files were hashed before and after every run: `~/.gemini/antigravity-cli/settings.json`, `~/.gemini/config/config.json`, `~/.gemini/config/mcp_config.json`, `~/.gemini/settings.json` (and `config/import_manifest.json`, absent on this machine). Equal before and after in every run. The real `~/.gemini/antigravity-cli` directory did change during the window (new log files, `cli.log`, `conversation_summaries.db`, `builtin/`), and the real-config hashes are the evidence that my runs did not write there. The new entries are consistent with other agy processes on the machine: their logs show workspace `/` and the real app-data directory, while every agy run of this receipt logged the scratch project and the scratch app-data directory under its own HOME.
|
|
13
|
+
|
|
14
|
+
## Facts (final run, agy 1.4.12; the same legs also passed in an earlier run, see below)
|
|
15
|
+
|
|
16
|
+
| Leg | Observation |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| Slot is held during the launch, before agy attaches | `ahub agy` was started a second time seconds after the first, with the first still starting its TUI: exit 1, `a managed native launch is already active; end it in its terminal first`. The three managed files were still present. |
|
|
19
|
+
| Slot is held while the TUI runs | After the first prompt was answered, a second `ahub agy`: exit 1, `native peer is already attached; end it in its terminal first`. The three managed files were still present. |
|
|
20
|
+
| Launcher wrote the managed plugin | While the TUI ran, `.agents/plugins/agent-hub/` held exactly `hooks.json`, `mcp_config.json`, `plugin.json`. |
|
|
21
|
+
| Hub tools worked through the plugin | The plugin MCP server attached lazily: provider requests listed 0, 12, then 15 tools (`call_mcp_tool` from the second agent request), `call_mcp_tool` ran `hub_inbox` once and the TUI printed the fixture answer. The hub log shows `agy` going `idle`, `busy`, `idle`. |
|
|
22
|
+
| Normal close | `/exit` and Enter in the TUI: `agy` exited by itself, the `ahub agy` process exited 0, and agy printed its resume line. No signal was sent. The hub log shows `state agy -> offline`. |
|
|
23
|
+
| Plugin cleanup | After the close `.agents/plugins/agent-hub/` was an empty directory: the three managed files were removed. |
|
|
24
|
+
| Bystanders unchanged | SHA-256 of `.agents/plugins/other/plugin.json` and `.agents/rules/r.md` equal before and after. |
|
|
25
|
+
| Slot is released | A second full launch right after the first close was admitted: three managed files written, TUI ran a prompt, `/exit` closed it with exit 0, the files were removed again, the bystanders were unchanged again. |
|
|
26
|
+
| Real config | The five real-config hashes were equal before and after the run. |
|
|
27
|
+
| Cleanup | `ahub --live-test --project <scratch> down` reported `hub stopped`. No `agy` process and no scratch hub process remained. |
|
|
28
|
+
|
|
29
|
+
An earlier complete run (the first two-cycle run, agy 1.4.7 for the first cycle and 1.4.12 for the second, after the binary was replaced, see below) gave the same results for the held slot after attach, the normal close, the cleanup, the second admitted cycle, the bystanders and the real-config hashes.
|
|
30
|
+
|
|
31
|
+
## Other observations
|
|
32
|
+
|
|
33
|
+
- **Closing while a native approval is pending.** Two earlier runs typed `/exit` while the fixture's `hub_inbox` call was waiting on agy's native approval prompt (the scratch settings did not yet pre-allow it). agy did not exit within 15 s, the probe sent SIGTERM, `ahub agy` forwarded it, the slot was released and the managed files were removed. The next launch after that kill was admitted. Neither run is the normal-close leg above; they only show that the signal path also ends in a released slot and removed files.
|
|
34
|
+
- The launcher printed `agy 1.4.12 is untested (verified 1.4.2, 1.4.7; compatible: the 1.4.x line); launching on the compatible line`, as designed (#589). `src/adapters/compat.ts` is unchanged by this receipt: 1.4.12 has no T0 receipt and stays unverified.
|
|
35
|
+
|
|
36
|
+
## Side effect on the machine: agy replaced its own binary
|
|
37
|
+
|
|
38
|
+
The first scratch run started agy 1.4.7 with a scratch HOME and without `AGY_CLI_DISABLE_AUTO_UPDATE`. agy spawned its background updater, which replaced the person's `~/.local/bin/agy` (a path the scratch HOME does not isolate) with 1.4.12 and kept the previous binary beside it as `agy.<n>.old`. The kept binary has SHA-256 `b7a13e53c9f49921692676ef8edc2e60ceb67064c00bc732d9a364ec3ad75b32`, the 1.4.7 hash recorded in the 1.4.7 receipt. The new binary's SHA-256 is `34423fc9b0af3841e7646aa72a2d40ffeab8218b22d1cb99eac7355f9eba31e3`. The real Gemini configuration files were not touched. Setting `AGY_CLI_DISABLE_AUTO_UPDATE=1` for any further live agy run prevents this; the smoke ledger now says so. Rolling back is the person's choice.
|
|
39
|
+
|
|
40
|
+
## Not verified
|
|
41
|
+
|
|
42
|
+
- A real account, a real model turn and agy's own permission prompts (the provider was a fixture).
|
|
43
|
+
- `hub_send` and a board read or proposal through the TUI: only `hub_inbox` was called. AC3 of #485 names all three, so the issue stays open.
|
|
44
|
+
- The IDE form, Linux, and a Seatbelt-wrapped `ahub agy`.
|
|
45
|
+
- A launch of the verified 1.4.7 build from start to finish: the first cycle of the earlier run was 1.4.7 and the final run was 1.4.12.
|
|
46
|
+
|
|
47
|
+
## Decision
|
|
48
|
+
|
|
49
|
+
The hub launcher's own close leg holds on the 1.4.x line in a scratch project: the launch slot is held while agy starts and runs, a normal TUI close releases it so the next launch is admitted, the three managed plugin files are the only thing removed, and the person's real Gemini configuration hashes are unchanged. This does not close #485 on its own (see Not verified), so the pull request says `Refs #485`.
|