diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 51d62ce..6ec4172 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -12,7 +12,7 @@ "displayName": "Agent Stack", "source": "./plugins/agent-stack", "description": "Four skills: agent-orchestrator — tool-calling loops, pipelines with checkpoints, provider routing with fallback, memory architecture, plus the wallet side of reselling LLM access; agent-evals — run/trace/thread evals, LLM judges, and fixtures grown from production; agent-interop — MCP servers and clients, A2A agent cards, the MCP Registry, and gateways; agent-harness — system prompts, tool shaping, workflow-vs-agent, and auditing an agent system.", - "version": "0.28.1", + "version": "0.28.2", "author": { "name": "ssheleg", "url": "https://x.com/sshlg93" diff --git a/CHANGELOG.md b/CHANGELOG.md index 24b88c4..02c6594 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +## 0.28.2 — bounded restart admission + +- Resume only an owned stopped worker through the host's supported operation. + A quiet stream does not prove a stall; one failed lane does not authorize + stopping siblings or duplicating their in-flight work. +- Reconcile uncertain outward effects before replay. Run IDs and unchanged + arguments do not guarantee cached completion or preserved context. +- Record finite attempt and deadline bounds, including host retries, and retain + provider Retry-After/reset timing. Recheck task authority and ownership before + each attempt; preserve the best partial when the series ends. +- Keep independent work moving while a watcher handles the eligible retry. + Billing, sign-in, consent and secret-entry gates remain human; no account/key + switching or cap bypass. Focused text controls cover known unsafe instructions, + without claiming observed model or scheduler behavior. + ## 0.28.1 — a limit stop is not a wait There is no 0.28.0 package. The tag `v0.28.0` was pushed by mistake onto `cb8f699` (the 0.27.1 diff --git a/README.md b/README.md index 924c158..7c8b636 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,10 @@ mechanisms for one idea, the four double-texting policies, streaming a dropped connection can rejoin, forking a past checkpoint to debug through the real loop, stateful versus stateless schedules, and the seven cross-cutting concerns pulled out of the loop into ordered interceptors — where order is semantics. +Usage-limit recovery preserves lane ownership and uncertain effects, uses finite +attempt/deadline budgets and provider timing, and keeps independent work moving. +The [restart correction packet](docs/evidence/runs/2026-10-13-restart-boundaries.md) +records the counterexamples and the limits of the instruction-only checks. **`references/governance.md`** — permission rather than cost. The four boundaries an agent crosses (model, tool, external server, agent-to-agent), each with its own diff --git a/SKILL-CARD.md b/SKILL-CARD.md index bd4192f..16be97c 100644 --- a/SKILL-CARD.md +++ b/SKILL-CARD.md @@ -5,7 +5,7 @@ | Field | Value | |---|---| | Pack | `agent-stack` | -| Version | `0.28.1` | +| Version | `0.28.2` | | Skills | `agent-orchestrator`, `agent-evals`, `agent-interop`, `agent-harness` | | License | MIT | | Source | https://github.com/ssheleg/agent-stack | diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 8979cbd..a6c4e3c 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -1,11 +1,21 @@ -# Current work — published agent-stack 0.27.2 +# Current work — agent-stack 0.28.2 release candidate (not published) -R30 owner-board and release-ancestry gates are merged and published as0.27.2, -source `792e3f6cb2e46517f0187066db55edc63ae7d12c`. All four release jobs passed, -and all44 npm payload files matched that source. The -[release packet](evidence/runs/2026-10-13-release-0.27.2.md#published-readback) -is the durable entry with exact sources, gates and limitations. +Agent-stack0.28.1 source `cd6421b8ca7d9440bc87e366ebd8a96bb38b69b8` is published, +but independent review found the restart instruction overbroad. The current +[restart correction packet](evidence/runs/2026-10-13-restart-boundaries.md) owns +scope, counterexamples, checks, remaining gates and the exact next action. -Exact next task: coordinator pins0.27.2 in the next family release and verifies -installed files. B-161 source/publication scope is closed; the family-wide R30 -and native runtime remain distinct. Preserve foreign worktrees and old tags. +Independent source review of the doctrine correction passed at +`ff797c6341fe6cdb4d9b0dd2e113f7ebb8f24f6f`, recorded in the hub's +[peer receipt](https://github.com/ssheleg/sshlg-skills/blob/82310a5/docs/evidence/completion-1013/agent-stack-restart-peer.json). +Version metadata now targets 0.28.2; this is not publication evidence. +The [release packet](evidence/runs/2026-10-13-release-0.28.2.md) owns pending gates. + +Next: independent metadata review, one coordinated local owner aggregate, normal +exact-head PR checks and merge, then exact accepted-main local full chain before +the annotated tag and release/readback; do not change either existing0.28.0 or0.28.1 tag. Hub keeps its +accepted0.27.2 pin until the correction is accepted and published. No native retry +mechanism or model behavior is claimed by these documentation tests. + +Earlier0.27.2 source/publication evidence remains in the +[release packet](evidence/runs/2026-10-13-release-0.27.2.md#published-readback). diff --git a/docs/evidence/runs/2026-10-13-release-0.28.2-candidate.json b/docs/evidence/runs/2026-10-13-release-0.28.2-candidate.json new file mode 100644 index 0000000..6af6594 --- /dev/null +++ b/docs/evidence/runs/2026-10-13-release-0.28.2-candidate.json @@ -0,0 +1,295 @@ +{ + "schema": "release-candidate/1", + "version": "0.28.2", + "status": "CANDIDATE_NOT_PUBLISHED", + "reviewedDoctrine": "ff797c6341fe6cdb4d9b0dd2e113f7ebb8f24f6f", + "observedAt": "2026-10-13T08:45:01.162095+00:00", + "checks": [ + { + "argv": [ + "python3", + "-B", + "test/validate.py" + ], + "exit": 0, + "outputSha256": "6822712dfac56cb79ac20c371d64adc75758eb5c021c53984e5439546a6ac73a" + }, + { + "argv": [ + "python3", + "-B", + "test/audit_regressions/restart-boundaries.py" + ], + "exit": 0, + "outputSha256": "cd0858c45bc89bcad050bf7426a8af8e400eeb63851b89e81fe647cbeb161e2d" + }, + { + "argv": [ + "claude", + "plugin", + "validate", + ".", + "--strict" + ], + "exit": 0, + "outputSha256": "e681c9722b621a912c34443001df8b4c02c4276cc50f4004a70a37f4f957d358" + }, + { + "argv": [ + "claude", + "plugin", + "validate", + "plugins/agent-stack", + "--strict" + ], + "exit": 0, + "outputSha256": "bc22c2f268f8d30ec7fe5e5cbcc6cb95fa6766bbf57deb4802cc94c229134df5" + }, + { + "argv": [ + "git", + "diff", + "--check" + ], + "exit": 0, + "outputSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + ], + "npmDryRunExit": 0, + "payload": [ + { + "path": "CHANGELOG.md", + "sha256": "0fce6df83bb875438bbcd2dd1609665ae19348284405c1b2c7b075514a375e7e", + "sameAsReviewedDoctrine": false + }, + { + "path": "LICENSE", + "sha256": "826df230e15df9b208c1e08c42ef3b764b21c4abec5a91a38976748e92a82e9d", + "sameAsReviewedDoctrine": true + }, + { + "path": "README.md", + "sha256": "49953599fcd54dfcba0f1254636ddd46fca0e0ac6c141091bf72552c53131f3e", + "sameAsReviewedDoctrine": true + }, + { + "path": "SECURITY.md", + "sha256": "87715bb85d820beb6179cf5294fc7ed461cb234657df810031c0eb527fb00b62", + "sameAsReviewedDoctrine": true + }, + { + "path": "bin/agent-stack.js", + "sha256": "5706481b1f1266174eeefebc1f2fc5ff6f30f77b395289490b182e95d5c97b00", + "sameAsReviewedDoctrine": true + }, + { + "path": "package.json", + "sha256": "42cbab0ed2a00d1bc950ada5688221b8d291bf82f1a681df6e3994935066ceed", + "sameAsReviewedDoctrine": false + }, + { + "path": "plugins/agent-stack/.claude-plugin/plugin.json", + "sha256": "678aa34cceef4ff51bedad7f718baa901af911fdf33afd9bf22b091ac1461a3f", + "sameAsReviewedDoctrine": false + }, + { + "path": "plugins/agent-stack/skills/agent-evals/references/multi-agent.md", + "sha256": "e0c3175aa8858de1ba8117c613d2e201e32ff581453078c927a3ebddcff6c0bb", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-evals/references/otel-genai.md", + "sha256": "d2cadad0a6a0632d234a51621b136f3001f5a7422e256f84d261d7c0ff1660d5", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-evals/references/statistics.md", + "sha256": "77cd03cc4f258a097888f81b817e8c9487b4d777d9ac092f76fe48de8de692ca", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-evals/SKILL.md", + "sha256": "8f533ce3e320e0416163a39a98207cd347a0d22332c4072afa1d628f77204b8b", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/references/audit.md", + "sha256": "b91b966250438edd91b87c392113404d830b06301518d9120246321c88d9a1aa", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/references/context-lifecycle.md", + "sha256": "f682b0d4894f7f58baf4f39e622ed1bf8bc773d3c76c552a09aecab4c1e23fef", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/references/instruction-budget.md", + "sha256": "3962dbe1643ca1f867575786597cfeea93a28b1d0cc940811020e2d4b49fc6a6", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/references/layers.md", + "sha256": "e2f4fd73424b0896c493616dbb98e7bd973eaad3b8365b3c1b31964fbac46d89", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/references/pi-sdk.md", + "sha256": "b7eb9375934887ed5f85e597e80c5f3d83c02c37cd585aff13960104a31ddcd5", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/references/pi.md", + "sha256": "684616062c9d109ff13eed83a5b9a10544040f1ee22790ee70e8d8156b286c08", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/references/system-prompt.md", + "sha256": "f8577ebfeb8ae7448b36b5cd7fcca1ef4ab7065d1aef9baf6f7946eb5ea2905a", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/references/techniques.md", + "sha256": "4198c8d2d8a0d6da2f8ba7f2370310578167819abbb9bd351a722491ee8f31e8", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/references/tools.md", + "sha256": "572822bc05a710019fc5454f2ddb3750537dbf3667fc73fad0c8bcdcd0f1346a", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/references/workbench-contracts.md", + "sha256": "a17af9cc84dcc8661085ebb606b09ac08ebe39f6c1fc436ab547ac21747bca80", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/scripts/audit_agent.py", + "sha256": "f0193565dd3851d3ea779a05f018099b9f2bca3eccacc370b9a43048baba656a", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/scripts/instruction_budget.py", + "sha256": "0f88ff1764cc5a87a2b523126c871e71af750bc29128e05b97f9e6955db999ab", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-harness/SKILL.md", + "sha256": "003866190df99a02ea862860050c03c2ce8971479ced5ba75bfe42057a0ba4e0", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-interop/references/a2a.md", + "sha256": "e39c4c6d1f19b39e09720c40a09a50e8f2a59824aeb83c5336443f8b709a6c34", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-interop/references/gateway.md", + "sha256": "e74e8585eb6a1fba08af5b419a67c41f38689a29886a89dc149ef3465b9319a0", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-interop/references/mcp-scale.md", + "sha256": "c69b0bfd73e189776fcc6ecdd7d3e88964073ab19a66ffcf79aab579b341a892", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-interop/references/mcp-ship.md", + "sha256": "2918ca0beed94ca7f7e34bb30e2609495c421121d3a94a0e43e743fc76b644a2", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-interop/references/mcp.md", + "sha256": "9b427194659408ae7f521ea689b8b23cbfd216f918f313cc961dce360b7e80b4", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-interop/references/registry.md", + "sha256": "648e7649369b9aa5dac5f424c9a4373292e5d73c90d9466b58171934e5c7b51f", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-interop/SKILL.md", + "sha256": "3e70a38f204edc6822814335dc6dfc4e8c3b825117137239da46b96fdd60bfec", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/context-engineering.md", + "sha256": "57811d800b75f25a5a242505e8e6be2b33775fb156893ebec51af5ea18fcfc1e", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/governance.md", + "sha256": "bb2e3389779a56d4ace610bb14b5df05ace7fa6efc1e5810b0ae929f7050e435", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/graph-engineering.md", + "sha256": "c594d1b0a4813f0d47e60a26e2b7905a964c3017556a400fcbd534f390811e70", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/kv-cache.md", + "sha256": "b8ae7c5ba9531ebb02ded2e403a8fcb4ae2b944940076a4f15f966d05f6caeae", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/llm-proxy-billing.md", + "sha256": "84c2144d6a5a917c042c5e31ecfacfe6238c60870da567abc00bd770e3bccccd", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/memory-architecture.md", + "sha256": "860466e4e54d0116063146401c3df54a25bbf07cdfba18b63d0fb0e06a285f1a", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/memory-landscape.md", + "sha256": "b297b121ebb07c50579f929f0e5361598625b024dbf49653b82e12b1dc0b4f4d", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/memory-lifecycle.md", + "sha256": "6c7252553bc6308e6f5ec88bb802a62e4bacd98f7946ec5b2e82fef8c1aa0073", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/patterns.md", + "sha256": "a239bc4549339b049b54b154f88536bed68256ffffdcdc4a0f41cf7185eeb360", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/pipeline.md", + "sha256": "89f160068715136c6f7793b305f78371831ebef9527cdb481e15b5af9a1af40b", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/provider-lifecycle.md", + "sha256": "d9b4462baf1c805daf05612d7ee8556ac5e666f72de62609666f1ee469294de3", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/references/runtime.md", + "sha256": "4c49fe64e16256fd78529e4a557782c5ccd9be8af8a5703bb92a773bdea12d70", + "sameAsReviewedDoctrine": true + }, + { + "path": "plugins/agent-stack/skills/agent-orchestrator/SKILL.md", + "sha256": "8a80583133707ea69c9e7c0963a68f74b138b74e5148e31ceeea12097af32aba", + "sameAsReviewedDoctrine": true + } + ], + "payloadCount": 44, + "changedPayloadSinceReviewedDoctrine": [ + "CHANGELOG.md", + "package.json", + "plugins/agent-stack/.claude-plugin/plugin.json" + ], + "fullOwnerGate": "NOT_RUN_QUEUED_AFTER_TP_AND_SEO", + "hostedPR": "NOT_RUN", + "release": "NOT_RUN", + "installedApply": "OUT_OF_SCOPE", + "notes": [ + "Metadata homes package/marketplace/plugin/card aligned, historical changelog untouched below new section.", + "Exact accepted main will run local full npm test chain before annotated tag." + ] +} diff --git a/docs/evidence/runs/2026-10-13-release-0.28.2.md b/docs/evidence/runs/2026-10-13-release-0.28.2.md new file mode 100644 index 0000000..55b72a0 --- /dev/null +++ b/docs/evidence/runs/2026-10-13-release-0.28.2.md @@ -0,0 +1,38 @@ +# Agent-stack 0.28.2 release candidate + +Status: NOT PUBLISHED. Current published predecessor is 0.28.1 at +`cd6421b8ca7d9440bc87e366ebd8a96bb38b69b8`. + +This candidate packages the independently reviewed bounded restart correction at +`ff797c6341fe6cdb4d9b0dd2e113f7ebb8f24f6f`. The +[correction packet](2026-10-13-restart-boundaries.md) records source scenarios and +text-control limits. Independent peer evidence is in the hub at +[82310a5](https://github.com/ssheleg/sshlg-skills/blob/82310a5/docs/evidence/completion-1013/agent-stack-restart-peer.json). +Metadata aligns package, marketplace, plugin and skill card; no skill description, +runtime reference, validator, workflow or executable helper changes relative to +that reviewed source. The new changelog section describes the correction while +leaving historical 0.28.0/0.28.1 records and immutable tags untouched. + +Plan: root independently reviews this metadata diff; acquire the coordinated +local aggregate slot after TP and SEO; run owner npm test and both strict plugin +manifests; promote one frozen draft PR for genuine required checks; merge normally +with exact head matching; verify the accepted main tree and run its local full +npm test chain before making an annotated v0.28.2 tag. Watch all release jobs and +compare every served npm file against the tagged source. A pending/failed check +is not success and causes no blind dispatch/tag retry. Parent owns hub pins and +actual installation; this task makes no machine apply. + +Coordination task AS-RELEASE-0282 is advisory local ownership, not cross-machine +exclusion. Full owner validation, hosted candidate, source merge, annotated tag, +registry publication, published byte readback and installed adoption are pending +at this planning cut. Subsequent receipts append actual outcomes with exact SHAs. + +## Bounded candidate checks + +The [candidate receipt](2026-10-13-release-0.28.2-candidate.json) records exact +command exit codes and all 44 npm dry-run file hashes. Structural validation, +focused restart controls, both strict manifests and diff hygiene passed. +Only package.json, plugin.json and the new changelog section differ in the +shipped payload from reviewed doctrine ff797c6; all other published bytes match. +These focused checks do not replace the queued owner aggregate or future hosted +and release gates. diff --git a/docs/evidence/runs/2026-10-13-restart-boundaries.md b/docs/evidence/runs/2026-10-13-restart-boundaries.md new file mode 100644 index 0000000..86ed6e0 --- /dev/null +++ b/docs/evidence/runs/2026-10-13-restart-boundaries.md @@ -0,0 +1,81 @@ +ssheleg skills — task-pipeline · evidence-docs · agent-sync + +# Bounded restart correction after0.28.1 + +## Objective and ownership + +Preserve the operator's autonomous continuation intent without making a stopped +lane permission to cancel active siblings, duplicate an uncertain outward effect +or retry forever. Baseline is published `cd6421b8ca7d9440bc87e366ebd8a96bb38b69b8`. +The isolated branch owns agent-orchestrator's body/runtime reference, its focused +text regression, current README/handoff/verification and this packet. Task +`RESTART-BOUNDS-1013` uses an advisory local lease; guarded verification resource +was separately acquired. No foreign tree or installed profile is changed. + +The independent parent-hub receipt is committed as `5f71ec2` on +`docs/eval-results-1013`, under `docs/evidence/completion-1013/agent-stack-0281-peer.md`. +It verified all44 npm files against baseline Git and all four release jobs at +https://github.com/ssheleg/agent-stack/actions/runs/38355706771. +Publication success did not certify the new doctrine's recovery semantics. + +## Frozen counterexamples and intended correction + +| Scenario | Baseline instruction path | Corrected boundary | +|---|---|---| +| A hits quota while B awaits an outward response | “stop the workflow” can stop B too | Resume owned stopped A only; whole-workflow recovery needs sibling/in-flight reconciliation and authority. | +| Provider accepted an effect but response/checkpoint is missing | Same run ID/arguments are presented as sufficient recovery | Unknown outcome stays unknown; reconcile attempt/provider receipt or idempotency key before replay. | +| Fixed quota never clears | Backoff continues every15 minutes without a terminal rule | Finite recorded cap/deadline includes host attempts; exhaustion records partial and next step. | +| Retry-After or known reset is later than the suggested next attempt | “restart at once” ignores eligibility | Provider timing is a lower bound unless newer supported evidence changes it; deadline may end the series. | +| Task is cancelled or another worker takes ownership between attempts | Resume-by-ID alone can continue stale work | Recheck current task authority/ownership before each attempt; revoked/exhausted work stops. | +| Stream is quiet while a host request or command remains active | Silence is treated as a restart trigger | Inspect host liveness; no second active owner; ambiguous state gets a watcher. | +| Spend/credit failure or human sign-in required | Existing billing exception is correct | Preserve billing stop and human-only gates; no account/key switching or cap bypass. | +| A stopped transient worker is eligible and authorized | Autonomous continuation is desired | Supported bounded resume proceeds without a new approval question; independent work continues meanwhile. | + +These are manual semantic instruction counterexamples, not executed provider or +agent traces. The change supplies doctrine, not a scheduler implementation. +Cache/resume claims are now conditional on the actual host contract; no invented +universal `resume` API or cache guarantee remains. The prior changelog stays an +immutable description of0.28.1; a successor release must explicitly describe the +correction rather than rewrite the old entry. + +## Checks actually run + +- New `python3 -B test/audit_regressions/restart-boundaries.py` on baseline source: + exit1 with12 diagnostic clauses. This counts textual omissions/reintroduced + unsafe claims, not12 independent production defects. Initial exploratory + checker also demanded a new spelling for the already-present billing exception; + that redundant assertion was removed before recording this baseline. +- The same checker on corrected source: exit0, candidate contract plus11 + in-memory plants/controls. It removes admission/timing/authority clauses, + restores unsafe old commands, checks body admission and accepts an unrelated + wording edit. No temporary tree or provider call. It cannot prove arbitrary + English semantics or actual model adherence. +- `python3 -B test/validate.py`: exit0,17 structural checks at0.28.1. It explicitly + reports strict frontmatter cross-reader unlooked in this isolated checkout; + separate strict native manifest results are recorded below. +- Direct `tiktoken` cl100k_base body measurement:4400 tokens for agent-orchestrator, + below the4750 working bound. The description is unchanged. +- `claude plugin validate plugins/agent-stack --strict` and + `claude plugin validate . --strict`: both exit0. + +- `npm pack --dry-run --json`: exit0,44 files; runtime reference included and + docs/test/private coordination paths absent. `git diff --check`: exit0. + +Owner aggregate and model replay are **NOT_RUN**; no duplicate broad suite while +the coordinator's serial slot is occupied. Release version remains0.28.1 in this +pre-review correction branch; no successor publication claim yet. + +## Exact next task + +Independent reviewer reads the body/reference delta against the frozen scenarios +and challenges the text checker with a missing boundary or restored unsafe +command. On acceptance, synchronize a successor patch version in all metadata +homes and add its changelog correction, run the single coordinated owner aggregate +and normal required CI, then release under existing policy and compare the whole +published payload. Parent may advance the hub pin only after that separate +acceptance. Keep the two historical tags unchanged. + +--- +**Made with [ssheleg skills](https://github.com/ssheleg/sshlg-skills)**: +task-pipeline for bounded delivery; evidence-docs for proof boundaries; +agent-sync for local ownership. diff --git a/docs/evidence/verification.md b/docs/evidence/verification.md index 2ce0332..8aed362 100644 --- a/docs/evidence/verification.md +++ b/docs/evidence/verification.md @@ -10,6 +10,15 @@ This file exists because its absence read as zero exposure. `sshlg-skills` board --- +## Unreleased restart-boundary correction (2026-10-13) + +The [owner packet](runs/2026-10-13-restart-boundaries.md) narrows the published +0.28.1 restart instruction: isolated owned recovery, sibling/in-flight admission, +finite retry bounds, provider timing and current authority. Local text regression +checks, structural validation and manual counterexample reading are evidence for +instruction scope only. Native model behavior, owner aggregate, integration and +successor release remain pending. The published0.28.1 evidence below is historical. + ## Release candidate — v0.28.1 (2026-10-13) The change is doctrine only: no script, validator or installer change. It was measured on the diff --git a/package.json b/package.json index 1562f9e..5e5949e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ssheleg/agent-stack", - "version": "0.28.1", + "version": "0.28.2", "scripts": { "test": "python3 test/validate.py && python3 test/plant_guard_test.py && python3 test/member_owner_gates_test.py && python3 test/reap_own_test.py && node test/installer_test.js && npm run test:audit", "test:audit": "for t in test/audit_regressions/*.py; do python3 \"$t\" || exit 1; done" diff --git a/plugins/agent-stack/.claude-plugin/plugin.json b/plugins/agent-stack/.claude-plugin/plugin.json index 5a7bd79..a489be5 100644 --- a/plugins/agent-stack/.claude-plugin/plugin.json +++ b/plugins/agent-stack/.claude-plugin/plugin.json @@ -3,7 +3,7 @@ "name": "agent-stack", "displayName": "Agent Stack", "description": "Four skills: agent-orchestrator — tool-calling loops, pipelines with checkpoints, provider routing with fallback, memory architecture, plus the wallet side of reselling LLM access; agent-evals — run/trace/thread evals, LLM judges, and fixtures grown from production; agent-interop — MCP servers and clients, A2A agent cards, the MCP Registry, and gateways; agent-harness — system prompts, tool shaping, workflow-vs-agent, and auditing an agent system.", - "version": "0.28.1", + "version": "0.28.2", "author": { "name": "ssheleg", "url": "https://x.com/sshlg93" diff --git a/plugins/agent-stack/skills/agent-orchestrator/SKILL.md b/plugins/agent-stack/skills/agent-orchestrator/SKILL.md index d1822a5..17f07ae 100644 --- a/plugins/agent-stack/skills/agent-orchestrator/SKILL.md +++ b/plugins/agent-stack/skills/agent-orchestrator/SKILL.md @@ -124,7 +124,7 @@ Wrap every sub-agent call in retry **and** validation, and keep the two apart: a threw and a call that returned something unusable need different answers. Retry the first, re-prompt or fail the second. -Three decisions the rest follows from: +The decisions the rest follows from: - **Split errors into retryable and fatal at the type level**, not at the call site. A bad credential and an overloaded provider are both exceptions and only one is worth a second @@ -134,11 +134,11 @@ Three decisions the rest follows from: passes every check that only looks for an exception. - **Cap the attempts and return the best partial**, because the alternative to a partial answer is not a better answer, it is no answer and a spent budget. -- **A limit stop is not a wait.** A worker halted by a provider's usage limit - ("resets at 9pm"), a rate-limit error, or silence with its task unfinished is restarted - from where it stopped right away, not at the stated reset; back off only when the - restart fails again. Spend and billing limits are the exception — a person's gate. - Mechanics: [`references/runtime.md`](references/runtime.md) → *A limit stop is not a wait*. +- **A limit stop is not a wait.** Continue independent work and arrange a + bounded, authorized resume of the stopped worker; not every silence is a stall. + Preserve provider timing, attempt/deadline budgets and uncertain-effect recovery. + Spend and billing limits remain a person's gate. Mechanics and admission: + [`references/runtime.md`](references/runtime.md) → *A limit stop is not a wait*. The hierarchy, the loop and the per-domain validators: [`references/patterns.md`](references/patterns.md). diff --git a/plugins/agent-stack/skills/agent-orchestrator/references/runtime.md b/plugins/agent-stack/skills/agent-orchestrator/references/runtime.md index 5797cff..d2004bd 100644 --- a/plugins/agent-stack/skills/agent-orchestrator/references/runtime.md +++ b/plugins/agent-stack/skills/agent-orchestrator/references/runtime.md @@ -45,43 +45,59 @@ Two properties earn their cost: ## A limit stop is not a wait -A coding-agent host shows a usage stop as *You've hit your session limit · resets 5am*. -The time in that message describes **one account**, read when the request was refused. In -practice an orchestrator that restarts the worker minutes later usually finds it runs. An -account rotator may already have moved the session to an account with room, or the -limit was a short rate window. Waiting hours for the stated reset idles a run that would -have gone on. - -**Three triggers** send the orchestrator to restart a worker — a lane of a workflow, a -sub-agent, a whole session: - -- it stopped on a usage or session limit, whatever reset time it names; -- it failed on a rate-limit error after the host's own retries; -- it went silent: no transcript or event write for 15–20 minutes, its task unfinished, - **and no command of its own still running**. A build or a test suite that runs for half - an hour is not a stall, and stopping that lane loses the step in flight. - -**Restart at once, from where it stopped**, never from scratch: - -| Worker | Restart | +A usage/session limit or exhausted host rate-limit retry is a recovery signal, +not a reason to leave all other work idle. Record the stopped unit and continue an +independent task. A reset message describes the provider/account that emitted it; +without a newer supported status, do not assume that its limit has cleared or that +an account rotator exists. Do not change accounts, keys or providers to evade it. + +**Admit the stopped unit before resuming.** Read the host's supported resume and +checkpoint contract. Establish that this unit has stopped, rather than only lost +its visible stream. Silence for 15–20 minutes is a reason to inspect liveness, +not proof of failure: an active command, provider request, sibling or supervisor +may still own the work. Do not create a second active owner. + +| Worker | Recovery boundary | |---|---| -| A workflow lane | stop the workflow, then resume it with the same run id and **the same arguments**: finished agents replay from the cache, and only the failed or stalled ones run again | -| A sub-agent | send `resume` to its id, so it keeps its own context | -| A session | re-prompt it: *continue from where you stopped* | - -Changed arguments invalidate the cache, so the whole run is paid for again. - -**Back off only on a second stop.** If the restart halts again at once, retry at 2, 5, -10 and then every 15 minutes, and keep doing independent work in between. Do not sleep -until the reset time. - -**Not every limit is retried.** A spend cap, exhausted credits or a billing error does not -clear on a timer: someone has to pay or raise it. Report it to that person once and do -not loop. - -**Log every restart** in the run's journal: which worker stopped, on what, when, and the -attempt number. Ten restarts of one lane in an hour is a finding about that lane, not -noise. +| A workflow lane | Resume only the owned stopped lane through a supported host operation. Do not stop the whole workflow for one failed lane. If the host only supports whole-workflow recovery, reconcile every sibling and in-flight effect before stopping; require the workflow owner's existing authority and a safe checkpoint for all affected work. Otherwise record the dependency and use a watcher. | +| A sub-agent | Use the host's documented resume operation at its existing ID only after it is stopped and its owner permits continuation. An ID alone does not prove a resume API or preserved context. | +| A session | Re-prompt the same stopped session when supported, carrying the durable checkpoint and exact next action. Do not overlap a still-running turn or infer authority from the prompt. | + +Keep the run identity and arguments when that host's resume contract requires +them. Cached completion and argument invalidation are host-specific properties, +not guarantees of this skill. Verify what is actually durable. A checkpoint is +not a promise that an effect was not performed. Do not blindly replay an outward effect with an unknown outcome. +Reconcile its attempt/provider receipt or idempotency key first; preserve unknown +state and arrange a watcher when the outcome cannot yet be determined. + +**Bound every retry series.** Before the first attempt, record a finite attempt cap and a deadline, +including attempts already made by the host, plus the existing resource/spend +budget. If a bound is unknown, establish a conservative bound within existing +authority before making another call; do not interpret unknown as unlimited. +Before each attempt, recheck that the task is still active and authorized and that +no sibling or replacement now owns it. Cancellation, expired authority or exhausted +bounds stops the series, retains the best partial and records a durable next step. +This uses existing act-specific authority, not a new permission gate for ordinary +already-authorized continuation. + +An immediate supported resume is eligible only when no provider Retry-After or +known reset window remains, or newer supported evidence shows the earlier limit +no longer applies. Otherwise set a watcher for that lower bound. If a transient +stop repeats, use 2, 5, 10, then 15 minute backoff only within the recorded cap and +deadline; take the later of backoff and provider timing. A deadline before eligibility +ends this series rather than bypassing the provider. Continue independent work +between attempts; a watcher is not a sleep holding the worker. + +**Human gates stay human.** Do not loop on a spend, credit or billing failure; +report it once with the existing policy/decision and preserve the pending task. +Sign-ins, consents, payments/top-ups and secrets typed by a person remain human +steps. A resume grant cannot raise a cap, spend another agent's key or bypass +provider restrictions. Other already-authorized work continues. + +**Log each attempt**: stopped unit and owner, reason, supported recovery action, +checkpoint and uncertain effects, current authority, attempt/cap, deadline, +provider eligibility and watcher identity. Record the outcome before scheduling +another attempt. Repeated stops are a finding, not a reason to extend the cap. ## The interrupt/resume contract diff --git a/test/audit_regressions/restart-boundaries.py b/test/audit_regressions/restart-boundaries.py new file mode 100644 index 0000000..c781e57 --- /dev/null +++ b/test/audit_regressions/restart-boundaries.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +"""Bounded text regression for the unsafe restart instructions in 0.28.1. + +This watches known unsafe clauses return and critical admission clauses disappear. +It does not execute an agent or prove arbitrary prose/host semantics. Counterexample +schedules and the manual baseline/candidate reading live in the dated owner receipt. +No temporary trees, provider requests or runtime implementation are introduced. +""" +from pathlib import Path +import sys +sys.dont_write_bytecode = True +ROOT = Path(__file__).resolve().parents[2] +HOME = ROOT / 'plugins/agent-stack/skills/agent-orchestrator' + +def errors(skill, runtime): + section = runtime.split('## A limit stop is not a wait\n', 1)[1].split('\n## ', 1)[0] + flat = ' '.join(section.split()) + failures = [] + for forbidden in ('stop the workflow, then resume it', + 'finished agents replay from the cache', + 'Changed arguments invalidate the cache, so the whole run is paid for again.', + 'usually finds it runs'): + if forbidden in flat: failures.append('unqualified restart/cache claim: '+forbidden) + for needle, label in ( + ('Do not stop the whole workflow for one failed lane.', 'lane isolation'), + ('reconcile every sibling and in-flight effect before stopping', 'sibling admission'), + ('Do not blindly replay an outward effect with an unknown outcome.', 'uncertain effect'), + ('finite attempt cap and a deadline', 'retry ceiling'), + ('Retry-After', 'provider timing'), + ('recheck that the task is still active and authorized', 'current authority'), + ('not a promise that an effect was not performed', 'checkpoint distinction'), + ): + if needle not in flat: failures.append('missing '+label) + body = ' '.join(skill.split()) + if 'bounded, authorized resume' not in body or 'not every silence is a stall' not in body: + failures.append('body bypasses bounded admission') + return failures + +def main(): + skill=(HOME/'SKILL.md').read_text();runtime=(HOME/'references/runtime.md').read_text() + problems=errors(skill,runtime) + for p in problems: print('FAIL:',p) + if problems:return 1 + # Plants run against actual candidate text: a safe unrelated wording edit remains + # accepted; removing a relevant constraint and restoring old operational commands fail. + checks=0 + for phrase in ('Do not stop the whole workflow for one failed lane.', + 'reconcile every sibling and in-flight effect before stopping', + 'Do not blindly replay an outward effect with an unknown outcome.', + 'finite attempt cap and a deadline','Retry-After', + 'recheck that the task is still active and authorized'): + assert phrase in runtime + assert errors(skill,runtime.replace(phrase,'REMOVED')),phrase + checks+=1 + for old in ('stop the workflow, then resume it', + 'finished agents replay from the cache', + 'usually finds it runs'): + planted=runtime.replace('## A limit stop is not a wait\n','## A limit stop is not a wait\n'+old+'\n',1) + assert errors(skill,planted),old + checks+=1 + assert not errors(skill,runtime.replace('Log each attempt','Record each attempt')) + checks+=1 + assert errors(skill.replace('bounded, authorized resume','resume now'),runtime) + checks+=1 + print(f'PASS: restart-boundaries — candidate contract + {checks} text plants/controls; no agent replay') + return 0 +if __name__=='__main__':raise SystemExit(main())