instar 1.3.214 → 1.3.216
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/frameworkSessionLaunch.d.ts.map +1 -1
- package/dist/core/frameworkSessionLaunch.js +2 -1
- package/dist/core/frameworkSessionLaunch.js.map +1 -1
- package/dist/monitoring/ApprenticeshipCycleStore.d.ts +52 -0
- package/dist/monitoring/ApprenticeshipCycleStore.d.ts.map +1 -0
- package/dist/monitoring/ApprenticeshipCycleStore.js +190 -0
- package/dist/monitoring/ApprenticeshipCycleStore.js.map +1 -0
- 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/server/AgentServer.d.ts +1 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +28 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +3 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +55 -1
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +47 -47
- package/upgrades/1.3.215.md +41 -0
- package/upgrades/1.3.216.md +44 -0
- package/upgrades/apprenticeship-cycle-store.eli16.md +62 -0
- package/upgrades/gemini-capacity-policy.eli16.md +21 -0
- package/upgrades/side-effects/apprenticeship-cycle-store.md +109 -0
- package/upgrades/side-effects/gemini-capacity-policy.md +139 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Side-Effects Review — Apprenticeship Cycle Store
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `apprenticeship-cycle-store`
|
|
4
|
+
**Date:** `2026-06-03`
|
|
5
|
+
**Author:** `instar-codey`
|
|
6
|
+
**Second-pass reviewer:** `not required`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Adds `ApprenticeshipCycleStore`, a small better-sqlite3 store for one row per
|
|
11
|
+
apprenticeship differential cycle, plus authenticated HTTP routes for recording,
|
|
12
|
+
listing, fetching, and closing cycles. The server creates
|
|
13
|
+
`server-data/apprenticeship-cycles.db` when a state directory is available and
|
|
14
|
+
registers the SQLite handle with `SqliteRegistry`.
|
|
15
|
+
|
|
16
|
+
## Decision-point inventory
|
|
17
|
+
|
|
18
|
+
- `ApprenticeshipCycleStore.record` — add — validates required fields, stores
|
|
19
|
+
array fields as JSON, and defaults status to `open`.
|
|
20
|
+
- `ApprenticeshipCycleStore.list` — add — lists recent cycles globally or by
|
|
21
|
+
`instanceId`, with a bounded positive limit.
|
|
22
|
+
- `ApprenticeshipCycleStore.get` — add — returns one parsed cycle or null.
|
|
23
|
+
- `ApprenticeshipCycleStore.closeCycle` — add — marks a cycle closed and returns
|
|
24
|
+
the updated parsed row.
|
|
25
|
+
- `/apprenticeship/cycles*` routes — add — bearer-protected CRUD-style API with
|
|
26
|
+
503 when the store is unavailable, 400 for invalid input, and 404 for unknown
|
|
27
|
+
ids.
|
|
28
|
+
|
|
29
|
+
## 1. Over-block
|
|
30
|
+
|
|
31
|
+
The store rejects missing `instanceId`, non-positive `cycleNumber`, empty `task`,
|
|
32
|
+
empty `menteeOutput`, and non-string entries in array fields. That is intentional:
|
|
33
|
+
these are structural capture records, and accepting malformed rows would make the
|
|
34
|
+
later retro-harvest less reliable.
|
|
35
|
+
|
|
36
|
+
The route layer returns 503 when the store is not wired. This is stricter than
|
|
37
|
+
returning an empty list, but it is the right failure mode because callers need to
|
|
38
|
+
know the feature is unavailable rather than "no cycles exist."
|
|
39
|
+
|
|
40
|
+
## 2. Under-block
|
|
41
|
+
|
|
42
|
+
The store does not enforce that `instanceId` references an existing
|
|
43
|
+
apprenticeship instance. That keeps this Tier-1 change additive and avoids
|
|
44
|
+
coupling the cycle recorder to instance lifecycle transitions. A later workflow
|
|
45
|
+
layer can add instance-aware capture if it needs that guarantee.
|
|
46
|
+
|
|
47
|
+
The `coaching` and `kind` fields are plain strings, not constrained enums. The
|
|
48
|
+
current default `kind` is `differential-cycle`; preserving strings keeps room for
|
|
49
|
+
future cycle subtypes without a migration.
|
|
50
|
+
|
|
51
|
+
## 3. Level-of-abstraction fit
|
|
52
|
+
|
|
53
|
+
Persistence belongs in `src/monitoring` with the other small operational stores,
|
|
54
|
+
not in the apprenticeship lifecycle JSON registry. The lifecycle registry owns
|
|
55
|
+
instance state and gates; the cycle store owns repeatable evidence captured
|
|
56
|
+
during an active mentorship.
|
|
57
|
+
|
|
58
|
+
The HTTP routes stay thin: they validate availability, call the store, and map
|
|
59
|
+
store validation errors to 400 responses.
|
|
60
|
+
|
|
61
|
+
## 4. Signal vs authority compliance
|
|
62
|
+
|
|
63
|
+
No conversational/product judgment is delegated to brittle logic. The change only
|
|
64
|
+
persists explicit caller-provided fields and exposes them through authenticated
|
|
65
|
+
routes. It does not decide whether a cycle was good, whether a mentor was right,
|
|
66
|
+
or whether an instance may complete.
|
|
67
|
+
|
|
68
|
+
## 5. Interactions
|
|
69
|
+
|
|
70
|
+
- **SqliteRegistry:** the store registers and unregisters its handle so native
|
|
71
|
+
SQLite lifecycle checks include the new database.
|
|
72
|
+
- **AgentServer shutdown:** the store closes during server stop, best-effort,
|
|
73
|
+
beside the other monitoring stores.
|
|
74
|
+
- **ApprenticeshipProgram:** instance routes remain unchanged. Cycle capture is
|
|
75
|
+
adjacent to, not inside, the lifecycle transition gate.
|
|
76
|
+
- **Monitoring/e2e:** the e2e alive path asserts `POST /apprenticeship/cycles`
|
|
77
|
+
returns 201 when the server has the store and not 503.
|
|
78
|
+
|
|
79
|
+
## 6. External surfaces
|
|
80
|
+
|
|
81
|
+
Adds four bearer-authenticated API routes:
|
|
82
|
+
|
|
83
|
+
- `POST /apprenticeship/cycles`
|
|
84
|
+
- `GET /apprenticeship/cycles?instanceId=&limit=`
|
|
85
|
+
- `GET /apprenticeship/cycles/:id`
|
|
86
|
+
- `POST /apprenticeship/cycles/:id/close`
|
|
87
|
+
|
|
88
|
+
Adds one database file under server state when the server is running:
|
|
89
|
+
`server-data/apprenticeship-cycles.db`.
|
|
90
|
+
|
|
91
|
+
## 7. Rollback cost
|
|
92
|
+
|
|
93
|
+
Rollback is a code and route revert. Existing `apprenticeship-cycles.db` files
|
|
94
|
+
can remain inert on disk; the server simply stops opening them after rollback.
|
|
95
|
+
No migration is required because no existing schema is modified.
|
|
96
|
+
|
|
97
|
+
## Conclusion
|
|
98
|
+
|
|
99
|
+
Ship. This is an additive Tier-1 persistence/API surface with focused store,
|
|
100
|
+
integration, and e2e coverage. The only failure-mode hardening is returning 503
|
|
101
|
+
when the store is unavailable, which is the correct liveness signal.
|
|
102
|
+
|
|
103
|
+
## Evidence pointers
|
|
104
|
+
|
|
105
|
+
- `tests/unit/apprenticeship-cycle-store.test.ts`
|
|
106
|
+
- `tests/unit/SqliteRegistry-wiring.test.ts`
|
|
107
|
+
- `tests/integration/apprenticeship-routes.test.ts`
|
|
108
|
+
- `tests/e2e/apprenticeship-lifecycle.test.ts`
|
|
109
|
+
|
|
@@ -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`
|