instar 1.3.213 → 1.3.215
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/route.d.ts.map +1 -1
- package/dist/commands/route.js +1 -0
- package/dist/commands/route.js.map +1 -1
- package/dist/core/GeminiCliIntelligenceProvider.d.ts +3 -0
- package/dist/core/GeminiCliIntelligenceProvider.d.ts.map +1 -1
- package/dist/core/GeminiCliIntelligenceProvider.js +51 -21
- package/dist/core/GeminiCliIntelligenceProvider.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +15 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/frameworkSessionLaunch.d.ts.map +1 -1
- package/dist/core/frameworkSessionLaunch.js +2 -1
- package/dist/core/frameworkSessionLaunch.js.map +1 -1
- package/dist/providers/adapters/gemini-cli/config.d.ts +3 -0
- package/dist/providers/adapters/gemini-cli/config.d.ts.map +1 -1
- package/dist/providers/adapters/gemini-cli/config.js.map +1 -1
- package/dist/providers/adapters/gemini-cli/errors.d.ts.map +1 -1
- package/dist/providers/adapters/gemini-cli/errors.js +4 -2
- package/dist/providers/adapters/gemini-cli/errors.js.map +1 -1
- package/dist/providers/adapters/gemini-cli/models.d.ts +7 -4
- package/dist/providers/adapters/gemini-cli/models.d.ts.map +1 -1
- package/dist/providers/adapters/gemini-cli/models.js +10 -3
- package/dist/providers/adapters/gemini-cli/models.js.map +1 -1
- package/dist/providers/adapters/gemini-cli/observability/geminiCapacityPolicy.d.ts +54 -0
- package/dist/providers/adapters/gemini-cli/observability/geminiCapacityPolicy.d.ts.map +1 -0
- package/dist/providers/adapters/gemini-cli/observability/geminiCapacityPolicy.js +111 -0
- package/dist/providers/adapters/gemini-cli/observability/geminiCapacityPolicy.js.map +1 -0
- package/dist/providers/adapters/gemini-cli/transport/oneShotCompletion.d.ts.map +1 -1
- package/dist/providers/adapters/gemini-cli/transport/oneShotCompletion.js +55 -23
- package/dist/providers/adapters/gemini-cli/transport/oneShotCompletion.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +1 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/SecretDrop.d.ts +19 -6
- package/dist/server/SecretDrop.d.ts.map +1 -1
- package/dist/server/SecretDrop.js +79 -30
- package/dist/server/SecretDrop.js.map +1 -1
- package/dist/server/routes.js +1 -1
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +64 -64
- package/src/scaffold/templates.ts +1 -0
- package/src/templates/scripts/secret-drop-retrieve.mjs +65 -2
- package/upgrades/1.3.214.md +65 -0
- package/upgrades/1.3.215.md +41 -0
- package/upgrades/gemini-capacity-policy.eli16.md +21 -0
- package/upgrades/side-effects/gemini-capacity-policy.md +139 -0
- package/upgrades/side-effects/secret-drop-sliding-window.md +83 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Secret Drop's stored-submission lifetime was reworked so a submitted secret can no
|
|
9
|
+
longer be deleted out from under an active consumer.
|
|
10
|
+
|
|
11
|
+
- **Server (`SecretDrop.ts`)** — the post-submission store now uses a **sliding idle
|
|
12
|
+
window** instead of a fixed 5-minute timer. The cleanup timer re-arms on every
|
|
13
|
+
`peekReceived`, so a secret that is actively being retrieved never expires. The idle
|
|
14
|
+
window is 15 minutes (was 5) and a new per-token `receivedDeadline` enforces a hard
|
|
15
|
+
**30-minute absolute cap** (`armReceivedCleanup` clamps each re-arm with
|
|
16
|
+
`Math.min(idle, deadline − now)`), so even a continuously-polled secret is purged.
|
|
17
|
+
`consumeReceived`/`shutdown` clear the new deadline map; the stuck-consumer event's
|
|
18
|
+
`minutesUntilCleanup` is derived from the deadline.
|
|
19
|
+
- **Consumer (`secret-drop-retrieve.mjs`)** — new `--run -- <cmd>` mode performs an
|
|
20
|
+
**atomic use-and-consume**: it pipes the field value to the command's stdin and
|
|
21
|
+
consumes the submission only if the command exits 0. A failed or launch-error
|
|
22
|
+
handoff never destroys the secret, making consume-on-failure structurally impossible.
|
|
23
|
+
- **Awareness/migration** — the CLAUDE.md scaffold documents `--run` for new agents;
|
|
24
|
+
an idempotent `PostUpdateMigrator` block adds the guidance to existing agents that
|
|
25
|
+
already have the hardened helper. The helper script itself ships via the existing
|
|
26
|
+
always-overwrite relay-script refresh.
|
|
27
|
+
|
|
28
|
+
## What to Tell Your User
|
|
29
|
+
|
|
30
|
+
- **Secret Drop is now sturdier**: "If you hand me a password or key through a secure
|
|
31
|
+
link, it won't quietly expire while I'm in the middle of using it anymore — so you
|
|
32
|
+
shouldn't have to send the same thing twice. And if a step fails, I keep what you
|
|
33
|
+
sent so we can retry, instead of throwing it away." (Note: a secret still lives only
|
|
34
|
+
in memory, so a server restart still clears anything not yet used — that's the
|
|
35
|
+
security trade-off, unchanged.)
|
|
36
|
+
|
|
37
|
+
## Summary of New Capabilities
|
|
38
|
+
|
|
39
|
+
| Capability | How to Use |
|
|
40
|
+
|-----------|-----------|
|
|
41
|
+
| Sliding retrieval window + 30-min cap | automatic |
|
|
42
|
+
| Atomic use-and-consume | `secret-drop-retrieve.mjs TOKEN field --run -- <cmd>` |
|
|
43
|
+
|
|
44
|
+
## Evidence
|
|
45
|
+
|
|
46
|
+
**Reproduction (observed live, 2026-06-02):** during a multi-step credential handoff
|
|
47
|
+
(Bitwarden login, then a GitHub token) the operator had to resubmit the same secret
|
|
48
|
+
roughly six times. Each time, the submission sat in the store while a multi-step
|
|
49
|
+
retrieval ran; the fixed 5-minute timer deleted it mid-flow regardless of the active
|
|
50
|
+
retrievals, and a standalone consume fired after a step that had not yet succeeded —
|
|
51
|
+
destroying the secret with no recovery but resubmission.
|
|
52
|
+
|
|
53
|
+
**Before/after (deterministic, fake-timer unit tests in
|
|
54
|
+
`tests/unit/SecretDrop.test.ts`):**
|
|
55
|
+
- Before this change, a submission was unconditionally deleted 5 minutes after
|
|
56
|
+
submit. After it: a submission peeked at 14 min and again at 28 min is still present
|
|
57
|
+
(the window slid on each read); an untouched submission is still cleaned up after the
|
|
58
|
+
idle window; and a submission polled every 10 min is nonetheless purged once past the
|
|
59
|
+
30-min absolute cap.
|
|
60
|
+
- `--run` mode: consume is invoked only on child exit 0; on non-zero exit or a launch
|
|
61
|
+
error the submission is left intact (verified by inspecting the spawnSync branch and
|
|
62
|
+
the documented `gh auth login --with-token` example).
|
|
63
|
+
|
|
64
|
+
Suites: SecretDrop 37/37, migration 15/15 green; `tsc --noEmit` clean. An independent
|
|
65
|
+
second-pass reviewer concurred with the side-effects review.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Gemini CLI one-shot calls now have a provider-specific capacity policy. When
|
|
9
|
+
Gemini reports a 429, `QUOTA_EXHAUSTED`, `resource exhausted`, or a usage/quota
|
|
10
|
+
limit, Instar parses any reset window Gemini provides, retries only short
|
|
11
|
+
capacity windows once, and otherwise records a local defer window so subsequent
|
|
12
|
+
calls fail fast instead of spawning another doomed Gemini process.
|
|
13
|
+
|
|
14
|
+
Explicit caller-supplied raw Gemini model ids continue to pass through to the
|
|
15
|
+
Gemini CLI. Only the automatic `capacityPolicy.fallbackModel` path is
|
|
16
|
+
constrained to the known local Gemini model set. When that fallback is valid,
|
|
17
|
+
both Gemini execution paths rebuild `gemini -m <model>` on retry from the
|
|
18
|
+
policy-selected model, so fallback configuration is not just resolved, it is
|
|
19
|
+
actually applied to the next CLI invocation.
|
|
20
|
+
|
|
21
|
+
## What to Tell Your User
|
|
22
|
+
|
|
23
|
+
- **Gemini quota handling is calmer:** "When Gemini says its quota is exhausted,
|
|
24
|
+
I now remember the reset window and stop repeatedly poking it. Short capacity
|
|
25
|
+
blips get one bounded retry; longer quota windows are surfaced as a clear
|
|
26
|
+
defer instead of looking like a stalled agent."
|
|
27
|
+
|
|
28
|
+
## Summary of New Capabilities
|
|
29
|
+
|
|
30
|
+
| Capability | How to Use |
|
|
31
|
+
|-----------|------------|
|
|
32
|
+
| Gemini capacity defer window | Automatic for Gemini CLI one-shot calls |
|
|
33
|
+
| Short Gemini capacity retry | Automatic, one bounded retry for short windows |
|
|
34
|
+
| Known-only Gemini capacity fallback | Automatic; `fallbackModel` swaps only when the fallback is a known Gemini model |
|
|
35
|
+
|
|
36
|
+
## Evidence
|
|
37
|
+
|
|
38
|
+
- `npx vitest run tests/unit/gemini-cli-adapter.test.ts tests/unit/geminiCapacityPolicy.test.ts tests/unit/frameworkSessionLaunch.test.ts tests/integration/gemini-capacity-policy-integration.test.ts tests/e2e/gemini-capacity-policy-lifecycle.test.ts`
|
|
39
|
+
— 5 files / 80 tests passed, including raw-model pass-through and spawned
|
|
40
|
+
retry argv assertions.
|
|
41
|
+
- `npx tsc --noEmit`
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Gemini Capacity Handling — ELI16
|
|
2
|
+
|
|
3
|
+
Viewable private artifact:
|
|
4
|
+
https://codey.dawn-tunnel.dev/view/b5873ea2-17ba-4adf-9d1a-f0e1c48f781e?sig=3e2c7d2f4e0852cf91496f79ce25aeca72ce778c92d3278e101b63bec90400af
|
|
5
|
+
|
|
6
|
+
Gemini sometimes says, "I'm out of capacity right now; try again after this
|
|
7
|
+
reset window." Before this change, Instar treated that too much like an ordinary
|
|
8
|
+
failure. The next Gemini call could try again immediately, hit the same quota
|
|
9
|
+
wall, and make the agent look stuck. One fallback path also guessed an old model
|
|
10
|
+
name, `gemini-2.0-flash`, which Gemini rejected.
|
|
11
|
+
|
|
12
|
+
This change gives Gemini its own capacity rule. If the reset is short, Instar
|
|
13
|
+
waits briefly and tries once. If Gemini gives a longer reset window, Instar
|
|
14
|
+
remembers it and refuses later Gemini calls locally until the window passes.
|
|
15
|
+
That means no repeated doomed Gemini subprocesses and a clearer error for the
|
|
16
|
+
agent/operator.
|
|
17
|
+
|
|
18
|
+
It also limits Gemini model choices to the verified names we know work:
|
|
19
|
+
`gemini-2.5-flash` and `gemini-2.5-pro`. If some code asks for an unknown Gemini
|
|
20
|
+
model, Instar falls back to `gemini-2.5-flash` instead of sending a guessed model
|
|
21
|
+
to Gemini and getting a 404.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Side-Effects Review — Gemini capacity policy
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `gemini-capacity-policy`
|
|
4
|
+
**Date:** `2026-06-03`
|
|
5
|
+
**Author:** `instar-codey`
|
|
6
|
+
**Second-pass reviewer:** `not required`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
This change adds a Gemini-specific capacity policy beside the existing Gemini
|
|
11
|
+
adapter observability code. Gemini one-shot calls now classify quota/rate-limit
|
|
12
|
+
failures, parse reset windows such as `quota will reset after 7h32m28s`, retry
|
|
13
|
+
only short capacity windows once, and record a process-local defer window for
|
|
14
|
+
longer quota exhaustion. While deferred, later calls fail locally with a retry
|
|
15
|
+
hint instead of spawning another Gemini CLI process that would hit the same
|
|
16
|
+
quota wall.
|
|
17
|
+
|
|
18
|
+
Review update: the optional `capacityPolicy.fallbackModel` is now wired into
|
|
19
|
+
the retry loop instead of only being resolved in the policy decision. Both
|
|
20
|
+
Gemini execution paths rebuild `gemini -m <model>` on each retry attempt from
|
|
21
|
+
the current policy-selected model, so a configured fallback actually changes
|
|
22
|
+
the spawned CLI argv. Explicit caller-supplied raw model ids still pass through
|
|
23
|
+
the primary resolver; only automatic capacity fallback is constrained to known
|
|
24
|
+
Gemini models.
|
|
25
|
+
|
|
26
|
+
The change also constrains automatic Gemini fallback selection to verified known
|
|
27
|
+
models: `gemini-2.5-flash` and `gemini-2.5-pro`. Explicit raw Gemini model ids
|
|
28
|
+
continue to pass through to the CLI because they represent caller intent. The
|
|
29
|
+
bad `gemini-2.0-flash` fallback observed during the mentor loop is avoided by
|
|
30
|
+
the known-only fallback helper rather than by rewriting every raw model id.
|
|
31
|
+
|
|
32
|
+
## Decision-point inventory
|
|
33
|
+
|
|
34
|
+
- `isGeminiCapacityError` — add — classifies Gemini quota/rate-limit/capacity
|
|
35
|
+
error strings.
|
|
36
|
+
- `parseGeminiRetryAfterMs` — add — extracts reset windows from Gemini stderr.
|
|
37
|
+
- `decideGeminiCapacityPolicy` — add — chooses `none`, `retry`, or `defer`.
|
|
38
|
+
- `recordGeminiCapacityDeferral` / `getGeminiCapacityGate` — add — process-local
|
|
39
|
+
defer state for Gemini calls.
|
|
40
|
+
- Gemini fallback resolution — modify — automatic capacity fallback ids must be
|
|
41
|
+
in the known set or the current caller-selected model is kept.
|
|
42
|
+
- `GeminiCliIntelligenceProvider` and adapter one-shot transport — modify — both
|
|
43
|
+
apply the policy before and after spawning Gemini.
|
|
44
|
+
- Retry argv rebuild — modify — short-window retries rebuild the Gemini argv
|
|
45
|
+
from `decision.model`, so `capacityPolicy.fallbackModel` is applied to the
|
|
46
|
+
next spawned process.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 1. Over-block
|
|
51
|
+
|
|
52
|
+
The main over-block risk is a false-positive capacity classification that defers
|
|
53
|
+
Gemini when the failure was not actually quota related. The classifier is
|
|
54
|
+
deliberately narrow: explicit `429`, `QUOTA_EXHAUSTED`, `resource exhausted`,
|
|
55
|
+
`rate limit`, quota, usage-limit, or capacity language. Generic parse errors,
|
|
56
|
+
syntax errors, binary-not-found errors, and ordinary non-zero exits do not defer.
|
|
57
|
+
|
|
58
|
+
The known-model constraint applies only to automatic capacity fallback. Explicit
|
|
59
|
+
caller-selected Gemini model ids still pass through to the CLI, so newly valid
|
|
60
|
+
Gemini ids are not blocked by this policy. If `capacityPolicy.fallbackModel` is
|
|
61
|
+
unknown, the retry keeps the caller's current model instead of swapping to a
|
|
62
|
+
guessed fallback.
|
|
63
|
+
|
|
64
|
+
## 2. Under-block
|
|
65
|
+
|
|
66
|
+
This policy is process-local. A server restart forgets the defer window and the
|
|
67
|
+
first post-restart Gemini call may probe the provider again. That matches the
|
|
68
|
+
existing LLM circuit-breaker shape and keeps the change small. A future durable
|
|
69
|
+
capacity ledger could persist provider reset windows across restarts if repeated
|
|
70
|
+
restart-probes become noisy.
|
|
71
|
+
|
|
72
|
+
This does not discover the full Gemini model catalog dynamically. It uses the
|
|
73
|
+
currently verified set and keeps the list explicit. Dynamic discovery is a
|
|
74
|
+
separate model-catalog problem, not part of quota handling.
|
|
75
|
+
|
|
76
|
+
## 3. Level-of-abstraction fit
|
|
77
|
+
|
|
78
|
+
The policy belongs at the Gemini provider boundary, not at each caller. The
|
|
79
|
+
adapter one-shot transport and live `GeminiCliIntelligenceProvider` are the
|
|
80
|
+
places that see Gemini stderr and own whether to spawn Gemini again. Keeping the
|
|
81
|
+
decision there means reviewers, route, setup narrative calls, and future Gemini
|
|
82
|
+
one-shots share the same capacity behavior.
|
|
83
|
+
|
|
84
|
+
Known-model fallback belongs in the capacity-policy fallback helper because that
|
|
85
|
+
is the only automatic model swap path in this change. Primary model resolution
|
|
86
|
+
still maps canonical tiers and otherwise respects explicit raw model ids.
|
|
87
|
+
|
|
88
|
+
## 4. Signal vs authority compliance
|
|
89
|
+
|
|
90
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
91
|
+
|
|
92
|
+
- [x] Not applicable to conversational/product judgment — this is deterministic
|
|
93
|
+
provider-capacity handling and model-id validation at the transport boundary.
|
|
94
|
+
|
|
95
|
+
The defer gate is not making a semantic judgment about user intent. It acts only
|
|
96
|
+
after Gemini itself reports a quota/capacity condition or while the recorded
|
|
97
|
+
reset window from that provider report is still active.
|
|
98
|
+
|
|
99
|
+
## 5. Interactions
|
|
100
|
+
|
|
101
|
+
- **Global LLM circuit breaker:** The Gemini provider still throws clear
|
|
102
|
+
quota/rate-limit text, so the existing circuit breaker can continue to observe
|
|
103
|
+
and pause broader LLM-backed work. The Gemini policy additionally prevents
|
|
104
|
+
repeated Gemini subprocesses during a known Gemini reset window.
|
|
105
|
+
- **Setup wizard:** Gemini narrative fallback continues to work; quota failures
|
|
106
|
+
become clearer and do not repeatedly spawn Gemini.
|
|
107
|
+
- **Route override detector:** The known-model list now includes
|
|
108
|
+
`gemini-2.5-flash`, so the verified default is recognized.
|
|
109
|
+
- **Session launch:** Unchanged by the capacity fallback review fix; the
|
|
110
|
+
known-model gate is isolated to automatic provider retry fallback.
|
|
111
|
+
|
|
112
|
+
## 6. External surfaces
|
|
113
|
+
|
|
114
|
+
Users may see clearer Gemini quota/defer errors instead of a generic Gemini CLI
|
|
115
|
+
failure or a stalled task. Operators can rely on `gemini-2.5-flash` as the safe
|
|
116
|
+
automatic capacity fallback when configured. Explicit caller-supplied model ids
|
|
117
|
+
continue to pass through. No config migration, schema change, or external API
|
|
118
|
+
change is introduced.
|
|
119
|
+
|
|
120
|
+
## 7. Rollback cost
|
|
121
|
+
|
|
122
|
+
Rollback is a code revert of the Gemini policy module, the two provider wiring
|
|
123
|
+
changes, the fallback known-list change, tests, and these artifacts. No
|
|
124
|
+
data migration is required. A running process that had recorded a defer window
|
|
125
|
+
would forget it on restart.
|
|
126
|
+
|
|
127
|
+
## Conclusion
|
|
128
|
+
|
|
129
|
+
The change is a narrow sibling to the Codex capacity/model-swap work, scoped to
|
|
130
|
+
Gemini's actual error and model surfaces. It prevents repeated doomed Gemini CLI
|
|
131
|
+
spawns during quota windows, avoids guessed model fallbacks, and pins the
|
|
132
|
+
behavior with unit, integration, and E2E tests.
|
|
133
|
+
|
|
134
|
+
## Evidence pointers
|
|
135
|
+
|
|
136
|
+
- `tests/unit/geminiCapacityPolicy.test.ts`
|
|
137
|
+
- `tests/integration/gemini-capacity-policy-integration.test.ts`
|
|
138
|
+
- `tests/e2e/gemini-capacity-policy-lifecycle.test.ts`
|
|
139
|
+
- `tests/unit/frameworkSessionLaunch.test.ts`
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Side-effects review — Secret Drop Sliding Window + Atomic Use-and-Consume
|
|
2
|
+
|
|
3
|
+
**Spec:** `docs/specs/secret-drop-sliding-window.md`
|
|
4
|
+
**Files:** `src/server/SecretDrop.ts`, `src/templates/scripts/secret-drop-retrieve.mjs`, `tests/unit/SecretDrop.test.ts`, `tests/unit/PostUpdateMigrator-secretDropHardenedRetrieve.test.ts`, `src/core/PostUpdateMigrator.ts`, `src/scaffold/templates.ts`
|
|
5
|
+
|
|
6
|
+
## 1. Over-block — what legitimate inputs does this reject that it shouldn't?
|
|
7
|
+
|
|
8
|
+
Nothing new is rejected. Submission validation (CSRF, required fields, R1a signature)
|
|
9
|
+
is unchanged. The sliding window only affects how long an accepted submission is
|
|
10
|
+
*retained*; it never rejects a submission or a retrieve. `--run` adds a code path but
|
|
11
|
+
the default retrieve/`--names`/`--consume` behaviors are byte-for-byte unchanged.
|
|
12
|
+
|
|
13
|
+
## 2. Under-block — what failure modes does this still miss?
|
|
14
|
+
|
|
15
|
+
- **Server restart loses an unconsumed secret.** Explicitly out of scope (in-memory by
|
|
16
|
+
design); contract documented in the spec; encrypted-at-rest tracked as follow-up
|
|
17
|
+
(`fb-391a4a30-de9`).
|
|
18
|
+
- **An agent that uses the destructive `consumeReceived`/`--consume` mid-flow can still
|
|
19
|
+
drop a secret.** The `--run` mode + CLAUDE.md guidance steer away from this, but the
|
|
20
|
+
standalone `--consume` is retained for back-compat and is still misusable. Mitigated,
|
|
21
|
+
not eliminated. Accepted: removing `--consume` outright would be a breaking change to
|
|
22
|
+
any caller already using it.
|
|
23
|
+
|
|
24
|
+
## 3. Level-of-abstraction fit
|
|
25
|
+
|
|
26
|
+
Correct layer. Lifetime management belongs in `SecretDrop` (it owns the store and the
|
|
27
|
+
timers). The atomic use-and-consume belongs in the consumer helper (it owns the
|
|
28
|
+
hand-off to the command). No higher/lower layer is a better owner, and no smarter gate
|
|
29
|
+
exists that this should feed instead.
|
|
30
|
+
|
|
31
|
+
## 4. Signal vs authority compliance
|
|
32
|
+
|
|
33
|
+
Compliant. This adds no decision point that gates information flow or blocks actions.
|
|
34
|
+
The `--run` "consume only on exit 0" is a success gate on a local subprocess, not an
|
|
35
|
+
authority over agent behavior. No brittle-check-with-blocking-authority is introduced.
|
|
36
|
+
(Ref: `docs/signal-vs-authority.md`.)
|
|
37
|
+
|
|
38
|
+
## 5. Interactions
|
|
39
|
+
|
|
40
|
+
- **Stuck-consumer timer:** still fires at 60s; `minutesUntilCleanup` now derives from
|
|
41
|
+
`receivedDeadline` (true purge time) — more accurate, not less. The stuck timer is
|
|
42
|
+
NOT re-armed on peek (deliberate: it's a "nobody has consumed this yet" nudge, and
|
|
43
|
+
the absolute deadline it reports is fixed at submit). No double-fire, no race.
|
|
44
|
+
- **Cleanup timer:** centralized in `armReceivedCleanup`; each re-arm clears the prior
|
|
45
|
+
timer first (no timer leak). `consumeReceived`/`shutdown` clear the timer, the stuck
|
|
46
|
+
timer, AND the new `receivedDeadline` map (no map leak).
|
|
47
|
+
- **`--consume` flag and `--run`:** mutually independent; `--run` consumes via the same
|
|
48
|
+
`?consume=true` endpoint after success. No shadowing.
|
|
49
|
+
|
|
50
|
+
## 6. External surfaces
|
|
51
|
+
|
|
52
|
+
- **Other agents:** the helper template change reaches every agent via the
|
|
53
|
+
always-overwrite relay-script refresh; the server change ships via npm. CLAUDE.md
|
|
54
|
+
awareness reaches new agents (scaffold) and existing agents (idempotent migrator
|
|
55
|
+
block, tested). No external API shape change — `/secrets/retrieve/:token` and
|
|
56
|
+
`?consume=true` are unchanged.
|
|
57
|
+
- **Timing/runtime dependence:** the window is wall-clock based (setTimeout); fake-timer
|
|
58
|
+
tests cover the boundaries deterministically. No dependence on conversation state.
|
|
59
|
+
|
|
60
|
+
## 7. Rollback cost
|
|
61
|
+
|
|
62
|
+
Pure code revert — no data migration, no agent-state repair. Reverting restores the
|
|
63
|
+
fixed 5-min window and removes `--run`; the standalone `--consume` path is untouched
|
|
64
|
+
throughout, so nothing depends on the new behavior to function. The migrator block is
|
|
65
|
+
idempotent and additive (a revert simply stops adding the bullet; already-migrated
|
|
66
|
+
CLAUDE.md files keep a harmless accurate bullet).
|
|
67
|
+
|
|
68
|
+
## Tier
|
|
69
|
+
|
|
70
|
+
**Tier 2.** Risk floor 2 (safety-invariant proximity: SecretDrop / never-on-disk).
|
|
71
|
+
Declared at the floor — not below it. Full ceremony: converged + approved spec, ELI16,
|
|
72
|
+
this artifact, second-pass review, trace.
|
|
73
|
+
|
|
74
|
+
## Second-pass review (independent)
|
|
75
|
+
|
|
76
|
+
An independent reviewer audited this artifact against the code and verified each
|
|
77
|
+
claim: (1) no timer/`receivedDeadline` map leak — every add has a matching clear on
|
|
78
|
+
consume/shutdown/re-arm; (2) the sliding window cannot exceed the 30-min cap (the
|
|
79
|
+
`Math.min(IDLE, deadline−now)` clamp enforces it); (3) `--run` consumes only on exit
|
|
80
|
+
0, never on launch error or non-zero exit, and the value reaches the subprocess via
|
|
81
|
+
stdin only — never stdout/argv; (4) signal-vs-authority compliant (no brittle gate
|
|
82
|
+
with blocking authority); (5) the stuck-consumer timer is correctly NOT re-armed on
|
|
83
|
+
peek. **Verdict: "Concur with the review."**
|