instar 1.3.415 → 1.3.417
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/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +25 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/monitoring/SessionRecovery.d.ts.map +1 -1
- package/dist/monitoring/SessionRecovery.js +4 -0
- package/dist/monitoring/SessionRecovery.js.map +1 -1
- package/dist/monitoring/agentWorktreeGit.d.ts.map +1 -1
- package/dist/monitoring/agentWorktreeGit.js +4 -0
- package/dist/monitoring/agentWorktreeGit.js.map +1 -1
- package/dist/scaffold/templates.js +1 -1
- package/package.json +2 -2
- package/scripts/lint-no-blocking-process-scans.js +115 -0
- package/scripts/lint-no-direct-destructive.js +3 -0
- package/src/data/builtin-manifest.json +19 -19
- package/src/scaffold/templates.ts +1 -1
- package/upgrades/1.3.416.md +42 -0
- package/upgrades/1.3.417.md +24 -0
- package/upgrades/side-effects/lint-no-blocking-process-scans.md +73 -0
- package/upgrades/side-effects/secret-retrieval-first-standard.md +24 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Side-Effects Review — lint: ban blocking process scans on the runtime hot path
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `lint-no-blocking-process-scans`
|
|
4
|
+
**Date:** `2026-06-07`
|
|
5
|
+
**Author:** `Echo`
|
|
6
|
+
**Tier:** 1 (a new CI lint + comment-only src annotations + a test; no behavior change, no API/route/config/migration)
|
|
7
|
+
**Second-pass reviewer:** `Echo (self) — Tier-1; preventive gate, no runtime behavior change`
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
|
|
11
|
+
Adds `scripts/lint-no-blocking-process-scans.js` (wired into `npm run lint`): in
|
|
12
|
+
`src/monitoring/` and `src/server/`, a SYNCHRONOUS child-process call
|
|
13
|
+
(`spawnSync`/`execSync`/`execFileSync`) whose command literal is a process-
|
|
14
|
+
enumeration tool (`ps`/`pgrep`/`lsof`/`pkill`) now fails CI. This is post-mortem
|
|
15
|
+
standard #3 for the 2026-06-07 "server temporarily down" incident (topic 21816):
|
|
16
|
+
synchronous `ps`/`lsof` scans on a cadence blocked the event loop and starved
|
|
17
|
+
`/health` under load → the supervisor restarted an alive server → the loop.
|
|
18
|
+
#972 fixed SessionWatchdog; this lint stops the class from being re-introduced.
|
|
19
|
+
|
|
20
|
+
The two existing in-dir call sites are `lsof` one-shots, allowlisted with inline
|
|
21
|
+
`// lint-allow-blocking-scan:` justifications (comment-only edits):
|
|
22
|
+
- `SessionRecovery.ts` — targeted `lsof -p <pid>` (single process, 5s timeout),
|
|
23
|
+
runs once during a session's JSONL recovery, not on a cadence.
|
|
24
|
+
- `agentWorktreeGit.ts` — full-cwd `lsof` in AgentWorktreeReaper, which ships
|
|
25
|
+
dark + dry-run by default (not on any live agent's hot path); 15s timeout;
|
|
26
|
+
async conversion noted as a follow-up.
|
|
27
|
+
|
|
28
|
+
## Decision-point inventory
|
|
29
|
+
|
|
30
|
+
- The only decision: which sync calls to fail CI on. Scoped to the documented
|
|
31
|
+
load-sensitive enumeration commands (`ps`/`pgrep`/`lsof`/`pkill`) in the two
|
|
32
|
+
runtime hot dirs. tmux/git calls are deliberately NOT covered (bounded, fast,
|
|
33
|
+
ubiquitous — converting them is a separate, bigger concern and not this
|
|
34
|
+
incident's cause).
|
|
35
|
+
|
|
36
|
+
## 1. False positives (flagging a safe call)
|
|
37
|
+
|
|
38
|
+
A genuinely one-shot, bounded sync scan is excused by an inline
|
|
39
|
+
`// lint-allow-blocking-scan: <reason>` (scanned up to 6 lines above the call to
|
|
40
|
+
allow a multi-line justification). The escape hatch requires a written reason, so
|
|
41
|
+
the decision is reviewed, not silent. Two current sites use it.
|
|
42
|
+
|
|
43
|
+
## 2. False negatives (missing a real one)
|
|
44
|
+
|
|
45
|
+
Static detection matches a string-literal command. A sync scan that passes the
|
|
46
|
+
command via a variable (e.g. `execFileSync(file, args)` in `mcpProcessReaperDeps`)
|
|
47
|
+
is not caught — accepted: the lint is a ratchet against the common, copy-pasted
|
|
48
|
+
literal form; the variable-indirection cases are pre-existing and tracked. tmux
|
|
49
|
+
is intentionally out of scope.
|
|
50
|
+
|
|
51
|
+
## 3. Level-of-abstraction fit
|
|
52
|
+
|
|
53
|
+
Correct: a CI lint in the existing `lint-no-*` family, modeled on
|
|
54
|
+
`lint-no-unfunneled-headless-launch.js`. Structure > Willpower — a future periodic
|
|
55
|
+
`spawnSync('ps')` fails the build instead of being discovered as a stall in prod.
|
|
56
|
+
|
|
57
|
+
## 4. Blast radius
|
|
58
|
+
|
|
59
|
+
CI-only. No runtime code changes (the two src edits are comments). Cannot affect a
|
|
60
|
+
running agent. Worst case of a bug in the lint = a spurious CI failure, fixed by an
|
|
61
|
+
allowlist comment or a lint tweak — never a production impact.
|
|
62
|
+
|
|
63
|
+
## 5. Rollback
|
|
64
|
+
|
|
65
|
+
Remove the script + the one `package.json` chain entry; revert the two comment
|
|
66
|
+
annotations. No state/format change.
|
|
67
|
+
|
|
68
|
+
## 6. Tests
|
|
69
|
+
|
|
70
|
+
`tests/unit/lint-no-blocking-process-scans.test.ts` (5): flags sync ps; flags
|
|
71
|
+
spawnSync pgrep + execSync lsof; honours the inline allow justification; ignores
|
|
72
|
+
comment-only mentions + async/tmux calls; the real runtime tree is clean. The lint
|
|
73
|
+
also self-validated against a synthetic violation. tsc clean.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Side-Effects Review — Secret-Retrieval-First Standard
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `secret-retrieval-first-standard`
|
|
4
|
+
**Date:** `2026-06-07`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Tier:** `1` (docs/template + idempotent migration; no runtime behavior, no deps/routes/stores)
|
|
7
|
+
**Second-pass reviewer:** `not-required (Tier-1 guidance/template change; correctness self-owned + covered by 3 unit tests)`
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
Inverts the CLAUDE.md Secret Drop "When to use" guidance from "use Secret Drop the moment you need a credential — the ONLY correct way" to **agent-retrieves-first; Secret Drop is the last resort**. Applied across all three Migration-Parity surfaces: the template (`generateClaudeMd`), the migrator inject-block (agents missing the section), and a new content-sniff patch in `migrateClaudeMd` that rewrites the harmful trigger for already-deployed agents.
|
|
11
|
+
|
|
12
|
+
Files: `src/scaffold/templates.ts` (template guidance), `src/core/PostUpdateMigrator.ts` (inject-block text + new content-sniff patch), `tests/unit/PostUpdateMigrator-secretDropHardenedRetrieve.test.ts` (+3 tests), `docs/specs/secret-retrieval-first-standard.md` (+ .eli16).
|
|
13
|
+
|
|
14
|
+
## Decision-point inventory
|
|
15
|
+
- **Runtime behavior change?** None. This is agent-facing guidance text only — no code path, route, store, config, or scheduler is touched. Secret Drop itself (endpoints, retrieve script, durability) is unchanged.
|
|
16
|
+
- **New dependency / state / route / config?** None → trips none of the SqliteRegistry-wiring / feature-delivery-completeness / docs-coverage(new-class) guard classes.
|
|
17
|
+
- **Migration parity?** Satisfied on all three surfaces (template for new inits; inject-block for agents lacking the section; content-sniff patch for agents with the old section). The content-sniff patch is **idempotent** — it anchors on the stable old phrase `It is the ONLY correct way to collect a secret.` and skips once `AGENT-RETRIEVES-FIRST` / the new wording is present. Unit-tested (rewrite / idempotent / fresh-inject).
|
|
18
|
+
- **Silent fallbacks?** None added. No new `try/catch`; pure string edits + one guarded `content.replace`.
|
|
19
|
+
- **Shadow-capability slicer (AGENTS.md for Codex/Gemini)?** Inherits the corrected CLAUDE.md text automatically (the slicer copies sections from CLAUDE.md) — no separate edit needed; this is a positive side-effect (shadows stop carrying the wrong default too).
|
|
20
|
+
- **Secret-handling safety baked into the new guidance:** explicitly tells agents to extract only the needed var, never print the value, and delete multi-secret temp files immediately — codifying the safe-retrieval discipline I followed pulling the value from `the-portal` env.
|
|
21
|
+
- **Rollback?** Trivial — revert the three edits; guidance returns to prior wording, no state to unwind.
|
|
22
|
+
|
|
23
|
+
## Why ship
|
|
24
|
+
A wrong default in the template propagates to every agent (and every shadow). Justin flagged it as a UX violation (2026-06-07) and directed the standards amendment. Fixing it in the artifact agents read — not by per-agent willpower — is the Structure > Willpower path.
|