instar 1.3.1663 → 1.3.1665
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/dist/commands/postDriveTranscriptAudit.d.ts.map +1 -1
- package/dist/commands/postDriveTranscriptAudit.js +3 -2
- package/dist/commands/postDriveTranscriptAudit.js.map +1 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +65 -30
- package/dist/commands/server.js.map +1 -1
- package/dist/core/BetweenWindowAdmissionGate.d.ts.map +1 -1
- package/dist/core/BetweenWindowAdmissionGate.js +3 -2
- package/dist/core/BetweenWindowAdmissionGate.js.map +1 -1
- package/dist/core/DirectDesktopAccess.d.ts.map +1 -1
- package/dist/core/DirectDesktopAccess.js +2 -1
- package/dist/core/DirectDesktopAccess.js.map +1 -1
- package/dist/core/LiveTailSource.d.ts.map +1 -1
- package/dist/core/LiveTailSource.js +5 -48
- package/dist/core/LiveTailSource.js.map +1 -1
- package/dist/core/MeshRpc.d.ts +4 -0
- package/dist/core/MeshRpc.d.ts.map +1 -1
- package/dist/core/MeshRpc.js +4 -0
- package/dist/core/MeshRpc.js.map +1 -1
- package/dist/core/OwnershipApplier.d.ts.map +1 -1
- package/dist/core/OwnershipApplier.js +5 -4
- package/dist/core/OwnershipApplier.js.map +1 -1
- package/dist/core/OwnershipReconciler.d.ts.map +1 -1
- package/dist/core/OwnershipReconciler.js +5 -4
- package/dist/core/OwnershipReconciler.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +6 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +25 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/PrHandLease.d.ts.map +1 -1
- package/dist/core/PrHandLease.js +2 -1
- package/dist/core/PrHandLease.js.map +1 -1
- package/dist/core/SafeGitExecutor.d.ts +33 -11
- package/dist/core/SafeGitExecutor.d.ts.map +1 -1
- package/dist/core/SafeGitExecutor.js +144 -116
- package/dist/core/SafeGitExecutor.js.map +1 -1
- package/dist/core/ScopeVerifier.d.ts.map +1 -1
- package/dist/core/ScopeVerifier.js +4 -3
- package/dist/core/ScopeVerifier.js.map +1 -1
- package/dist/core/SeamlessOrchestratorEngine.d.ts.map +1 -1
- package/dist/core/SeamlessOrchestratorEngine.js +3 -31
- package/dist/core/SeamlessOrchestratorEngine.js.map +1 -1
- package/dist/core/SessionDrainRunner.d.ts.map +1 -1
- package/dist/core/SessionDrainRunner.js +4 -3
- package/dist/core/SessionDrainRunner.js.map +1 -1
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +11 -10
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/SessionRouter.d.ts +14 -0
- package/dist/core/SessionRouter.d.ts.map +1 -1
- package/dist/core/SessionRouter.js +42 -1
- package/dist/core/SessionRouter.js.map +1 -1
- package/dist/core/StaleOwnerReleaseEngine.d.ts.map +1 -1
- package/dist/core/StaleOwnerReleaseEngine.js +2 -1
- package/dist/core/StaleOwnerReleaseEngine.js.map +1 -1
- package/dist/core/TelegramLiveSender.d.ts.map +1 -1
- package/dist/core/TelegramLiveSender.js +3 -2
- package/dist/core/TelegramLiveSender.js.map +1 -1
- package/dist/core/TelegramSpendTopicChannel.d.ts.map +1 -1
- package/dist/core/TelegramSpendTopicChannel.js +2 -1
- package/dist/core/TelegramSpendTopicChannel.js.map +1 -1
- package/dist/core/TopicProfileOrchestrator.d.ts.map +1 -1
- package/dist/core/TopicProfileOrchestrator.js +2 -1
- package/dist/core/TopicProfileOrchestrator.js.map +1 -1
- package/dist/core/TopicProfileStore.d.ts.map +1 -1
- package/dist/core/TopicProfileStore.js +2 -1
- package/dist/core/TopicProfileStore.js.map +1 -1
- package/dist/core/TopicProfileTransferCarrier.d.ts.map +1 -1
- package/dist/core/TopicProfileTransferCarrier.js +2 -1
- package/dist/core/TopicProfileTransferCarrier.js.map +1 -1
- package/dist/core/conversationBindGate.d.ts +0 -21
- package/dist/core/conversationBindGate.d.ts.map +1 -1
- package/dist/core/conversationBindGate.js +23 -1
- package/dist/core/conversationBindGate.js.map +1 -1
- package/dist/core/topicHistoryPull.d.ts +50 -0
- package/dist/core/topicHistoryPull.d.ts.map +1 -0
- package/dist/core/topicHistoryPull.js +87 -0
- package/dist/core/topicHistoryPull.js.map +1 -0
- package/dist/data/standards-guard-index.json +1 -1
- package/dist/data/standards-guard-index.meta.json +2 -2
- package/dist/data/standards-registry.meta.json +1 -1
- package/dist/memory/TopicSummarizer.d.ts.map +1 -1
- package/dist/memory/TopicSummarizer.js +3 -2
- package/dist/memory/TopicSummarizer.js.map +1 -1
- package/dist/messaging/ColdStartFallbackReply.d.ts.map +1 -1
- package/dist/messaging/ColdStartFallbackReply.js +3 -25
- package/dist/messaging/ColdStartFallbackReply.js.map +1 -1
- package/dist/messaging/NotificationBatcher.d.ts.map +1 -1
- package/dist/messaging/NotificationBatcher.js +2 -1
- package/dist/messaging/NotificationBatcher.js.map +1 -1
- package/dist/messaging/OutboundAdvisory.d.ts.map +1 -1
- package/dist/messaging/OutboundAdvisory.js +3 -2
- package/dist/messaging/OutboundAdvisory.js.map +1 -1
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +3 -2
- package/dist/messaging/TelegramAdapter.js.map +1 -1
- package/dist/messaging/shared/topicRef.d.ts +42 -0
- package/dist/messaging/shared/topicRef.d.ts.map +1 -0
- package/dist/messaging/shared/topicRef.js +82 -0
- package/dist/messaging/shared/topicRef.js.map +1 -0
- package/dist/messaging/telegram-origin/OriginForwardToHolder.d.ts.map +1 -1
- package/dist/messaging/telegram-origin/OriginForwardToHolder.js +4 -3
- package/dist/messaging/telegram-origin/OriginForwardToHolder.js.map +1 -1
- package/dist/messaging/telegram-origin/OriginLegacy.js +1 -1
- package/dist/messaging/telegram-origin/OriginLegacy.js.map +1 -1
- package/dist/messaging/telegramTopicSpace.d.ts.map +1 -1
- package/dist/messaging/telegramTopicSpace.js +2 -1
- package/dist/messaging/telegramTopicSpace.js.map +1 -1
- package/dist/monitoring/AutonomousLivenessReconciler.d.ts.map +1 -1
- package/dist/monitoring/AutonomousLivenessReconciler.js +9 -41
- package/dist/monitoring/AutonomousLivenessReconciler.js.map +1 -1
- package/dist/monitoring/PromiseBeacon.d.ts.map +1 -1
- package/dist/monitoring/PromiseBeacon.js +3 -2
- package/dist/monitoring/PromiseBeacon.js.map +1 -1
- package/dist/monitoring/ReapNoticeDrain.d.ts.map +1 -1
- package/dist/monitoring/ReapNoticeDrain.js +2 -1
- package/dist/monitoring/ReapNoticeDrain.js.map +1 -1
- package/dist/monitoring/ReapNotifier.d.ts.map +1 -1
- package/dist/monitoring/ReapNotifier.js +3 -2
- package/dist/monitoring/ReapNotifier.js.map +1 -1
- package/dist/monitoring/SessionReaper.d.ts.map +1 -1
- package/dist/monitoring/SessionReaper.js +13 -12
- package/dist/monitoring/SessionReaper.js.map +1 -1
- package/dist/monitoring/SessionRecovery.d.ts.map +1 -1
- package/dist/monitoring/SessionRecovery.js +4 -3
- package/dist/monitoring/SessionRecovery.js.map +1 -1
- package/dist/monitoring/TopicReachabilityVerifier.d.ts.map +1 -1
- package/dist/monitoring/TopicReachabilityVerifier.js +2 -20
- package/dist/monitoring/TopicReachabilityVerifier.js.map +1 -1
- package/dist/monitoring/machineMaintenance/WorkYieldRegistry.d.ts +0 -15
- package/dist/monitoring/machineMaintenance/WorkYieldRegistry.d.ts.map +1 -1
- package/dist/monitoring/machineMaintenance/WorkYieldRegistry.js +3 -2
- package/dist/monitoring/machineMaintenance/WorkYieldRegistry.js.map +1 -1
- package/dist/monitoring/sentinelWiring.d.ts.map +1 -1
- package/dist/monitoring/sentinelWiring.js +2 -1
- package/dist/monitoring/sentinelWiring.js.map +1 -1
- package/dist/native/InstarWedgeCanary.app/Contents/MacOS/InstarWedgeCanary +0 -0
- package/dist/native/instar-desktop-host +0 -0
- package/dist/recommended/catalog.js +1 -1
- package/dist/recommended/catalog.js.map +1 -1
- package/dist/recommended/recipes.d.ts.map +1 -1
- package/dist/recommended/recipes.js +3 -2
- package/dist/recommended/recipes.js.map +1 -1
- package/dist/recommended/setupState.d.ts +9 -0
- package/dist/recommended/setupState.d.ts.map +1 -1
- package/dist/recommended/setupState.js +17 -0
- package/dist/recommended/setupState.js.map +1 -1
- package/dist/scheduler/MentorAutonomousGuardian.d.ts.map +1 -1
- package/dist/scheduler/MentorAutonomousGuardian.js +3 -30
- package/dist/scheduler/MentorAutonomousGuardian.js.map +1 -1
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +7 -1
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +10 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/mobilePairingRoutes.d.ts.map +1 -1
- package/dist/server/mobilePairingRoutes.js +4 -0
- package/dist/server/mobilePairingRoutes.js.map +1 -1
- package/dist/server/mobileProposalsInsideRoutes.d.ts +155 -0
- package/dist/server/mobileProposalsInsideRoutes.d.ts.map +1 -0
- package/dist/server/mobileProposalsInsideRoutes.js +626 -0
- package/dist/server/mobileProposalsInsideRoutes.js.map +1 -0
- package/dist/server/recommendedServiceRoutes.d.ts +2 -0
- package/dist/server/recommendedServiceRoutes.d.ts.map +1 -1
- package/dist/server/recommendedServiceRoutes.js +41 -7
- package/dist/server/recommendedServiceRoutes.js.map +1 -1
- package/dist/server/routes/remediation-proposals.d.ts +1 -0
- package/dist/server/routes/remediation-proposals.d.ts.map +1 -1
- package/dist/server/routes/remediation-proposals.js +1 -1
- package/dist/server/routes/remediation-proposals.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +75 -42
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/HubIntentClassifier.d.ts.map +1 -1
- package/dist/threadline/HubIntentClassifier.js +2 -1
- package/dist/threadline/HubIntentClassifier.js.map +1 -1
- package/dist/threadline/PairingInviteTelegram.d.ts.map +1 -1
- package/dist/threadline/PairingInviteTelegram.js +2 -1
- package/dist/threadline/PairingInviteTelegram.js.map +1 -1
- package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
- package/dist/threadline/ThreadlineRouter.js +6 -2
- package/dist/threadline/ThreadlineRouter.js.map +1 -1
- package/dist/threadline/TopicLinkageHandler.d.ts.map +1 -1
- package/dist/threadline/TopicLinkageHandler.js +8 -3
- package/dist/threadline/TopicLinkageHandler.js.map +1 -1
- package/dist/threadline/hubCommands.d.ts.map +1 -1
- package/dist/threadline/hubCommands.js +2 -1
- package/dist/threadline/hubCommands.js.map +1 -1
- package/dist/types/pipeline.d.ts.map +1 -1
- package/dist/types/pipeline.js +6 -1
- package/dist/types/pipeline.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +65 -65
- package/src/data/standards-guard-index.json +1 -1
- package/src/data/standards-guard-index.meta.json +2 -2
- package/src/data/standards-registry.meta.json +1 -1
- package/upgrades/1.3.1664.md +32 -0
- package/upgrades/1.3.1665.md +36 -0
- package/upgrades/side-effects/mobile-native-proposals-inside.md +57 -0
- package/upgrades/side-effects/recommended-services-stop-holds.md +64 -0
- package/upgrades/side-effects/safe-git-one-verb-classifier.md +117 -0
- package/upgrades/side-effects/session-pool-keep-and-recall.md +49 -0
- package/upgrades/side-effects/topic-name-beside-id.md +152 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Side-Effects Review — Native Proposals and How I'm doing inside screens
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `mobile-native-proposals-inside`
|
|
4
|
+
**Date:** `2026-11-04`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `cross-model codex-cli and clean-door claude-code reviewers (see below)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Two read-only routes for the Instar iPhone app, owner phones (device-signed) or the bearer token only: `GET /mobile/proposals` and `GET /mobile/inside`. New module `src/server/mobileProposalsInsideRoutes.ts`, two `DEVICE_ALLOWLIST` entries, `loadAllProposals` exported, a CapabilityIndex entry and a CLAUDE.md bullet with its migration. Tier 2 because it widens device-key read access.
|
|
11
|
+
|
|
12
|
+
## Decision-point inventory
|
|
13
|
+
|
|
14
|
+
- `DEVICE_ALLOWLIST` — add — two exact-path GET rules, `ownerOnly`, a shared own bucket.
|
|
15
|
+
- `ownerOrBearer` — reuse.
|
|
16
|
+
- Field allowlists, path replacement, peer rebuild — add — a fixed redaction contract.
|
|
17
|
+
|
|
18
|
+
## 1. Over-block
|
|
19
|
+
|
|
20
|
+
An MSP phone cannot read either screen; that is the owner-only default. A peer whose answer fails the shape check is listed as not answering; one with a section missing its numbers still shows, with that section unavailable. Either way the screen under-claims, which is the intended direction.
|
|
21
|
+
|
|
22
|
+
## 2. Under-block
|
|
23
|
+
|
|
24
|
+
Free text can hold repo-relative file names, and a path form outside the replaced prefixes; the scrub is best effort, and the owner reads the same text in the console. A stolen owner phone that passes the device check can read these summaries, like the other owner reads.
|
|
25
|
+
|
|
26
|
+
## 3. Level-of-abstraction fit
|
|
27
|
+
|
|
28
|
+
Same layer as the merged mobile read modules. The words duplicate `inside-model.js`, because the server cannot import the console's view model into a route without coupling them; a parity test pins the kind, insight-status and verdict tables (the others are not exported by the console model).
|
|
29
|
+
|
|
30
|
+
## 4. Signal vs authority compliance
|
|
31
|
+
|
|
32
|
+
No blocking authority is added, no detector, no LLM. The allowlist and owner checks are identity authorization, not judgment. `docs/signal-vs-authority.md` does not apply beyond that.
|
|
33
|
+
|
|
34
|
+
## 5. Interactions
|
|
35
|
+
|
|
36
|
+
Shares the `peerSummaries` helper and the 15 s single-flight pattern. Own device bucket, so it does not eat the other screens' budget. A test fixes the named owner-only set. The raw routes are unchanged.
|
|
37
|
+
|
|
38
|
+
## 6. External surfaces
|
|
39
|
+
|
|
40
|
+
Two new read paths; the app shows "update the agent" on older servers. Peers receive two extra bearer reads, at most once per 15 s per route while a phone is reading. No LLM spend. No notices.
|
|
41
|
+
|
|
42
|
+
## 7. Multi-machine posture
|
|
43
|
+
|
|
44
|
+
Both proxied-on-read through `?scope=local`, each row or group naming its machine; missing machines named. No durable state, no generated URLs.
|
|
45
|
+
|
|
46
|
+
## 8. Rollback cost
|
|
47
|
+
|
|
48
|
+
Revert. No data, config or migration to repair; the CLAUDE.md bullet stays harmlessly until the next template refresh.
|
|
49
|
+
|
|
50
|
+
## Second-pass review (if required)
|
|
51
|
+
|
|
52
|
+
**Reviewer:** cross-model codex-cli gpt-6-astra (6 rounds) and clean-door claude-code (2 rounds), fresh context, reading the spec and module
|
|
53
|
+
**Independent read of the artifact: minor issues, no blocker**
|
|
54
|
+
|
|
55
|
+
Each round's findings were applied with tests; see `docs/specs/reports/mobile-native-proposals-inside-convergence.md`. Codex round 6 and the first clean-door read of this artifact raised design points, all fixed. The last clean-door read returned MINOR ISSUES: dismissed and promoted are per-machine sums, the headline ignores overdue and failed-review rows, and peers exchange display words rather than codes. The first two are stated in the spec as deliberate, matching the console. The third fails safe ("can't tell") and is left as it is.
|
|
56
|
+
|
|
57
|
+
**Test fixture note (2026-11-04):** the integration test used one proposal on both machines, which the later count-once change correctly merges. The peer now has its own proposal. No product code changed.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Side-Effects Review — a person's stop holds recommended-service setup
|
|
2
|
+
|
|
3
|
+
**Tier 2 by risk (session restart behaviour), with second-pass review.** Spec: `docs/specs/recommended-services.md`. Dark: setup only runs on a throwaway or development agent listing a recipe.
|
|
4
|
+
|
|
5
|
+
## Summary
|
|
6
|
+
|
|
7
|
+
- New `held` in per-machine setup state. `reconcile` skips a held service, so no restart and no stuck notice.
|
|
8
|
+
- `holdSetupForSession` is called from the Telegram sentinel kill and `DELETE /sessions/:id`, before the kill and matching by session name or topic. `holdAllSetups` is called from the Slack sentinel kill-all and the app's Slack kill-all, and also holds a setup whose session is already dead.
|
|
9
|
+
- Setup state now follows the conversation's current session, found through the topic. A reply brings a session back under a different name. Before this, a repeat yes could start a second session, and a no couldn't stop the renamed one.
|
|
10
|
+
- New `POST /recommended-services/:id/hold`, for a session whose person said not now. Needs the bearer token and `X-Instar-Request`. No PIN, and it refuses without a recipe.
|
|
11
|
+
- A repeat yes lifts a hold, resets its restart count and starts setup. A fresh yes also lifts it. A no and a pass clear it.
|
|
12
|
+
- The Jev offer text says credits are needed before a key. This changes its offer hash, which is harmless because no real agent has a grant.
|
|
13
|
+
- The brief rule covers sign-in codes and pictures. The Jev brief records the credit requirement and a credit code as the route that avoids a card.
|
|
14
|
+
|
|
15
|
+
## 1. Over-block
|
|
16
|
+
|
|
17
|
+
A false emergency stop now stays stopped until the person writes again. The second live run was exactly this: "No, don't add credits" was classified as a stop. It recovered before only because of the restart this removes. The person is told "Session terminated. Send a new message", so it isn't silent, and the classifier bug is filed on its own (fb-01131fac-fb1).
|
|
18
|
+
|
|
19
|
+
An agent's own `DELETE /sessions/:id` with a bearer token also holds, since the route can't always tell operator from agent. A session ended that way stays ended until a yes, a no, a pass, or a reply. An agent ending its own setup session on purpose wants that.
|
|
20
|
+
|
|
21
|
+
## 2. Under-block
|
|
22
|
+
|
|
23
|
+
- Kill paths that aren't named still restart: the reaper, the watchdog, crash recovery. They're not a person's stop, so that's intended. A new person-facing stop path added later would miss this. A test pins the four named paths by reading the source, so it shows the calls exist and not that each runs.
|
|
24
|
+
- `/stop-all` style autonomous stops and the route at `routes.ts:28380` are covered only where they go through `onSentinelKillSession`. The route's fallback without Telegram doesn't hold, and setup needs Telegram to talk to the person.
|
|
25
|
+
- A session the person brought back by replying, which then dies, isn't restarted while held. Their next message resumes it. Recorded in the spec's Left behind.
|
|
26
|
+
- The hold rule is prompt text, so a session can fail to call it. It then gets the bounded restarts, as today.
|
|
27
|
+
- The hold is written before the kill. If the kill fails, the session keeps running while held. It can still finish and pass, which clears the hold.
|
|
28
|
+
- Narrow race left in place: a stop during `startSetup`, before any session name is saved, can find nothing to hold or leave the new session running. The window is seconds, one recipe, and only on proving agents.
|
|
29
|
+
|
|
30
|
+
## 3. Level-of-abstraction fit
|
|
31
|
+
|
|
32
|
+
The stop decision stays where it is, in the sentinel and the routes. Setup state only records the outcome, and `reconcile` reads it. The two kill-all paths hold every setup that hasn't passed, including one whose session is already dead.
|
|
33
|
+
|
|
34
|
+
## 4. Signal vs authority compliance
|
|
35
|
+
|
|
36
|
+
No new judgment. `held` is a recorded fact, and `reconcile` applies a deterministic skip. The hold route only reduces what the system does, and grants nothing. Reference: `docs/signal-vs-authority.md`.
|
|
37
|
+
|
|
38
|
+
## 5. Interactions
|
|
39
|
+
|
|
40
|
+
`dormant` and `exhausted` are unaffected, because the hold check sits beside them. `endSetup` clears `held`, and `reconcile`'s no-grant branch runs before the skip, so a no from another machine still ends a held setup. A repeat yes used to return without touching setup. It now restarts a held one, which needs the PIN and a live page token.
|
|
41
|
+
|
|
42
|
+
## 6. External surfaces
|
|
43
|
+
|
|
44
|
+
`GET /recommended-services` gains `held`. One new route. The offer text changes only on the confirm page, which real agents can't reach. No change to what a person sees on any real agent.
|
|
45
|
+
|
|
46
|
+
## 6b. Operator-surface quality
|
|
47
|
+
|
|
48
|
+
The confirm page shows the new cost line through the existing field. It is one sentence longer, and the page is otherwise unchanged. No new control.
|
|
49
|
+
|
|
50
|
+
## 7. Multi-machine posture
|
|
51
|
+
|
|
52
|
+
Machine-local, like the rest of setup state. `machine-local-justification: physical-credential-locality`: setup state tracks a key and session on one disk. A stop on one machine holds the session on that machine. Setup runs only on the granted machine.
|
|
53
|
+
|
|
54
|
+
## 8. Rollback cost
|
|
55
|
+
|
|
56
|
+
A revert removes the route and the skip. A leftover `held` field in the state file is ignored. No data migration.
|
|
57
|
+
|
|
58
|
+
## Second-pass review
|
|
59
|
+
|
|
60
|
+
First read: concern raised. A stop, a reply and then a yes could start a second live session, because state kept a stale session name. The reviewer also named an unheld stop under a renamed session, a fresh yes leaving a hold, the app's Slack kill-all, a dead session coming back after a kill-all, the gap after the dashboard's kill, a hold overwritten during preflight, a repeat yes keeping its spent restarts, a pass not clearing the hold with no open promise, and an overclaiming test title. All were fixed.
|
|
61
|
+
|
|
62
|
+
Second read: concurred, nothing blocking, from reading the code without running tests. It raised three smaller items. Re-adopting a session after a no, and a stop during preflight, are fixed after that read and weren't re-read. Left in place: a stop during `startSetup` still ends with a session running while held, and a yes on an open session clears `lastAttemptAt`, so a later idle-out gets one more restart.
|
|
63
|
+
|
|
64
|
+
Verifier: the first full run failed one integration test, `recommended-services-confirm-wiring`, because that test's Telegram stand-in had no topic lookup, which the no path now calls. The real adapter has it. The stand-in now keeps real topic records, so the no path runs the real lookup. I hadn't run that file locally before pushing. Test-only, so no second read.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Side-Effects Review — SafeGitExecutor one verb classification
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `safe-git-one-verb-classifier`
|
|
4
|
+
**Date:** `2026-11-04`
|
|
5
|
+
**Author:** `Echo`
|
|
6
|
+
**Second-pass reviewer:** `independent reviewer subagent (see below)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
The git funnel kept two verb lists, one per kind of surface, so a verb in neither list was refused by both and each refusal named the other (EVO-028). `src/core/SafeGitExecutor.ts` now has one table, `GIT_VERB_CLASSES`, and one classifier, `classifyGitInvocation`, which all five entry points use. The two exported sets are derived from the table. `check-ignore` is added as a read and joins `SOURCE_TREE_READ_TIER_VERBS`. An unclassified verb gets one shared refusal on every surface. `reflog` becomes a `shape` verb, so its non-read forms route through `run` to `execSync`. Tests: `tests/unit/SafeGitExecutor-verb-classifier.test.ts` (new), plus one-line updates to `tests/unit/SafeGitExecutor.test.ts` and `tests/unit/SafeGitExecutor-sourceTreeReadOk.test.ts`.
|
|
11
|
+
|
|
12
|
+
Proportion: Tier 1 declared, because a revert fully undoes it and it adds no new authority, with the full chain run anyway because this is the safety funnel (converged spec, second-pass review). About 170 added source lines, most of them the list becoming a table. Three spec rounds, at the cap. The draft was three weeks stale and the rounds kept finding real errors in what it said about the system.
|
|
13
|
+
|
|
14
|
+
## Decision-point inventory
|
|
15
|
+
|
|
16
|
+
- `SafeGitExecutor` verb gate — modify — same gate, one source of truth. No new blocking authority.
|
|
17
|
+
- `SafeGitExecutor.run` routing — modify — routes on the classifier. Only `reflog` routing changes.
|
|
18
|
+
- `SOURCE_TREE_READ_TIER_VERBS` — modify — gains `check-ignore`, opt-in per call.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 1. Over-block
|
|
23
|
+
|
|
24
|
+
No legitimate call is newly refused. Every verb the classifier calls `unclassified` was refused by both surfaces before. Harmless unclassified verbs (`check-attr`, `show-branch`) stay refused on purpose; EVO-028 approved one verb, and each further one needs its own check. The refusal now tells the caller that adding a verb is a reviewed change.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2. Under-block
|
|
29
|
+
|
|
30
|
+
This change does not close existing gaps. Read-classified invocations can still write or run a program: `remote -v add`, `config key --list`, `format-patch`, `hash-object -w`, `write-tree`, `symbolic-ref`, `--output` on `diff`, `log` and `show`, repo-local `core.fsmonitor`, `diff.external`. Echo reproduced the first two. Those are EVO-029 items 4 and 5 <!-- tracked: CMT-1124 -->, and the record was widened in this run. `check-ignore` inherits the `core.fsmonitor` exposure that `status` already has, so it adds no new class. `run` still reads `args[0]`, so a pre-verb flag is routed to `readSync` (EVO-029 item 1 <!-- tracked: CMT-1124 -->).
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 3. Level-of-abstraction fit
|
|
35
|
+
|
|
36
|
+
Right layer. The contradiction lived inside the funnel, and the classification belongs next to the shape checks it calls. Two scripts keep their own verb lists for unrelated jobs and are left alone (EVO-029 item 6 <!-- tracked: CMT-1124 -->).
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 4. Signal vs authority compliance
|
|
41
|
+
|
|
42
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
43
|
+
|
|
44
|
+
**Does this change hold blocking authority with brittle logic?**
|
|
45
|
+
|
|
46
|
+
- [ ] No — this change produces a signal consumed by an existing smart gate.
|
|
47
|
+
- [ ] No — this change has no block/allow surface.
|
|
48
|
+
- [ ] Yes — but the logic is a smart gate with full conversational context (LLM-backed with recent history or equivalent).
|
|
49
|
+
- [ ] ⚠️ Yes, with brittle logic — STOP. Reshape the design. Brittle detectors must not own block authority. Either promote the logic to smart-gate level (with proper context) or demote it to a signal that feeds an existing smart gate.
|
|
50
|
+
|
|
51
|
+
None of the four boxes fits exactly, so this is stated directly. The funnel is a deterministic allowlist over git's fixed command grammar. It judges no meaning and it predates this change. `docs/signal-vs-authority.md` names hard-invariant validators as outside the principle and a deterministic policy evaluator as a valid authority where inputs can be enumerated. This change adds no blocking authority: everything it refuses was refused already. The Standards-Conformance Gate flagged this in all three rounds, because the registry article names only the emergency-stop floor as an exception. That disagreement between the two documents is filed as feedback fb-69615365-30f and needs a ruling, because the registry is the constitution.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 4b. Judgment-point check (Judgment Within Floors standard)
|
|
56
|
+
|
|
57
|
+
No static heuristic is added at a competing-signals point. Whether a verb is in a closed table has no competing signals.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 5. Interactions
|
|
62
|
+
|
|
63
|
+
- **Source-tree guard:** the unclassified refusal now comes before the guard on `execSync` and `spawn`. That call was refused either way; only the error changes, from `SourceTreeGuardError` to `SafeGitExecutorError`. `leaseMediumSelection.ts:67` treats both alike. Classified verbs keep their order, pinned by a test.
|
|
64
|
+
- **`GitStateManager.ts:345`:** `update-index --refresh` is still refused and swallowed; only the swallowed text changes.
|
|
65
|
+
- **`machine.ts:174`:** unchanged. It still reaches `readSync` and is refused.
|
|
66
|
+
- **Audit log:** one new reason, `unclassified-verb`. Nothing reads audit reasons.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 6. External surfaces
|
|
71
|
+
|
|
72
|
+
None. No route, config, message, file or agent-installed surface changes. Refusal text changes only for unclassified verbs, and nothing in `src/` or `scripts/` reads refusal text.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 6b. Operator-surface quality (Operator-Surface Quality standard)
|
|
77
|
+
|
|
78
|
+
No operator surface touched — not applicable.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
83
|
+
|
|
84
|
+
No new state, notice or URL. This is in-process classification that ships identically to every machine. The one machine dependence is in git, not here: `check-ignore` reads `.git/info/exclude` and the per-user ignore file (`$XDG_CONFIG_HOME/git/ignore`, by default `~/.config/git/ignore`, unless a repo-local `core.excludesFile` overrides it), so its answer can differ per machine. The spec states this for callers. No status surface changes.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 8. Rollback cost
|
|
89
|
+
|
|
90
|
+
Revert the commit. No stored state, config or migration. After a revert `check-ignore` is unreachable again and the contradictory messages return.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Conclusion
|
|
95
|
+
|
|
96
|
+
Three review rounds changed the design in two ways: the unclassified refusal moved ahead of the source-tree guard, and `check-ignore` joined the source-tree read tier, without which the goal was only half met. They also corrected several false statements in the spec and exposed the wider gap now recorded under EVO-029. Clear to ship as a consistency fix. It is not a claim that the read surfaces are safe.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Second-pass review (if required)
|
|
101
|
+
|
|
102
|
+
**Reviewer:** independent reviewer subagent (claude-opus-5-5), read-only, no shared context beyond this artifact and the diff
|
|
103
|
+
**Independent read of the artifact: concur**
|
|
104
|
+
|
|
105
|
+
Concur after two wording corrections, both applied: the per-user ignore file description, and "added" not "changed" for the line count. The reviewer ran old and new code side by side with a fake git over every table verb and every `git --list-cmds=main` command on all five surfaces, on plain and source-tree fixtures. Only three groups differ: unclassified verbs, `check-ignore`, and `run` with `reflog`. Table membership matches the old lists plus the two stated additions. Unstated and harmless: `run([''])` now reaches `readSync` and is still refused.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Evidence pointers
|
|
110
|
+
|
|
111
|
+
Disconfirmation on unchanged source: 14 of 16 tests failed for the expected reasons, including "readSync called with destructive verb 'check-ignore'" and "destructive shape 'reflog expire ...'". Convergence report: `docs/specs/reports/safe-git-one-verb-classifier-convergence.md`.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Class-Closure Declaration (display-only mirror)
|
|
116
|
+
|
|
117
|
+
No agent-authored-artifact defect — not applicable. This fixes source code, and adds no self-triggered controller.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Side-Effects Review — a live conversation stays put, and a moved one gets its recent messages
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `session-pool-keep-and-recall`
|
|
4
|
+
**Date:** `2026-11-04`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** codex-cli gpt-6-astra, 2 rounds; first round's findings fixed; last round's verdict still serious, its design points stated as accepted limits, see the report
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
`SessionRouter` keeps an unowned key on this machine when a session for it is already running here, subject to every mandatory placement check, and confirms the claim at once. A new read-class mesh verb, `topic-history-pull`, lets a moved session fetch recent messages from the lease holder with no shared bearer token; the bearer call stays as the fallback and gains a deadline.
|
|
11
|
+
|
|
12
|
+
## Decision-point inventory
|
|
13
|
+
|
|
14
|
+
- Keep a live local session on a new placement — add — live session, no preferred machine, this machine passes placement alone with no escalation.
|
|
15
|
+
- Serve history to a peer — add — registered peer, read class, capped by the handler.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 1. Over-block
|
|
20
|
+
|
|
21
|
+
Keep could hold a conversation on a busier machine when a peer is cheaper. That is the point: a running session is not moved for cost. Overload, a lost workspace and a blocked quota all still move it, because placement refuses this machine alone.
|
|
22
|
+
|
|
23
|
+
## 2. Under-block
|
|
24
|
+
|
|
25
|
+
Sessions away from the lease holder with no ownership record are not found. A failed confirm is not retried by the router. Both are stated in the spec.
|
|
26
|
+
|
|
27
|
+
## 3. Level-of-abstraction fit
|
|
28
|
+
|
|
29
|
+
Keep sits in the router, the one place Telegram, Slack and the drain share, and reuses `decide`, the CAS and `confirmClaim`. Recall follows the existing pull-verb pattern.
|
|
30
|
+
|
|
31
|
+
## 4. Signal vs authority compliance
|
|
32
|
+
|
|
33
|
+
No judgment moves into a brittle check. `liveLocalSession` is a fact from the session manager; placement keeps its authority over eligibility, and a pin still wins.
|
|
34
|
+
|
|
35
|
+
## 5. Interactions
|
|
36
|
+
|
|
37
|
+
The drain's `forceReplace` uses failover placement, which keep does not touch. The Telegram confirmation after delivery still runs and finds the row already `active`, a no-op. Moves are unaffected: a moved key has an owner, or its old session has closed.
|
|
38
|
+
|
|
39
|
+
## 6. External surfaces
|
|
40
|
+
|
|
41
|
+
One new mesh verb. An older peer answers `no-handler` and the bearer fallback carries it. No HTTP route, config or user-visible change. It discloses to this agent's own machines what the bearer route already does.
|
|
42
|
+
|
|
43
|
+
## 7. Multi-machine posture
|
|
44
|
+
|
|
45
|
+
This is multi-machine code. It is inert on one machine: no mesh, and no router past dark. History is read-only and holds no replicated state. Ownership changes go through the existing CAS and journal, so no second authority appears.
|
|
46
|
+
|
|
47
|
+
## 8. Rollback cost
|
|
48
|
+
|
|
49
|
+
Revert. No stored state. `enabled:false` stops all routing at once.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Side-Effects Review — a topic's name always travels with its id
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `topic-name-beside-id`
|
|
4
|
+
**Date:** `2026-11-02`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required (wording only; no gate, sentinel, lifecycle or dispatch decision touched)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Tier 1 (wording in server-authored text; a revert fully undoes it). Operator rule (Justin,
|
|
11
|
+
2026-11-02, verbatim): "An Instar agent should ALWAYS have access to the topic name if they have
|
|
12
|
+
access to the topic ID. The name and ID should be inseparable." Live case: a peer's session was
|
|
13
|
+
told "topic 11882, the topic for echo" and told its user it could not see the topic name, though
|
|
14
|
+
the registry held "🤝 echo".
|
|
15
|
+
|
|
16
|
+
- New `src/messaging/shared/topicRef.ts`: `topicRef` / `TopicRef` / `telegramTopicRef` /
|
|
17
|
+
`topicNameFor` render `topic 11882 "🤝 echo"` or `topic 11882 (name unresolved)`. The name is
|
|
18
|
+
the caller's, else the registry's (`setTopicNameResolver`, wired at boot in `server.ts` to the
|
|
19
|
+
live `TelegramAdapter.getTopicName`), accepted only through `verifiedEntityName` and sanitized
|
|
20
|
+
with the existing `sanitizeTopicName` (≤120 chars).
|
|
21
|
+
- `buildInjectionTag` (`src/types/pipeline.ts`): the `[telegram:N …]` prefix now always carries the
|
|
22
|
+
name (registry fallback) or ` (name unresolved)`; the long-message reference tag passes the name.
|
|
23
|
+
- Threadline session text: `TopicLinkageHandler` notice lines and `ThreadlineRouter` spawn-prompt
|
|
24
|
+
topic hint; hub topic candidates (`HubIntentClassifier`, `hubCommands`) fall back to the
|
|
25
|
+
registry name instead of an invented `topic N`.
|
|
26
|
+
- Notices/attention items and session-facing prompts in `routes.ts`, `server.ts`, `SessionReaper`,
|
|
27
|
+
`AutonomousLivenessReconciler`, `OwnershipReconciler`, `OriginForwardToHolder`,
|
|
28
|
+
`OutboundAdvisory`, `MentorAutonomousGuardian`, `StaleOwnerReleaseEngine`, `PrHandLease`,
|
|
29
|
+
`TelegramSpendTopicChannel`, `ReapNotifier`, `ReapNoticeDrain`, `TopicReachabilityVerifier`,
|
|
30
|
+
`SeamlessOrchestratorEngine`, `ScopeVerifier`, `ColdStartFallbackReply`, `SessionManager`,
|
|
31
|
+
`TelegramAdapter` (session list).
|
|
32
|
+
- Ratchet `tests/unit/topic-ref-ratchet.test.ts`: per-file baseline of two remaining bare
|
|
33
|
+
`topic ${…}` renders; one already carries the name beside the id and one is a lifeline log.
|
|
34
|
+
A new non-log site fails.
|
|
35
|
+
|
|
36
|
+
Size: ~25 source files, ~120 changed lines + formatter + 4 test files. Effort: no spec rounds
|
|
37
|
+
(Tier 1), one commit.
|
|
38
|
+
|
|
39
|
+
## Decision-point inventory
|
|
40
|
+
|
|
41
|
+
None. Text rendering only; no gate, block, routing or lifecycle decision changes.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 1. Over-block
|
|
46
|
+
|
|
47
|
+
No block/allow surface.
|
|
48
|
+
|
|
49
|
+
## 2. Under-block
|
|
50
|
+
|
|
51
|
+
- Two non-log bare renders remain in the ratchet baseline: the InputGuard prompt already
|
|
52
|
+
gives the name beside the id, and one lifeline diagnostic is internal. Other log-only
|
|
53
|
+
renders are outside the ratchet; they are not a proof that every log line carries a name.
|
|
54
|
+
- A topic the registry has never named shows "(name unresolved)" until the adapter learns its name (rename events, startup backfill).
|
|
55
|
+
- Processes with no Telegram adapter (no Telegram configured) render every topic as unresolved.
|
|
56
|
+
- Attention item ids, condition keys and log lines are unchanged (ids, not prose).
|
|
57
|
+
|
|
58
|
+
## 3. Level-of-abstraction fit
|
|
59
|
+
|
|
60
|
+
One formatter in `messaging/shared`, beside the existing verified-identity rule it reuses, and one
|
|
61
|
+
late-bound resolver wired once at boot, so no component needs a new dependency.
|
|
62
|
+
|
|
63
|
+
## 4. Signal vs authority compliance
|
|
64
|
+
|
|
65
|
+
- [x] No — this change has no block/allow surface.
|
|
66
|
+
|
|
67
|
+
## 4b. Judgment-point check
|
|
68
|
+
|
|
69
|
+
No judgment point.
|
|
70
|
+
|
|
71
|
+
## 5. Interactions
|
|
72
|
+
|
|
73
|
+
- `[telegram:N` parsers (`InputGuard`, `SessionManager` tag match, `telegram-topic-context.sh`) anchor on `^\[telegram:(\d+)`; the name / marker follows the id, so they are unaffected. `InputGuard` provenance check compares ids only.
|
|
74
|
+
- The long-message reference tag and the bare tag are no longer byte-identical to the old `[telegram:N]` (tests that pinned those bytes were updated).
|
|
75
|
+
- The topic name is peer- or user-influenced text entering session prompts and LLM classifier prompts; it is sanitized exactly like the existing prefix name.
|
|
76
|
+
- Dedup on notice text: identical held-reply/attention bodies still dedupe (the name is stable per topic).
|
|
77
|
+
|
|
78
|
+
## 6. External surfaces
|
|
79
|
+
|
|
80
|
+
User-visible wording in attention items and notices gains the topic name. Session prompts gain the
|
|
81
|
+
name. Nothing sent to peers changes. No config switch (wording only; a revert is the rollback).
|
|
82
|
+
|
|
83
|
+
## 6b. Operator-surface quality
|
|
84
|
+
|
|
85
|
+
Attention titles become longer by the topic name; they stay one line.
|
|
86
|
+
|
|
87
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
88
|
+
|
|
89
|
+
Machine-local by design: each machine renders from its own adapter's registry, which already
|
|
90
|
+
replicates names through the existing topic-registry paths. A standby that has not yet learned a
|
|
91
|
+
name says "(name unresolved)" rather than guessing.
|
|
92
|
+
|
|
93
|
+
## 8. Rollback cost
|
|
94
|
+
|
|
95
|
+
Revert the PR; no persisted state, no migration.
|
|
96
|
+
|
|
97
|
+
## Conclusion
|
|
98
|
+
|
|
99
|
+
Wording-only change with a structural ratchet against regression.
|
|
100
|
+
|
|
101
|
+
## Evidence pointers
|
|
102
|
+
|
|
103
|
+
- tests/unit/topic-ref.test.ts
|
|
104
|
+
- tests/unit/topic-ref-ratchet.test.ts
|
|
105
|
+
- tests/integration/threadline/topic-name-beside-id.test.ts
|
|
106
|
+
- tests/e2e/topic-name-beside-id-alive.test.ts
|
|
107
|
+
|
|
108
|
+
## Class-Closure Declaration (display-only mirror)
|
|
109
|
+
|
|
110
|
+
- **`defectClass`** — `n/a`
|
|
111
|
+
- **`closure`** — `n/a`
|
|
112
|
+
- **reason** — rendering change; no self-triggered action.
|
|
113
|
+
|
|
114
|
+
## Main-merge review (2026-11-04)
|
|
115
|
+
|
|
116
|
+
After merging current main, four source files had acquired new bare topic labels: `SessionDrainRunner`, `AgentServer`, `server.ts`, and `WorkYieldRegistry`. They now use the same `topicRef` formatter. `OriginForwardToHolder.heldExpiryItem` also uses it while retaining main's condition key and attention-item shape. This is a Tier 1 wording repair in an existing formatter path. No new gate, block, routing choice, or static judgment heuristic was added; the signal-versus-authority rule in `docs/signal-vs-authority.md` is therefore unchanged.
|
|
117
|
+
|
|
118
|
+
Over-block: none. Under-block: the two baseline sites described above remain. The formatter is the right layer because all four callers need the same verified local topic name. Interactions: only notice and audit text changes; topic ids, attention condition keys, dedupe keys, transfer decisions, and Telegram delivery remain as before. External surface: an agent or operator may see the topic name beside the id in a transfer reason, held-reply notice, media degradation, or maintenance work label. Multi-machine posture: machine-local registry reads by design, because a serving machine knows the topic names it owns; unresolved names are stated plainly. The changes add no durable state, URL, or new notifier, so they do not create a new one-voice or transfer obligation. Rollback is a revert of this PR; no data migration is needed.
|
|
119
|
+
|
|
120
|
+
## Scope audit (2026-11-04)
|
|
121
|
+
|
|
122
|
+
The first baseline included errors, refusal reasons, recovery notices, and command output that
|
|
123
|
+
an agent or operator can read. Those are part of the operator's rule, so they now call
|
|
124
|
+
`topicRef` too. This includes desktop confirmation, profile transfer disclosure, session
|
|
125
|
+
recovery, PromiseBeacon, Telegram sender failures, and API error text. The changed log lines
|
|
126
|
+
use the same formatter for consistency. This widens wording coverage only; no delivery target,
|
|
127
|
+
ownership decision, or durable key changed. The local resolver can still have no verified name,
|
|
128
|
+
in which case the text explicitly says `name unresolved`.
|
|
129
|
+
|
|
130
|
+
The issues-group refusal text is also read by the legacy relay replay classifier. Its parser
|
|
131
|
+
now accepts the old bare-id form plus the new verified-name and unresolved-name forms; unit
|
|
132
|
+
coverage checks all three so queued replies retain their replay classification across update.
|
|
133
|
+
|
|
134
|
+
The full unit run exposed three integration points in the merged branch. The watch-only
|
|
135
|
+
maintenance import allowlist now explicitly permits the pure formatter; the held-reply
|
|
136
|
+
assertion expects the unresolved-name wording; and the release note remains under
|
|
137
|
+
`upgrades/next/` so the release assembler consumes it. All three focused tests pass.
|
|
138
|
+
|
|
139
|
+
The new GitHub run exposed a runner-specific failure in the existing Claude-key E2E test:
|
|
140
|
+
the test's CLI child loaded Config before key handling, and Config required the configured
|
|
141
|
+
framework binary. GitHub's runner has no Claude CLI. Main independently fixed this
|
|
142
|
+
production defect in PR #2719 while this PR was running. The merge retains main's stronger
|
|
143
|
+
test, which runs the CLI with no framework binary on PATH and verifies the key path directly.
|
|
144
|
+
This PR's temporary test stub was dropped during conflict resolution.
|
|
145
|
+
|
|
146
|
+
The later CI run found one memory-recovery test timing out at the default ten-second
|
|
147
|
+
limit under a loaded Node 20 shard. The same file passed locally in 2.3 seconds; that
|
|
148
|
+
test now allows thirty seconds for the real subprocess checks. The local full integration
|
|
149
|
+
run found this host below the media store's five-percent free-disk floor, so three
|
|
150
|
+
unrelated media-flow fixtures refused uploads. Those fixtures now supply a healthy disk
|
|
151
|
+
reading for their media store instances. Production disk refusal remains unchanged and
|
|
152
|
+
retains its separate tests.
|