@agentskit/harness 0.8.0 → 0.10.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/CHANGELOG.md +40 -0
- package/capabilities/public-surface.json +187 -76
- package/dist/cli.js +1171 -151
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +342 -7
- package/dist/index.js +1002 -81
- package/dist/index.js.map +1 -1
- package/docs/ADR-0029-loop-resilience-pinning-intake.md +68 -0
- package/docs/ADR-0030-loop-event-bus-orchestration-hooks.md +54 -0
- package/docs/LOOP.md +185 -2
- package/docs/MODULE-BOUNDARIES.md +9 -3
- package/loop.config.example.yaml +54 -1
- package/package.json +2 -2
- package/release/manifest.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.10.0] - 2026-09-12
|
|
4
|
+
|
|
5
|
+
Closes the gaps found comparing this harness against LangChain's "custom agent harness" article. The structural
|
|
6
|
+
difference stands: this harness orchestrates opaque external CLI agents, so a model/tool-loop middleware isn't
|
|
7
|
+
possible here — every item below targets the orchestration layer this loop actually controls (see ADR-0030).
|
|
8
|
+
|
|
9
|
+
- **Local event bus + orchestration lifecycle hooks**: `plugins.modules` (local `.mjs` files, empty by default)
|
|
10
|
+
loaded once per `tick`/`deliver`, each getting `src/loop/event-bus.ts`'s bus to subscribe to loop events live
|
|
11
|
+
and to `beforeDispatch`/`afterDispatch`/`beforeReview`/`afterReview`/`beforeMerge`/`afterMerge`/`onPause`/
|
|
12
|
+
`onEscalate` — a `before*` hook can return `{ block: true, reason }` to stop the action. `loop doctor` gained a
|
|
13
|
+
`plugins.modules` check.
|
|
14
|
+
- **PII/secret scanning**: `security.pii.enabled` (default false) scans issue text before it enters the
|
|
15
|
+
orchestrator prompt and the worker brief for PII-shaped patterns (email, common API-key prefixes, phone,
|
|
16
|
+
card-number-shaped digits); `security.pii.action` is `redact` (default when enabled), `warn`, or `block`.
|
|
17
|
+
- **Cost/time circuit breakers** for an in-flight dispatch, since the loop cannot count a worker CLI's own
|
|
18
|
+
model/tool calls: `delivery.maxDispatchMinutes` (hard wall-clock ceiling) and `resilience.maxUsageDeltaPercent`
|
|
19
|
+
(stops a dispatch whose provider's remaining Orca usage dropped past the threshold since it was sent out).
|
|
20
|
+
`dispatch.json` now records `initialRemainingPercent`. Either trip stops the issue like a stuck worker.
|
|
21
|
+
- **Human-approval merge gate**: `delivery.merge.requireHumanApproval` (default false) holds a clean, green-checks
|
|
22
|
+
PR until a human approves it on GitHub (`reviewDecision: 'APPROVED'`, already fetched with every PR snapshot).
|
|
23
|
+
- **MCP allowlist doctor check**: `loop doctor` validates the default-deny `mcp.allowTools` bridge wiring when
|
|
24
|
+
`mcp.enabled` — MCP stays adapter-only and read-only per ADR-0028, so this checks the allow/deny plumbing, not a
|
|
25
|
+
live connection to an MCP server.
|
|
26
|
+
- **Dynamic outcome progress**: the brief documents an optional `progress.json` convention
|
|
27
|
+
(`{"o1": "done", "o2": "in-progress"}`) a worker can write at its worktree root; `loop debrief` shows
|
|
28
|
+
`N/M outcome(s) done` per in-flight issue when present (`src/loop/progress.ts`, best-effort, never required).
|
|
29
|
+
- **Secret-shaped filename guardrail**: `delivery.secretFilePatterns` (default covers `.env`, `*.pem`, `*.key`,
|
|
30
|
+
`id_rsa`, `credentials.json`, …) extends the existing `selfEditPaths` hold — a PR touching a matching filename is
|
|
31
|
+
held, never reviewed or merged, in both the normal dispatch path and GitHub label intake.
|
|
32
|
+
|
|
33
|
+
## [0.9.0] - 2026-09-12
|
|
34
|
+
|
|
35
|
+
- **Failure-classification fix**: `classifyProviderFailure` now recognises real Claude/Codex/Grok usage-limit phrasing ("You've hit your session limit", "usage limit reached", "credit balance is too low", "spend limit reached", "temporarily limiting requests", "Overloaded") as `quota` instead of falling through to `other`, and `extractResetsAt` parses a relative (`resets in 3h`) or clock-time (`resets 10:40pm`) reset out of the message. A code-review exit is classified the same way, marking the reviewer's provider (not the review-CLI transport id) cooling down instead of retrying every tick. Root cause of a 2026-09-11/12 pilot bug: 19 unclassified `contract.failed` retries across 4 issues and 12 incomplete reviews over 7h with no cooldown ever recorded.
|
|
36
|
+
- **Auto-pause after repeated failures**: `resilience.maxConsecutiveFailures` (default 3) pauses a single issue after that many consecutive `contract.failed`/`worker.dispatch-failed` events — one deduplicated Linear comment, the `resilience.pausedLabel` (default `loop:paused`), and it is skipped locally until the label is removed or `ak-harness loop resume <issue>` runs. `resilience.stagePauseAfterRuns` does the same for a `loop stage tick|deliver` run that throws repeatedly, via `loop resume --stage tick|deliver` and a new `loop paused` listing.
|
|
37
|
+
- **Skills pinned into the worker brief**: `brief.skills` lists Markdown files (relative to `project.root`) embedded verbatim, sha256-digested, and truncated at `brief.maxSkillChars` in every worker brief's new "Skills (pinned)" section. A missing file fails the dispatch closed. The rendered brief is persisted to `<stateDir>/issues/<id>/brief.md`; `dispatch.json` records `briefDigest` and per-skill digests. A handoff never re-reads `brief.skills`, so editing a skill file after dispatch never affects an in-flight worker. `loop doctor` gained a `brief.skills` check.
|
|
38
|
+
- **Worktree setup command**: `project.setup.command` (argv, no shell) runs once in a freshly created worktree before the worker terminal opens (e.g. `pnpm install --frozen-lockfile`), bounded by `project.setup.timeoutSec` (reserved out of the tick budget). `project.setup.required` (default true) fails the dispatch — same cleanup and consecutive-failure accounting as any other dispatch failure — on a non-zero exit or timeout; set to false to only warn.
|
|
39
|
+
- **Reasoning effort per role**: `models.effort.<role>` (`low`\|`medium`\|`high`\|`xhigh`) is rendered via `providers.<id>.effortFlag` (e.g. codex `-c model_reasoning_effort={effort}`, grok `--reasoning-effort {effort}`) into `tui`/`headless`; a provider without `effortFlag` ignores it. `dispatch.json` and `loop retro`'s `dispatches.byProvider` record/group by `provider/model@effort`.
|
|
40
|
+
- **GitHub label intake**: `github.intakeLabel` (default `loop:review`; `null` disables it) makes `deliver` review and comment on any open PR carrying the label, even one the loop never dispatched (tracked as `pr-<n>`, no Linear issue involved). Every nudge lands as a PR comment instead of a terminal send; `github.reviewOnly` is a fixed schema guarantee — a clean review always ends held ("merge is human") with the label removed, never auto-merged.
|
|
41
|
+
- Fixed `scripts/verify-release-manifest.mjs`, which pinned the release version literal to `0.5.0` and would have failed every release since 0.6.0.
|
|
42
|
+
|
|
3
43
|
## [0.8.0] - 2026-09-12
|
|
4
44
|
|
|
5
45
|
- Worker **handoff**: when a dispatched worker is idle (or its terminal is gone) and its provider is unavailable (usage/cooldown), deliver relaunches another builder on the **same** Orca worktree + branch with a continuation brief (`renderHandoffBrief`). Lease stays; `dispatch.json` updates terminal/provider/model; `delivery.handoffs[]` + `worker.handed-off` event. Caps via `delivery.handoff.maxHandoffs` (default 2).
|