agent-bios 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/claude/CLAUDE.md +8 -8
- package/claude/guides/cli-multi-model-workflow.md +6 -1
- package/claude/guides/coding-staged-workflow.md +12 -0
- package/claude/guides/learning-flow.md +4 -1
- package/claude/guides/llm-capability-boundary-patterns.md +8 -0
- package/claude/guides/review-request.md +13 -0
- package/claude/guides/session-distill-workflow.md +21 -9
- package/claude/guides/tooling-gotchas.md +181 -14
- package/claude/guides/verification-discipline.md +71 -3
- package/claude/hooks/tooling-gotchas-hook.py +50 -0
- package/codex/AGENTS.md +8 -8
- package/codex/guides/cli-multi-model-workflow.md +6 -1
- package/codex/guides/coding-staged-workflow.md +12 -0
- package/codex/guides/learning-flow.md +4 -1
- package/codex/guides/llm-capability-boundary-patterns.md +8 -0
- package/codex/guides/review-request.md +13 -0
- package/codex/guides/session-distill-workflow.md +21 -9
- package/codex/guides/tooling-gotchas.md +181 -14
- package/codex/guides/verification-discipline.md +71 -3
- package/install.sh +87 -5
- package/launch/agent-launch.zsh +109 -6
- package/learn/collect-learning.py +593 -62
- package/learn/redact.py +2 -1
- package/package.json +2 -2
- package/provenance.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Two layers:
|
|
|
35
35
|
| `claude/guides/*.md`, `codex/guides/*.md` | scoped guides (en) — installed |
|
|
36
36
|
| `codex/agents/*.toml` | Codex custom subagent role templates — installed |
|
|
37
37
|
| `ko/**` | Korean mirror of every doc above + this README + DEPENDENCIES (reference only) |
|
|
38
|
-
| `launch/` | launch profile, preflight TUI, zero-argument shell interception, the managed Textual venv, and the prompting-target check that guards the profile's model bindings |
|
|
38
|
+
| `launch/` | launch profile, preflight TUI, zero-argument shell interception (reasserted at `preexec`: a terminal that redefines `claude` at its prompt hook is redefined back before the command runs — one that redefines it in a later `preexec`, or through an alias for the command already parsed, is recorded, not fought), the managed Textual venv, and the prompting-target check that guards the profile's model bindings |
|
|
39
39
|
| `compose/` | corpus classification and per-selection assembly — domain manifest and its gate, assembler, package identity, hook registration, activation canary, deployed-corpus state |
|
|
40
40
|
| `learn/` | the collection loop — capture, record schema and its validator, curation intake, promotion manifest, redistribution, and the secret-redaction floor |
|
|
41
41
|
| `session-distill/` | the heavy curator pipeline that mines many sessions into corpus-grade items |
|
|
@@ -111,7 +111,7 @@ Add `$CODEX_DIR/bin` to `PATH` or invoke the wrappers by absolute path. `codex-h
|
|
|
111
111
|
|
|
112
112
|
## Adopting elsewhere
|
|
113
113
|
|
|
114
|
-
Keep the rule layers. Swap checklist:
|
|
114
|
+
Keep the rule layers. Swap checklist: every line carrying the `(private)` private-binding marker — today the global file's response-language preference; guides' `Environment Binding` author examples adopt the marker as they are touched — plus the "설계" design-trigger word in the global file and the skill/MCP names inventoried in `DEPENDENCIES.md` (the `spreadsheet-processing` skill, the review MCP). The other direction is enforced, not asked: `gates/check-hygiene.py` refuses org identifiers anywhere in the shipped distribution and author identifiers outside marked lines or per-reason exemptions. Then re-measure `Evidence Base` numbers in your environment before tuning.
|
|
115
115
|
|
|
116
116
|
## Scope
|
|
117
117
|
|
package/claude/CLAUDE.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Global Preferences
|
|
4
4
|
|
|
5
|
-
- Prefer concise Korean responses with polite speech unless the user asks otherwise.
|
|
5
|
+
- Prefer concise Korean responses with polite speech unless the user asks otherwise. (private)
|
|
6
6
|
- Keep file changes within the requested scope.
|
|
7
7
|
|
|
8
8
|
## Problem Solving
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
- First identify the goal, scope, ambiguities, and likely completion condition.
|
|
11
11
|
- Resolve ambiguity from context when safe; ask only when ambiguity blocks progress or creates risky outcomes.
|
|
12
12
|
- For simple requests, choose the most direct low-risk method and proceed.
|
|
13
|
-
- For non-trivial requests, compare 2-4 methods by goal fit, time, cost, risk, benefit, and "done when".
|
|
13
|
+
- For non-trivial requests, compare 2-4 methods by goal fit, time, cost, risk, benefit, and "done when", and portability — take a host-, model-, or tool-specific mechanism (hook, skill, host-owned directory) only after a portable route is shown absent and its per-host cost is judged worth it.
|
|
14
14
|
- Mark one default method. If the user is silent and the default is safe, proceed with it.
|
|
15
15
|
- Execute the chosen method accurately and stay within scope.
|
|
16
16
|
- Return to understanding if a discovery breaks the user's premise.
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
## Decision Framing
|
|
23
23
|
|
|
24
|
-
- Ask decision questions in outcome terms, not jargon terms.
|
|
24
|
+
- Ask decision questions in outcome terms, not jargon terms: before ending a turn on a decision request, check that it gives the situation in one plain sentence, what changes for the user under each option, and a default — and where a structured question channel exists, route the ask through it so its fields force that shape.
|
|
25
25
|
- When the user may not know the domain, explain choices by resulting behavior, tradeoffs, time, cost, risk, reversibility, and recommended default.
|
|
26
26
|
- Present 2-4 meaningful options. Ask about implementation details only when they directly affect the decision.
|
|
27
27
|
- For each option, state what changes for the user or product, what it costs, what risk it carries, and when it is the right choice.
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
- Ask for the user's goal or constraint when that determines the answer; otherwise choose the safest default and proceed.
|
|
30
30
|
- Evaluate user suggestions for goal fit, risk, complexity, and verification before turning them into implementation plans; if a suggestion does not fit the user's goal, say so clearly and recommend a better path.
|
|
31
31
|
- Distinguish implementation feasibility from recommendation.
|
|
32
|
-
- Do not default to a restrictive lens (security, masking, capability limits) when the system's purpose is sharing or utilization; confirm the purpose framing first, and restrict only on concrete, named risk.
|
|
32
|
+
- Do not default to a restrictive lens (security, masking, capability limits) when the system's purpose is sharing or utilization; confirm the purpose framing first, and restrict only on concrete, named risk — and size every control (gate, cap, rule, review lens, success criterion, clarifying question) to that risk: a target is a direction, not an absolute, and prefer a warning plus a recovery path over a prohibition.
|
|
33
33
|
- Treat user suggestions, inherited premises, prior diagnoses, handoff and design claims, reviewer findings, and your own earlier conclusions as hypotheses, not facts; re-derive each load-bearing claim from real code or data before building on it, and record a dated correction in the source doc or memory when a finding overturns it.
|
|
34
34
|
|
|
35
35
|
## LLM And Capability Boundary
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
## Concept Economy
|
|
54
54
|
|
|
55
55
|
- When adding, changing, renaming, splitting, or exposing anything lasting or shared — a feature, entity, type, field, config key, CLI flag, enum value, failure kind, artifact, or documentation term — read and use `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/concept-economy.md` as a scoped extension of this section.
|
|
56
|
-
- Before fixing a review finding or test failure, classify the fix as reducing, preserving, or increasing the active concept surface.
|
|
56
|
+
- Before fixing a review finding or test failure, name its cause — a finding is a symptom — then classify the fix as reducing, preserving, or increasing the active concept surface, and fix the cause completely now: a scope-minimal patch that leaves the cause in place is not a fix.
|
|
57
57
|
|
|
58
58
|
## Coding Guidelines
|
|
59
59
|
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
- For development work, read and use `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/coding-staged-workflow.md` as a scoped extension of these Coding Guidelines — a change too narrow to need it is what its lightweight path decides, not a reason to skip the read.
|
|
62
62
|
- For mock, fixture, fake, stub, simulated-provider, or test-realization design, read and use `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/mock-realization-boundary.md` as a scoped extension of these Coding Guidelines.
|
|
63
63
|
- Own the full lifecycle of what you create — spawned processes and handles through teardown, artifacts out of tool-managed temp locations into a durable home — and keep differently-owned state separate: never colocate deploy-managed and user-owned data in one overwrite-managed file.
|
|
64
|
-
- Land risky or behavior-changing work behind a default-off path that preserves current behavior when off (proven by diff) and is enabled by an explicit opt-in, so the change stays reversible and the on/off difference is isolated. When a request would weaken a security or authority posture — removing or loosening an authentication/authorization check or access scope, or lowering a protective value such as session/token lifetime, password/crypto strength, rate limit, lockout threshold, or audit retention — treat it as a decision, not a rote edit, even when it is a one-line change and nothing in the code labels the value as security-relevant: state the consequence and at least one safer path to the real goal, and do not apply the weakening in the same turn — proceed only after the user confirms they accept the tradeoff.
|
|
64
|
+
- Land risky or behavior-changing work behind a default-off path that preserves current behavior when off (proven by diff) and is enabled by an explicit opt-in, so the change stays reversible and the on/off difference is isolated — the switch lands a fix reversibly and never substitutes for one. When a request would weaken a security or authority posture — removing or loosening an authentication/authorization check or access scope, or lowering a protective value such as session/token lifetime, password/crypto strength, rate limit, lockout threshold, or audit retention — treat it as a decision, not a rote edit, even when it is a one-line change and nothing in the code labels the value as security-relevant: state the consequence and at least one safer path to the real goal, and do not apply the weakening in the same turn — proceed only after the user confirms they accept the tradeoff.
|
|
65
65
|
|
|
66
66
|
## Verification Discipline
|
|
67
67
|
|
|
@@ -77,14 +77,14 @@
|
|
|
77
77
|
- For concrete shell/CLI traps — pipe exit codes, output rendering, git range/pull semantics, config and managed-service pitfalls — read and use `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/tooling-gotchas.md` as a scoped extension of this section.
|
|
78
78
|
- Ambient state — the active shell, cloud CLI project/context, command-name resolution, 'latest'-style pointers, version-bearing paths — drifts silently; where an outcome depends on it, pin it explicitly (a pinned interpreter, --project/--context flags, exact handles, resolved paths) instead of trusting the environment.
|
|
79
79
|
- Before relying on any model id, tool flag, API capability, dependency version, or runtime constraint, confirm it empirically against the live or installed artifact (a minimal probe, the binary's registered options, the installed package version) rather than docs, memory, or a version string.
|
|
80
|
-
- Scope destructive actions (kill, rm, force-push, reset --hard) to targets you own,
|
|
80
|
+
- Scope destructive actions (kill, rm, force-push, reset --hard) to targets you own, by PID, path, or ancestry — never a broad command-line substring or blanket match — and diagnose actual state before any irreversible git, remote, or process operation; snapshot the last good state before any in-place resume or overwrite of a completed run, and gate irreversible identity-tied actions (revoke, delete, grant, consent, account-bound creation) on a live identity check — never auto-open a browser for a non-default identity (hand the operator the URL).
|
|
81
81
|
- Never accept secrets through transcript- or history-logged channels.
|
|
82
82
|
- When a secret must be supplied, provide a gitignored env slot, read the value only from the environment, verify its presence and format without echoing it, and advise rotating anything already pasted; assume a resource-creating call may echo the secret back in its success output — suppress or discard the response body, and treat an echoed secret as pasted (rotate).
|
|
83
83
|
- Treat a coarse runtime signal — a failure label, a `ps`/process-inspection result, idle CPU with no output — as a hypothesis, and confirm the cause against the authoritative low-level evidence the mechanism emits before attributing blame or intervening: read the raw provider/skill log payload (e.g. `input_tokens:0` proves a pre-dispatch rejection that exonerates your content and your change), and confirm a config/env toggle reached a subprocess via a cheap artifact the gated branch emits rather than an unreliable `ps` env read. A multi-minute LLM or subprocess call at ~0% CPU with an output gap is the normal signature of I/O wait, not a hang — check process state and the call trace's in-flight duration before acting, so you do not abort healthy long-running work.
|
|
84
84
|
|
|
85
85
|
## Multi-Model Workflow
|
|
86
86
|
|
|
87
|
-
- Standing spawn policy: check the spawn gates at every work-unit boundary — judgment latitude applies inside a gate, never to whether the gates are checked. Independence: verifying or reviewing your own work always spawns. Parallelism: two or more independent items spawn in parallel — SWEEP when each item applies one explicit rule and returns ambiguity as an exception, else WORKHORSE. Residual context: work whose log dwarfs the conclusion the main needs spawns with a bounded report contract. Escalation: an irreversible or authority-changing action ahead, two failed attempts, or two persisting design alternatives spawns a bounded FRONTIER judgment with a blind packet (evidence, constraints, rubric, neutral alternatives — never your draft conclusion) and a pre-noted change condition. Specifiability/de-minimis: work needing your live context, or whose verification would repeat the reasoning, or whose packet outweighs the work, stays inline.
|
|
87
|
+
- Standing spawn policy: check the spawn gates at every work-unit boundary — judgment latitude applies inside a gate, never to whether the gates are checked. Independence: verifying or reviewing your own work always spawns, and you raise it yourself — before presenting a load-bearing conclusion or taking an irreversible step, propose the cross-check unprompted; the user should never have to ask for it. Parallelism: two or more independent items spawn in parallel — SWEEP when each item applies one explicit rule and returns ambiguity as an exception, else WORKHORSE. Residual context: work whose log dwarfs the conclusion the main needs spawns with a bounded report contract. Escalation: an irreversible or authority-changing action ahead, two failed attempts, or two persisting design alternatives spawns a bounded FRONTIER judgment with a blind packet (evidence, constraints, rubric, neutral alternatives — never your draft conclusion) and a pre-noted change condition. Specifiability/de-minimis: work needing your live context, or whose verification would repeat the reasoning, or whose packet outweighs the work, stays inline.
|
|
88
88
|
- Down-spawns carry a machine-checkable done-when on decision-complete work with staged output (no external irreversible actions) and briefing-plus-verifying clearly cheaper than doing. Record one line per gate decision — `SpawnGate: <gate> <tier> spawn|inline — <why>` — and for FRONTIER record the disposition afterward (what changed, or why nothing did). A launch contract's `Delegation=off` lifts the spawn obligation, not the records; explicit user no-fan-out always wins.
|
|
89
89
|
- For work spanning multiple models or CLI agents, context resets and handoffs, unattended LLM batches (including orchestrated subagent fleets), or parallel worktree branches, read and use `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/cli-multi-model-workflow.md` as a scoped extension of this section.
|
|
90
90
|
- For composing a prompt, packet, or tool description aimed at a specific model family — including cross-family review dispatch, porting a prompt written for an older model, or choosing a reasoning-effort level for a model family — read and use `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/gpt-prompting.md` for gpt-family targets and `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/claude-prompting.md` for claude-family targets as scoped extensions of this section.
|
|
@@ -106,7 +106,7 @@ Instruction/config reach is per invocation. A rule in AGENTS.md cannot bind a he
|
|
|
106
106
|
- Run deterministic gates before LLM review. Funnel SWEEP finders → WORKHORSE judgments → FRONTIER triage/verdicts.
|
|
107
107
|
- On family collapse, record the downgrade and label clean verdicts PROPOSED until diversity is restored.
|
|
108
108
|
- A silent/dead lens is incomplete, never clean. Confirm liveness from usage/error/report evidence; rerun, swap provider, or report PROPOSED.
|
|
109
|
-
- Kind labels do not guarantee distinct backends: wrappers and rate-limit fallbacks can silently route two "different-kind" verifiers to the same model/provider. Before trusting diversity on a high-stakes verdict, confirm each verifier's actual backing model from live process or usage evidence; on collapse, treat the pair as one kind and label PROPOSED.
|
|
109
|
+
- Kind labels do not guarantee distinct backends: wrappers and rate-limit fallbacks can silently route two "different-kind" verifiers to the same model/provider. Before trusting diversity on a high-stakes verdict, confirm each verifier's actual backing model from live process or usage evidence; on collapse, treat the pair as one kind and label PROPOSED. Runners recording what ran need the same read: identity taken from the target at execution time, never a runner-side literal, and asserted equal to what was requested — fallback seats pass existence checks.
|
|
110
110
|
|
|
111
111
|
### Review Independence
|
|
112
112
|
|
|
@@ -124,6 +124,7 @@ How much independence a review actually bought, as an ordinal grade per reviewer
|
|
|
124
124
|
- The floor still requires **at least two distinct perspectives**; one pass on the main's own seat is self-review with extra steps.
|
|
125
125
|
- Multiple ready methods are **coverage, not diversity**. Distinct labels do not prove the perspectives differed.
|
|
126
126
|
- **Achieved is not available.** What can be projected before a review runs is `projected`; a clean verdict without a receipt evidencing a fresh dispatch, the declared packet, a non-empty result and the exact seat is `PROPOSED`, never ACHIEVED. A model echo is not a receipt.
|
|
127
|
+
- **Evidence access is its own axis.** When every reviewer saw only the blind packet, convergence — even across providers — is evidence about the packet's framing, omissions included. Before adopting a converged verdict resting on a code seat, a measured fact, or a constraint list, route one seat with live read access to falsify those facts: a lone dissent citing a real constraint outweighs a blind majority, and the missing fact returns to the packet. It sits beside the ladder, not on it.
|
|
127
128
|
|
|
128
129
|
## Dual-Provider Design Drafts
|
|
129
130
|
|
|
@@ -136,11 +137,14 @@ How much independence a review actually bought, as an ordinal grade per reviewer
|
|
|
136
137
|
- The parent owns per-item completion and a **code-level circuit breaker**. For dispatchers you do not control, verify equivalent protection or attend the run.
|
|
137
138
|
- Default breaker: halt after 3 consecutive cross-item provider limit/auth/transport failures after bounded backoff. Persist undone items and alert or swap provider.
|
|
138
139
|
- Item-specific failures are poison items: cap at 2–3 attempts, then dead-letter them as complete-with-failure. Resume only unfinished/invalid items; whole-batch reruns require cheap idempotence.
|
|
140
|
+
- An enumeration run is done only when its collected count is asserted against the source's own reported total for the same filter. Classify retriable failures by class — any server-side transient — rather than an enumerated code list, since an omitted code drops items silently; persist which batches failed and reconcile them before declaring completion; and treat a mismatch, or a total from a differently scoped population, as a defect rather than a footnote. A declared partial or sampled scope is outside this.
|
|
139
141
|
- Persist per-item outcome, token, and cost records for recalibration.
|
|
142
|
+
- Before releasing a metered batch past its first item, use that item to probe the batch machinery, not the item logic: run it end to end through the real runner to its side effect, then confirm every value the later analysis depends on — treatment knob, run identity, cost — reached the persisted record through the expected channel. On the first failures read raw run logs, not the runner's status classifier, which infers causes from missing outputs. A cheap idempotent batch needs no gate.
|
|
140
143
|
|
|
141
144
|
## Halt And Resume
|
|
142
145
|
|
|
143
146
|
- Resume-first from artifacts that parse, pass schema, and match their recorded source/config/HEAD fingerprint; unverifiable means invalid.
|
|
147
|
+
- A cache-hit or fingerprint predicate must cover every value that shapes the artifact's content — the upstream input's content identity, caps, templates, model ids, config — never existence, mtime, or size alone; when adding a new output-shaping value, inspect the key's pre-image in the same change and assert the key moves when the value moves. Before re-running because an upstream input changed, invalidate intermediates whose predicate omits that input's identity: a regenerate over existence-keyed caches re-derives from the old input.
|
|
144
148
|
- Resubmit one invalid unit unless failures are broadly correlated, which is structural and halts the run.
|
|
145
149
|
- Treat halt→continue as normal operation.
|
|
146
150
|
- Treat tool-managed temp/cache output locations as ephemeral — they are garbage-collected on the tool's own schedule. Copy any artifact a pending or handed-off decision depends on into a project-owned durable path before relying on it later.
|
|
@@ -150,6 +154,7 @@ How much independence a review actually bought, as an ordinal grade per reviewer
|
|
|
150
154
|
|
|
151
155
|
- Sessions bind to their starting directory. Use the CLI's native relocation/resume mechanism; never copy transcript files.
|
|
152
156
|
- For a new worktree, relocate natively or write a handoff and start fresh. Re-integrate branches serially and re-verify after each merge.
|
|
157
|
+
- A conflict-free merge with a green build is evidence about text, not placement. When the base side restructured the surrounding code — regrouped sections, split modules, new per-variant containers — locate each merged addition in the new structure and confirm its scope still matches its container's: a global setting must not sit inside a variant-specific container, and no duplicate or orphaned copy may remain. A merge onto an unchanged layout needs only the ordinary green-state check.
|
|
153
158
|
- Mark superseded worktrees/handoffs dead so later resume cannot select them.
|
|
154
159
|
- After resume/clear/relocation, verify pwd, branch, and HEAD against the pinned handoff before acting.
|
|
155
160
|
- Attribute a parallel session's action (commit, branch, resource) by execution evidence in that session's own transcript, never by token mentions — shared handoff/memory files inject the same tokens into every session's context.
|
|
@@ -75,6 +75,18 @@ patching downstream: compensating code keeps accumulating around bad inputs, and
|
|
|
75
75
|
another instance of the same defect. The first says go upstream to where the value is produced.
|
|
76
76
|
The second says the instances are a class — single-source the value and fix the class, because
|
|
77
77
|
patching them one at a time is a queue that refills.
|
|
78
|
+
**Supplying a missing shared dependency wakes every consumer, not just the one you are fixing.** When
|
|
79
|
+
a repair supplies a value many paths read and that was absent — a secret, a packaged file —
|
|
80
|
+
enumerate those consumers and say what each starts doing: metered calls, external writes,
|
|
81
|
+
user-visible output. Where that onset exceeds the feature under repair, hand the list to the owner
|
|
82
|
+
as a decision, not a line in the fix. Consumers that are all read-only and free need no gate.
|
|
83
|
+
|
|
84
|
+
**Measure a flip before you design its activation.** When a version bump, default change, or
|
|
85
|
+
severity re-mapping is coming, flip it, run the full suite, classify every failure (cascade,
|
|
86
|
+
pinned control, true detection, real regression), and restore — that count is the activation's
|
|
87
|
+
blast radius. Re-mapping a level obliges enumerating every reader of that field, since one level
|
|
88
|
+
commonly gates shipping, repair, retry, and display at once. A deferred defect is pinned as a
|
|
89
|
+
strict expected failure, never a silent pass.
|
|
78
90
|
|
|
79
91
|
## Review Loop
|
|
80
92
|
|
|
@@ -103,4 +103,7 @@ payload — do not work around the validation.
|
|
|
103
103
|
- Single-session capture only; cross-session mining is `distill!` (curator).
|
|
104
104
|
- Mechanization (hook/gate/enforcement) is deferred to curation — record intent, don't build it.
|
|
105
105
|
- Type-G principle manufacture is curator-only.
|
|
106
|
-
- Transport (upload to the org)
|
|
106
|
+
- Transport (upload to the org) is best-effort after the local write: it runs only
|
|
107
|
+
when the `~/.config/agent-bios/{ingest-url,token}` slot is set, which is the
|
|
108
|
+
only source there is. A default install sets nothing, so nothing leaves the
|
|
109
|
+
machine; an org fills the slot through its own wrapper.
|
|
@@ -314,6 +314,14 @@ Retries are safe for pure generation and validation. They are not automatically
|
|
|
314
314
|
safe for external side effects. Use idempotency keys, locks, duplicate detection,
|
|
315
315
|
or compensation plans where needed.
|
|
316
316
|
|
|
317
|
+
A stage that can re-run on the same record must not read the field it writes.
|
|
318
|
+
On a re-run (reclassification, backfill, retry) an input field that is also
|
|
319
|
+
its output feeds the model its prior answer, and the value drifts from the
|
|
320
|
+
source silently. Keep the captured original immutable, write derived values to
|
|
321
|
+
their own field, and treat `original ?? current` as migration, not design.
|
|
322
|
+
Audit its siblings: one harmless only because its selection rule skips
|
|
323
|
+
overwritten rows is a latent instance.
|
|
324
|
+
|
|
317
325
|
## Single Source Of Truth And Schema Evolution
|
|
318
326
|
|
|
319
327
|
Hybrid enforcement creates drift risk. A single constraint can appear in prompt
|
|
@@ -122,6 +122,12 @@ design; do not treat missing implementation as a defect." A session given exactl
|
|
|
122
122
|
that instruction returned zero findings and proved it had looked, anchored on
|
|
123
123
|
both sides of the comparison. A session not given it filed unimplemented code as
|
|
124
124
|
blockers, and the user caught it manually.
|
|
125
|
+
The target also has a revision. Name the commit or content hash the packet
|
|
126
|
+
was dispatched on, and hold the artifact still until every reviewer on
|
|
127
|
+
that revision has returned. When a fix must land while a lens is still in
|
|
128
|
+
flight, map the returned findings against the pinned revision before
|
|
129
|
+
counting them: a finding whose anchor text no longer exists is stale,
|
|
130
|
+
closed by that mapping rather than re-fixed, and never tallied as open.
|
|
125
131
|
|
|
126
132
|
## Bundle the consumer, not just the artifact
|
|
127
133
|
|
|
@@ -226,6 +232,13 @@ Two consequences for anyone consuming a review:
|
|
|
226
232
|
count was scoped to the material section, at which point 16% of the same
|
|
227
233
|
findings turned out to have reached the reader explicitly flagged
|
|
228
234
|
non-material. Read the verdict field, not the mention.
|
|
235
|
+
- Count the emitted item list against every total the harness reports —
|
|
236
|
+
findings count, verdict tally, per-item decision log — before triaging.
|
|
237
|
+
Zero findings is only the extreme case: any shortfall means items were
|
|
238
|
+
dropped in aggregation, and the dropped set is not random, since a merge
|
|
239
|
+
or filter tends to lose a whole class. Recover the difference from the
|
|
240
|
+
raw per-item record and triage the union; with no raw record the
|
|
241
|
+
deliverable is incomplete, not clean.
|
|
229
242
|
|
|
230
243
|
## Trust an empty result only when it cites what it checked
|
|
231
244
|
|
|
@@ -49,15 +49,27 @@ Run in order; each stage reads the previous stage's `out/`:
|
|
|
49
49
|
Claude sidechain/sdk-cli/agentId).
|
|
50
50
|
2. `digest.py` — one secret-redacted digest per session with deterministic
|
|
51
51
|
6-criteria signals. Screen ALL digests; triage orders, never drops.
|
|
52
|
-
3.
|
|
53
|
-
|
|
54
|
-
`
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
3. `batch.py` — the baseline blob (`claude/CLAUDE.md` + every guide, the
|
|
53
|
+
repo's canonical corpus) and per-provider batches; writes
|
|
54
|
+
`out/batch_index.json`, which the screeners take as their `args`.
|
|
55
|
+
4. Provider-affine screening against that baseline: `screen-claude.js`
|
|
56
|
+
(Claude sessions; a Workflow script — pass the index as `args`, one
|
|
57
|
+
WORKHORSE screener per batch) and `screen-codex.py` (Codex sessions;
|
|
58
|
+
one hermetic read-only `codex exec` per batch, packet on stdin). Novelty
|
|
59
|
+
is judged against real baseline text, not memory. Then `collect.py`
|
|
60
|
+
unions the two outputs into `out/candidates-all.json` and fails when a
|
|
61
|
+
provider's screened set is smaller than its batch.
|
|
62
|
+
5. `consolidate.js` (Workflow; `args` = baseline, candidates path, count,
|
|
63
|
+
and the ledger's `{id, lesson}` list) — dedup + independent novelty
|
|
64
|
+
verification, then a match pass naming which survivor recurs an
|
|
65
|
+
existing ledger entry. Rank by strength (recurrence × materiality),
|
|
66
|
+
never by self-reported confidence. Save its return value as
|
|
67
|
+
`out/consolidated.json`.
|
|
68
|
+
6. `bundle_final.py` — tiered bundle. `merge-ledger.py --window-end <date>`
|
|
69
|
+
(dry-run; `--apply` writes) merges survivors into `ledger.json`: a
|
|
70
|
+
recurrence gains the window's sessions under `recurrence`, a new lesson
|
|
71
|
+
becomes a `candidate` entry — so recurrence accumulates across windows
|
|
72
|
+
and incubated items promote when they re-occur.
|
|
61
73
|
|
|
62
74
|
## Stage 2 — Review with the user
|
|
63
75
|
|
|
@@ -40,28 +40,47 @@ depends on it, pin it explicitly instead of trusting the environment.
|
|
|
40
40
|
shells resolve functions/aliases first, programmatic spawns resolve raw
|
|
41
41
|
PATH, and a same-named package can shadow a system tool with silent empty
|
|
42
42
|
output. Before trusting a result across execution contexts, confirm the
|
|
43
|
-
resolved target (`type -a`, absolute path).
|
|
43
|
+
resolved target (`type -a`, absolute path). A missing prefix wrapper fails
|
|
44
|
+
the same silent way — GNU `timeout` is routinely absent on BSD-derived
|
|
45
|
+
systems — so confirm the wrapper too.
|
|
44
46
|
- **Cloud CLI context**: gcloud/aws/kubectl/terraform carry mutable ambient
|
|
45
47
|
context (active project, profile, cluster) that drifts between sessions.
|
|
46
48
|
Before the first environment-affecting command — or right after a resume —
|
|
47
49
|
verify it against intent, then pin the target explicitly on every command
|
|
48
50
|
(`--project`, `--profile`, `--context`) rather than fixing the global
|
|
49
|
-
default once.
|
|
51
|
+
default once. A forge CLI (`gh`/`glab`) reads its repository from the
|
|
52
|
+
checkout's remotes too: with a fork plus an upstream it can answer for the
|
|
53
|
+
wrong repo, so pass `--repo` wherever the answer feeds a decision.
|
|
50
54
|
- **Installed is not running**: a live process keeps its old code until
|
|
51
55
|
restarted or reloaded. When confirming an update, config change, or
|
|
52
56
|
dependency bump took effect, don't stop at the on-disk artifact — confirm
|
|
53
57
|
the running process's actual version/behavior or force a restart.
|
|
58
|
+
- **Producer newer than consumer**: when a deployed binary validates an
|
|
59
|
+
artifact you produce (a signed config or manifest), produce and verify it
|
|
60
|
+
with the producer tooling checked out at the exact commit that binary was
|
|
61
|
+
built from — a local verify with current-tree tooling proves only that
|
|
62
|
+
newer tooling accepts it. Confirm the consumer's build commit from image
|
|
63
|
+
provenance, not the current branch; any version mismatch is a release
|
|
64
|
+
blocker. A consumer rebuilt from the same commit needs only ordinary
|
|
65
|
+
verification.
|
|
66
|
+
- **A dev-labelled datastore target is a claim**: a localhost URL or
|
|
67
|
+
exported override is no evidence of a non-production target — a local port
|
|
68
|
+
can proxy into the only real instance, and a tool's config loader can
|
|
69
|
+
re-load a dotenv over your exported value. Before the first writing
|
|
70
|
+
command (migration, seeder), print what the connection reaches from inside
|
|
71
|
+
the tool's own path and assert it is the intended target; where the loader
|
|
72
|
+
is untrustworthy, extract the DDL and apply it yourself.
|
|
54
73
|
|
|
55
74
|
## Shell execution traps
|
|
56
75
|
|
|
57
76
|
- **Pipe exit masking**: `$?` after a pipeline reflects only the last stage;
|
|
58
|
-
a real failure
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
77
|
+
a real failure upstream is masked by a successful `tail`/`grep`/`jq`,
|
|
78
|
+
reading green. Capture the tested stage's own status: run it unpiped,
|
|
79
|
+
store `$?` immediately, or use `set -o pipefail`/`PIPESTATUS` — a
|
|
80
|
+
per-command choice, since pipefail breaks early-exit consumers (`cmd |
|
|
81
|
+
head -1`, `grep -q` on a long producer → SIGPIPE 141). The
|
|
82
|
+
final-stage-assertion exemption (`cmd | grep -q pattern`) holds only
|
|
83
|
+
without pipefail; under it, capture output and check its status first.
|
|
65
84
|
- **Passthrough arguments in a CLI you author**: an option meant to carry
|
|
66
85
|
another command's own flags cannot use a greedy-but-dash-stopping arity —
|
|
67
86
|
Python's `nargs="+"` ends at the first token starting with `-`, so the
|
|
@@ -71,6 +90,13 @@ depends on it, pin it explicitly instead of trusting the environment.
|
|
|
71
90
|
second, separate trap: argparse consumes it as its own positional marker
|
|
72
91
|
before the remainder sees it, so the form every caller reaches for first is
|
|
73
92
|
the one that breaks — normalize it out of `argv` before parsing.
|
|
93
|
+
- **CLI flag probes that execute**: probe a CLI only with invocations that
|
|
94
|
+
cannot do real work — a help form, or the candidate flag paired with a
|
|
95
|
+
control flag that forbids execution (dry-run, an invalid required
|
|
96
|
+
argument). Never run a subcommand bare, and assume a value after a flag
|
|
97
|
+
may be read as positional input: a boolean flag does not consume it, so it
|
|
98
|
+
falls through and runs. Tell a boolean from an unregistered flag by the
|
|
99
|
+
parser's error, not by the run succeeding.
|
|
74
100
|
- **Reserved parameter names**: assigning to reserved shell names (`UID`,
|
|
75
101
|
`EUID`, `GID`, `PPID`) can invoke the bound system behavior instead of
|
|
76
102
|
storing a value — silently changing process credentials mid-script. Use
|
|
@@ -105,6 +131,14 @@ depends on it, pin it explicitly instead of trusting the environment.
|
|
|
105
131
|
timestamp resolution (mutation testing). Clear the cache or run no-cache
|
|
106
132
|
per iteration, and re-confirm the unmutated baseline still passes after a
|
|
107
133
|
cache clear.
|
|
134
|
+
- **Transport limits are measured on the wire payload, in the provider's
|
|
135
|
+
unit**: take the unit and value from the provider's rejection or a live
|
|
136
|
+
probe, never from docs or a variable's name, and measure the serialized
|
|
137
|
+
payload the consumer receives — after encoding and wrappers — not the
|
|
138
|
+
object you assembled. A character count against a byte limit undercounts
|
|
139
|
+
multibyte text, hiding while inputs are ASCII; an item count bounds no
|
|
140
|
+
size. Enforce at one dispatch chokepoint, deriving every budget from that
|
|
141
|
+
constant.
|
|
108
142
|
|
|
109
143
|
## Git operations
|
|
110
144
|
|
|
@@ -131,12 +165,31 @@ depends on it, pin it explicitly instead of trusting the environment.
|
|
|
131
165
|
restore from that. The same asymmetry makes the restore step fragile: if the
|
|
132
166
|
probe can time out or abort, the restore must not be the next command in the
|
|
133
167
|
same invocation — put it where a failure cannot skip it.
|
|
168
|
+
- **An ignore rule can swallow a durable record**: before treating a path as
|
|
169
|
+
durable — a new ledger, a cited authority — run `git check-ignore -v
|
|
170
|
+
<path>` and `git ls-files --error-unmatch <path>`. Broad runtime-state
|
|
171
|
+
patterns (`*.jsonl`, `runs/`, `out/`) absorb a new file, and a tracked
|
|
172
|
+
file pointing at an ignored path is an authority that exists in one
|
|
173
|
+
checkout only. Fix with a negation rule proven by a sibling that stays
|
|
174
|
+
ignored; genuinely ephemeral output stays ignored.
|
|
134
175
|
- **Dirty-worktree pulls**: before pulling into a worktree with
|
|
135
176
|
staged/unstaged/untracked changes, fetch first and compare incoming paths
|
|
136
177
|
against every dirty path; on overlap or a non-fast-forward, stop and clear
|
|
137
178
|
the conflict risk (stash, commit, ask). Otherwise pull `--ff-only`, confirm
|
|
138
179
|
dirty changes survived, and regenerate any local derived artifacts whose
|
|
139
180
|
inputs were updated.
|
|
181
|
+
- **A split series is proven commit by commit**: order them by dependency
|
|
182
|
+
and check each out into a throwaway worktree to run the build, tests, and
|
|
183
|
+
gates before pushing. Green only at the tip hides a broken bisect point
|
|
184
|
+
and a commit that cannot be reverted alone — usually a rename or shared
|
|
185
|
+
hunk in the wrong commit. If a handoff cites the branch's hashes, merge
|
|
186
|
+
with a merge commit: squash and rebase rewrite every hash.
|
|
187
|
+
- **A shared tree holds other operators' work**: a commit you did not make, a file the
|
|
188
|
+
editor reports changed on disk, a staged path you never added, one more field than
|
|
189
|
+
your predicted post-state — treat an unexplained delta as someone else's work, not
|
|
190
|
+
noise. Before a sweeping write (`git add -A`/`.`, `commit -a`, `stash`, `clean`,
|
|
191
|
+
`reset --hard`), attribute it (`git status`, reflog timestamps, other live sessions)
|
|
192
|
+
and then act only on what you can prove is yours — add by name.
|
|
140
193
|
|
|
141
194
|
## Config, secrets, and managed services
|
|
142
195
|
|
|
@@ -151,6 +204,13 @@ depends on it, pin it explicitly instead of trusting the environment.
|
|
|
151
204
|
leaving stale, unreferenced definitions live. After updating, re-read the
|
|
152
205
|
resource, check definitions and active references separately, and remove
|
|
153
206
|
the orphans explicitly.
|
|
207
|
+
- **Derive a new revision from the live one, not from a template**: a
|
|
208
|
+
replace-semantics update drops every field the command does not restate,
|
|
209
|
+
and wrappers commonly default mounted secrets to off. Render the exact set
|
|
210
|
+
the command will send, derived from the live resource, and diff it field
|
|
211
|
+
by field; a field that disappears, or an operational value that moves
|
|
212
|
+
backward, is a blocker to explain, not a default to accept. Re-read the
|
|
213
|
+
resource afterwards, since a command rarely labels its semantics.
|
|
154
214
|
- **A new revision is not live traffic**: on a runtime that pins traffic to a
|
|
155
215
|
named revision (e.g. Cloud Run with a fixed split), `gcloud run deploy` (or
|
|
156
216
|
the equivalent) creates the new revision but shifts no traffic to it — the
|
|
@@ -158,23 +218,101 @@ depends on it, pin it explicitly instead of trusting the environment.
|
|
|
158
218
|
update-traffic`. Read the "deploy succeeded" message as "a revision exists",
|
|
159
219
|
not "the new code is serving"; verify the live traffic split before
|
|
160
220
|
concluding the deploy took effect.
|
|
161
|
-
- **
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
221
|
+
- **Job logs outlive the execution**: a managed job that has run more than
|
|
222
|
+
once under one name — including one deleted and recreated with the same
|
|
223
|
+
name — returns the earlier incarnations' output when its logs are read by
|
|
224
|
+
job name. Scope every read to the execution id you received at launch and
|
|
225
|
+
confirm the timestamp window covers that run. An unscoped read merges
|
|
226
|
+
prior runs into the present and yields confident false diagnoses that a
|
|
227
|
+
scoped read reverses.
|
|
228
|
+
- **Dispatch status is not execution**: a CLI `--wait` returning or timing
|
|
229
|
+
out, a scheduler reporting success, a trigger accepted without error —
|
|
230
|
+
each reports what the dispatcher saw, not whether the target ran or what
|
|
231
|
+
state it reached. Before retrying or declaring done, re-derive the state
|
|
232
|
+
from the target's own record (its execution describe, the handler's logs),
|
|
233
|
+
matched to the run by id, and keep a manual probe distinguishable from the
|
|
234
|
+
scheduled one. A blind re-launch is a duplicate execution with side
|
|
235
|
+
effects.
|
|
236
|
+
- **An apply cut off before confirmation is unconfirmed** — neither done nor
|
|
237
|
+
un-run: when a multi-statement side-effecting apply (migration, batch
|
|
238
|
+
write) loses its confirmation channel, enumerate which target objects
|
|
239
|
+
already exist in the store, and plan the rerun from that partial state; a
|
|
240
|
+
naive rerun half-fails on "already exists" and leaves a second partial
|
|
241
|
+
state. Where the runner surfaces only exit status, route the object list
|
|
242
|
+
out through a deliberate failure. A transactional or provably idempotent
|
|
243
|
+
apply needs only the confirmation.
|
|
244
|
+
- **A traffic rollback is not a config rollback**: on a revision-pinned
|
|
245
|
+
runtime, sending traffic back to the previous revision restores behavior
|
|
246
|
+
but leaves the added env var or secret binding in the service template,
|
|
247
|
+
where the next deploy re-enables it silently. Count a rollback complete
|
|
248
|
+
only when the traffic split and the service spec are both back to the
|
|
249
|
+
prior state — re-read the spec and remove the change explicitly. Runtimes
|
|
250
|
+
that redeploy the prior spec itself (immutable-artifact, GitOps) have no
|
|
251
|
+
such gap.
|
|
252
|
+
- **Perimeter controls need the enforcement point's own logs**: an
|
|
253
|
+
agent-side fetch is not an independent observer — its egress IP and
|
|
254
|
+
caching path are opaque, and it may share the protected network or serve a
|
|
255
|
+
stale cached response. Verify allow AND deny directions from those logs,
|
|
256
|
+
and check for a front-side cache/CDN separately. Aim the probe at an
|
|
257
|
+
in-unit sentinel the app answers without credentials: a denial the app
|
|
258
|
+
produces anyway passes with the control off, and a redirect into it is a
|
|
259
|
+
bypass.
|
|
260
|
+
- **Tightening exposure is a behavior change for external clients**: switching
|
|
261
|
+
ingress mode, adding an allowlist, or requiring auth is not safe when
|
|
262
|
+
callers live outside your redeploy. Enumerate which clients reach the
|
|
263
|
+
endpoint and by which hostname, verify from a client's vantage, and
|
|
264
|
+
confirm inbound volume did not fall to zero — clients you cut off raise no
|
|
265
|
+
error on your side, so enforcement-point logs alone can sever ingestion
|
|
266
|
+
silently. Callers you redeploy in the same change need only the ordinary
|
|
267
|
+
deploy check.
|
|
166
268
|
- **Smoke limits outlive the smoke test**: item caps, sample sizes, and row
|
|
167
269
|
limits left in env vars/flags/config make a later "full-scale" run silently
|
|
168
270
|
succeed on a slice. Clearing or explicitly verifying their absence is a
|
|
169
271
|
precondition of declaring a full run.
|
|
272
|
+
- **A remote handle is valid only when it was read**: a row index in a sheet
|
|
273
|
+
that auto-sorts, a downloaded copy of a hosted file — each moves between
|
|
274
|
+
your read and your write. Before writing, re-establish the target from the
|
|
275
|
+
live source: re-locate the row by its key column, not a remembered
|
|
276
|
+
position, and assert the key matches after the write; compare the remote's
|
|
277
|
+
version against the copy you edited, re-downloading and reapplying on a
|
|
278
|
+
move. Local single-writer files need none of this.
|
|
279
|
+
- **Packaging and ignore rules are judged against paths and environments, not your tree**: before
|
|
280
|
+
a release, pack the real tarball, install it clean with lifecycle scripts
|
|
281
|
+
ON, and smoke it — a postinstall hook fine in the repo can delete the
|
|
282
|
+
shipped runtime where the build toolchain is absent. After moving or
|
|
283
|
+
renaming a directory, every ignore rule is void for the new paths:
|
|
284
|
+
re-check there and read the staged diff's file count, since old-path
|
|
285
|
+
patterns stop matching and excluded data enters the stage.
|
|
170
286
|
- **Shared live config has concurrent writers**: before concluding your edit
|
|
171
287
|
to a shared state/config file was lost or corrupting, rule out concurrent
|
|
172
288
|
writers with a short live observation (mtime plus the fields you changed),
|
|
173
289
|
and scope merge/union operations to the intended fields only.
|
|
290
|
+
- **Uniform failure is structural — read the persisted reason, then check the built artifact**: when
|
|
291
|
+
every item in a batch fails and the per-item error is persisted outside
|
|
292
|
+
the log (a status column, a result record), read it before blaming keys,
|
|
293
|
+
quota, or model availability. And when code reads sibling files from its
|
|
294
|
+
working directory, prove they exist inside the built image by listing or
|
|
295
|
+
hashing them there: a selective copy passes every repo-side check and
|
|
296
|
+
fails only at runtime.
|
|
174
297
|
- **Production probes expose data**: default diagnostic queries against
|
|
175
298
|
production stores to read-only server-side aggregation (counts, types,
|
|
176
299
|
presence, hashes) — never pull raw payloads into logs, prompts, or
|
|
177
300
|
transcripts — and delete scratch probe resources after the decision.
|
|
301
|
+
- **Build-context ignore patterns anchor at the root**: in a `.dockerignore`
|
|
302
|
+
or any root-anchored filter, a bare filename matches only at the context
|
|
303
|
+
root and never in a subdirectory, and an extension glob misses the
|
|
304
|
+
same-purpose credential file carrying another extension. Never conclude a
|
|
305
|
+
shipped image is secret-free from the patterns — list the built artifact's
|
|
306
|
+
own filesystem for credential-shaped files (env files, keys,
|
|
307
|
+
service-account JSON) as a named negative control, repeated whenever the
|
|
308
|
+
build context or ignore file changes.
|
|
309
|
+
- **A revoke is grant-wide, not token-wide**: revoking anything issued under
|
|
310
|
+
a client id the user's live sessions share invalidates those sessions too,
|
|
311
|
+
and the failure surfaces later, elsewhere, with no re-auth prompt. A probe
|
|
312
|
+
may clean up only what it alone owns — use minimum scopes and a dedicated
|
|
313
|
+
client id, and let a probe token expire rather than revoking it. Where a
|
|
314
|
+
revoke on a shared grant is unavoidable, state the blast radius and time
|
|
315
|
+
it with the user.
|
|
178
316
|
|
|
179
317
|
## Own what you spawn
|
|
180
318
|
|
|
@@ -186,3 +324,32 @@ Instance of the global rule: own the full lifecycle of what you create.
|
|
|
186
324
|
orphans the real child), and await exit. An unref'd child handle or open
|
|
187
325
|
stdin pipe keeps the parent's event loop alive and hangs otherwise-complete
|
|
188
326
|
commands.
|
|
327
|
+
- **A handle issued to a human is a commitment**: once a consent URL is
|
|
328
|
+
handed over, the listener behind it must not be restarted, re-ported, or
|
|
329
|
+
replaced while the person may still act — keep it alive until the callback
|
|
330
|
+
lands, or say plainly that the link is dead. The handler captures the
|
|
331
|
+
credential write-once and ignores later hits, since a browser's favicon
|
|
332
|
+
request clears a naive one. Before asking a human to click again, drive
|
|
333
|
+
the handler with a simulated callback.
|
|
334
|
+
- **A stop is confirmed at the sink, not in the process list**: a kill that
|
|
335
|
+
misses one descendant lets that stage finish and publish, and the process
|
|
336
|
+
list looks clean either way. After stopping a multi-stage run, list the
|
|
337
|
+
output sink for anything written after the stop instant and roll it back
|
|
338
|
+
as contaminated. Read the rollback path's retention — noncurrent-version
|
|
339
|
+
expiry is a recovery window, not a backup — and snapshot before a risky
|
|
340
|
+
run, choosing the restore point by timestamp.
|
|
341
|
+
- **Detach what must outlive the call**: a process started inside a harness
|
|
342
|
+
tool call belongs to that call's process group: a trailing `&` is reaped
|
|
343
|
+
when the call returns, and the harness may signal the group when another
|
|
344
|
+
background task finishes. Launch anything meant to outlive one call
|
|
345
|
+
through the harness's background facility or fully detached
|
|
346
|
+
(nohup/setsid), writing progress to durable files a resume can read. A
|
|
347
|
+
zero-byte output file means it never survived. Detached still means owned
|
|
348
|
+
— PID file and stop path.
|
|
349
|
+
- **Name-substring lookup is not a liveness check**: `pgrep -f <name>` and
|
|
350
|
+
`ps | grep <name>` match the argv of the shell running the query itself,
|
|
351
|
+
and match unrelated processes carrying the same name — another session, a
|
|
352
|
+
sibling dispatch, the launcher's own plan text. To decide whether a
|
|
353
|
+
dispatched job is alive, use the PID or handle captured at launch, its
|
|
354
|
+
process-group state, or growth of its own output artifact. Substring
|
|
355
|
+
lookup is for discovery only, confirmed against one of those first.
|