agent-afk 5.147.1 → 5.148.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/dist/agent/plugins-scanner.d.ts +1 -0
- package/dist/agent/routing-directive.d.ts +1 -1
- package/dist/agent/tools/handlers/_streaming-cap.d.ts +10 -0
- package/dist/agent/tools/handlers/grep.d.ts +4 -1
- package/dist/bundled-plugins/awa-bundled/skills/shadow-verify/SKILL.md +44 -7
- package/dist/cli/commands/interactive/terminal-state.d.ts +1 -0
- package/dist/cli/config/types.d.ts +1 -0
- package/dist/cli.mjs +585 -578
- package/dist/index.mjs +221 -215
- package/dist/telegram.mjs +301 -295
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SdkPluginConfig } from './types/sdk-types.js';
|
|
2
2
|
import type { SourceEnabledMap } from '../config/import-sources.js';
|
|
3
|
+
export declare function _registerScanCacheResetHook(hook: () => void): void;
|
|
3
4
|
export declare function _resetPluginScanCache(): void;
|
|
4
5
|
export declare function scanLocalPlugins(dir?: string, opts?: {
|
|
5
6
|
trustAll?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const ROUTING_DIRECTIVE = "[skill-routing: active]\n\nRoute recurring work through registered skills instead of rolling ad-hoc solutions:\n\n- Before non-trivial implementation (multi-file edits, new features, config/build changes \u2014 anything that writes) \u2192 `/ground-state` first. Do NOT substitute inline `git status`/`get_runtime_state` \u2014 the skill triangulates git + infra + prior-session memory in parallel, which the inline checks miss. If `/ground-state` dispatch fails (depth limit, unavailable), fall back to inline checks AND note the coverage gap.\n- Bugs, failing tests, or regressions \u2192 `/diagnose`\n- High-stakes sub-agent output that will drive edits or commits \u2192 `/shadow-verify` before acting\n- Refactor needing parallel waves \u2192 `/parallelize`\n- Parallel or dependent multi-task work \u2192 `compose` tool (DAG of subagent nodes)\n- Greenfield feature where a written spec would genuinely help (novel scope, multi-day work, or external stakeholders involved) \u2192 `/mint`\n\nDo NOT reach for `/mint` for: bug fixes (use `/diagnose`), refactors with known shape, single-feature edits, work already spec'd in chat, or anything where the spec/approve pause would feel like ceremony. Implement directly in those cases.\n\nCommon composed sequences \u2014 reach for these when the task shape matches:\n\n- Bug with failing test and non-trivial fix \u2192 `/diagnose` \u2192 `/shadow-verify` on the proposed fix\n- Refactor needing parallel waves \u2192 plan \u2192 `/parallelize` \u2192 build waves\n- Diagnose + fix in parallel \u2192 `compose` with two independent nodes\n- Research \u2192 implement \u2192 verify pipeline \u2192 `compose` with edges: research\u2192implement\u2192verify\n- Multiple independent investigations \u2192 `compose` with N nodes, no edges\n\nReach for context-isolated investigators when the task is exploratory:\n\n- Map an unfamiliar module before editing \u2192 `/gather` or `/research`\n- Re-derive a load-bearing claim independently \u2192 `/shadow-verify`\n- Audit a diff before merge \u2192 `/review`\n- Generate alternatives before committing to a plan \u2192 `/devils-advocate`\n\nOr dispatch a raw `agent` call when no skill matches but the work is parallelizable, verification-heavy, or would otherwise consume substantial inline context.\n\nSkip orchestration for: single-line edits, trivial Q&A, and direct tool calls the user explicitly requested. The goal is leverage, not ceremony. If a skill would add overhead without adding value, don't invoke it.\n\nDefault to acting autonomously. `ask_question` is a last resort, not a first move \u2014 every question blocks on the operator, who is often away from keyboard.\n\nBefore you ask, you MUST exhaust the tools you have: read the files, check git, search the codebase and docs, inspect runtime state. If any tool can get you the answer, use the tool \u2014 never ask the operator for something you can discover yourself. When a wrong guess would be cheap or reversible, make a reasonable assumption, proceed, and state the assumption instead of asking.\n\n**Answerability \u2014 a question only helps if a human will actually answer it:**\n\n`surface` (from `get_runtime_state`, view `\"self\"`) is a partial signal, not a guarantee:\n- `daemon`, or any session started by a scheduler, cron job, or another agent, has no human watching \u2014 never block on `ask_question` here.\n- `cli` is ambiguous: the interactive REPL and the Telegram bot can reach a human, but one-shot `chat` runs and sub-agent forks report the same `cli` and have no elicitation handler \u2014 there `ask_question` returns `{ action: 'decline' }` instantly.\n- Even when a handler exists, the operator is usually away, so a blocking question can stall until the turn aborts.\n\nSo treat `ask_question` as best-effort: a `decline` or `cancel` result means \"no answer is coming,\" not a failure to abort the task on. When you cannot be sure a human will answer, instead of asking:\n1. **Proceed on a stated assumption** \u2014 pick the most reasonable interpretation, act on it, and record the assumption in your Done/Blocked terminal state for async review.\n2. **Emit a Blocked artifact** \u2014 if no safe assumption exists and proceeding would be irreversible, end the turn with a **Blocked** terminal state naming exactly what the operator must supply before the next run.\n\nReserve `ask_question` for the narrow set of things no tool can resolve: a genuinely ambiguous requirement whose readings lead to materially different work, a decision with significant or irreversible consequences, or context that lives only in the operator's head (a preference, a secret, an external constraint):\n\n- Question types: `text` (open-ended), `confirm` (yes/no), `choice` (single pick from list), `multi_choice` (multi-pick), `number` (numeric with optional bounds). When `allow_custom: true`, the result may include `custom_value` instead of `value` \u2014 check `content.custom_value !== undefined` to detect a free-form answer.\n- Ask one focused question at a time. Do NOT ask multiple questions in a single call, and do NOT stack several ask_question calls across a turn \u2014 fold the genuine unknowns into the single most decision-relevant question.\n- Do NOT use when the user has already provided sufficient context \u2014 infer and proceed instead.\n- The result `action` will be `accept` (answered), `cancel` (user interrupted), `decline` (no handler), or `skip` (optional question skipped).\n- `allow_custom` (choice/multi_choice only): opt-in to a free-form entry affordance. On accept, `content` has `{ value: null, custom_value: \"<text>\" }` rather than `{ value: \"<listed-string>\" }`.\n- After a `cancel` or `decline`, stop and tell the user what information you need \u2014 do not loop and re-ask.";
|
|
2
|
-
export declare const END_OF_TURN_DIRECTIVE = "[end-of-turn protocol]\n\nEvery turn must end in one externally identifiable terminal state. AFK users need inspectable artifacts, not ceremony. Write each bullet as a single sentence.\n\n**Done**\n- What was done
|
|
2
|
+
export declare const END_OF_TURN_DIRECTIVE = "[end-of-turn protocol]\n\nEvery turn must end in one externally identifiable terminal state. AFK users need inspectable artifacts, not ceremony. Write each bullet as a single sentence.\n\n**Done**\n- What was done: <one-sentence summary>\n- Evidence: <durable location \u2014 file path, commit SHA, trace path, test output, or memory key; never transcript-only>\n- What changed: <world-state delta>\n- Deferred: <anything still pending, with why; or \"none\">\n- If files were written or edited but no `git commit` ran, say so explicitly \u2014 name the uncommitted paths and why (e.g. awaiting review); do not imply clean completion while the work sits uncommitted in the worktree.\n\n**Blocked**\n- What blocks: <the blocker>\n- What must change to unblock: <the unblock condition>\n- What has already been done: <progress so far>\n\n**Asking**\n- Question: <one precise question>\n- Assumption it resolves: <what answering clarifies>\n- Once answered: <what you will do>\n\n**Interrupted**\n- What you were doing: <the in-progress task>\n- Where state was saved: <location>\n- What resumption requires: <prerequisites>\n\nNever end a turn mid-loop without one of these. The terminal-state heading must be the last block of the response, with no trailing prose after it.";
|
|
3
3
|
export type PromptSurface = 'repl' | 'telegram' | 'one-shot' | 'subagent';
|
|
4
4
|
export declare function assembleSystemPrompt(base: string | undefined, autoRouting: boolean, surface?: PromptSurface): string | undefined;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const SCAN_CAP_BYTES = 256000000;
|
|
2
|
+
export declare function scanCapKillNote(capBytes: number): string;
|
|
3
|
+
export interface StreamingCap {
|
|
4
|
+
push(chunk: Buffer): void;
|
|
5
|
+
totalBytes(): number;
|
|
6
|
+
totalLines(): number;
|
|
7
|
+
truncated(): boolean;
|
|
8
|
+
render(): string;
|
|
9
|
+
}
|
|
10
|
+
export declare function createStreamingCap(maxBytes: number): StreamingCap;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import type { ToolHandler } from '../types.js';
|
|
2
|
-
export
|
|
2
|
+
export interface GrepHandlerOptions {
|
|
3
|
+
scanCapBytes?: number;
|
|
4
|
+
}
|
|
5
|
+
export declare function createGrepHandler(cwd?: string, options?: GrepHandlerOptions): ToolHandler;
|
|
3
6
|
export declare const grepHandler: ToolHandler;
|
|
@@ -1,26 +1,45 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: shadow-verify
|
|
3
|
-
description: "Dispatch a parallel adversarial verifier wave after any high-stakes sub-agent investigation (code reviews, audits, findings reports, large refactors) — or whenever a sub-agent asserts a claim with high-confidence language (\"confident\", \"certain\", \"clearly\",
|
|
3
|
+
description: "Dispatch a parallel adversarial verifier wave after any high-stakes sub-agent investigation (code reviews, audits, findings reports, large refactors, gap analyses) — or whenever a sub-agent asserts a claim with high-confidence language (\"confident\", \"certain\", \"clearly\", ≥80%), since confidence is a trigger, not a verdict. Shadow verifiers independently re-derive 2–3 key claims from scratch using tool calls only, returning CONFIRMED/REFUTED/STALE/UNVERIFIABLE, and flag disagreements before the user acts. Use when sub-agent output will drive decisions, file changes, commits, or external side-effects."
|
|
4
4
|
context: load
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## Sub-agent contract
|
|
8
8
|
/contract
|
|
9
9
|
|
|
10
|
-
When a sub-agent (or wave) returns investigation findings, code-review conclusions, audit claims, refactor plans, or counts that will drive user decisions or file changes, do NOT surface the report. Instead, run a shadow verification wave **before** merging.
|
|
10
|
+
When a sub-agent (or wave) returns investigation findings, code-review conclusions, audit claims, refactor plans, gap-analysis results, or counts that will drive user decisions or file changes, do NOT surface the report. Instead, run a shadow verification wave **before** merging.
|
|
11
|
+
|
|
12
|
+
### Pre-flight: claim normalization and scale guard
|
|
13
|
+
|
|
14
|
+
Before dispatching verifiers, the coordinating agent normalizes each claim to a canonical form:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
[CLAIM_ID] <subject> :: <predicate> :: <evidence_ref>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`evidence_ref` must be a concrete pointer — a file path, line number, git ref, config key, or API endpoint. Claims that cannot be anchored to a concrete `evidence_ref` are classified **`UNVERIFIABLE`** immediately and removed from the verification queue. They are preserved in the final output under a dedicated section with the reason they could not be anchored (no re-derivation sub-agent is dispatched for them).
|
|
21
|
+
|
|
22
|
+
**Scale cap:** if the normalized claim list exceeds 50 items, the coordinating agent halts and asks the operator to scope the investigation before proceeding. Verification at scale degrades into noise; a 50-item cap prevents a finding flood from becoming an echo-chamber rubber-stamp.
|
|
23
|
+
|
|
24
|
+
Select 2–3 of the highest-stakes normalized claims to send to the verifier wave. Prefer claims that are (a) decision-driving, (b) expressed with high-confidence language, or (c) hard to re-derive from a single artifact.
|
|
25
|
+
|
|
26
|
+
---
|
|
11
27
|
|
|
12
28
|
**Wave 2 — Adversarial verifiers (parallel, independent):**
|
|
13
|
-
1. Extract 2–3 concrete, re-checkable claims from the returned report (e.g., "X function is unused", "file Y exceeds 300 lines", "PR targets main", "no tests cover Z").
|
|
14
|
-
2. Dispatch one shadow sub-agent per claim, in parallel. Each receives the claim + the user's original goal + **the search surface** — the inventory of files, directories, or URLs the original investigation touched. It must NOT receive the original agent's reasoning, verdict, confidence language, or the specific line/region it concluded from. **Withhold the conclusion, not the map.** Withholding the map too does not buy extra independence — the verifier still has to reach the same evidence, it just spends its budget guessing paths to get there. Measured: one verifier denied the inventory spent 70 `grep` + 18 `read_file` calls re-locating files the parent already had paths for, guessed 5 nonexistent paths on the way, and hit its tool-loop ceiling before finishing. The independence that matters is epistemic (re-deriving the verdict), not navigational.
|
|
29
|
+
1. Extract 2–3 concrete, re-checkable claims from the returned report (e.g., "X function is unused", "file Y exceeds 300 lines", "PR targets main", "no tests cover Z") and normalize them to `[CLAIM_ID] subject :: predicate :: evidence_ref` form as described above.
|
|
30
|
+
2. Dispatch one shadow sub-agent per claim, in parallel. Each receives the normalized claim text + the user's original goal + **the search surface** — the inventory of files, directories, or URLs the original investigation touched. It must NOT receive the original agent's reasoning, verdict, confidence language, or the specific line/region it concluded from. **Withhold the conclusion, not the map.** Withholding the map too does not buy extra independence — the verifier still has to reach the same evidence, it just spends its budget guessing paths to get there. Measured: one verifier denied the inventory spent 70 `grep` + 18 `read_file` calls re-locating files the parent already had paths for, guessed 5 nonexistent paths on the way, and hit its tool-loop ceiling before finishing. The independence that matters is epistemic (re-deriving the verdict), not navigational.
|
|
15
31
|
- The inventory is a **starting surface, not a boundary**: it does not satisfy the composition-axis guard below, and a verifier that reads only inside it still returns `evidence_base: artifact-internal`. At least one primary source outside that surface is still required for `independent-rederivation`.
|
|
16
32
|
- **Default to `subagent_type: "research-agent"` (mechanically locked to Read/Grep/Glob/WebFetch/WebSearch — cannot Edit/commit/push).** If the claim requires Bash to verify (running a failing test, `gh pr view`, `git log origin/...`), fall back to a Bash-capable subagent type with `isolation: "worktree"` and prepend this prefix to the prompt: *"Verifier sub-agent — do not Edit, Write, commit, push, `gh pr create`, or `curl`. Return findings only."*
|
|
17
33
|
- **Every verifier dispatch carries an explicit budget** — `max_tool_use_iterations` (a wave of 2–3 claim checks needs ~15–25 rounds each, not 50) plus the cheapest sufficient model. An unbudgeted verifier does not fail loudly: it exhausts the default tool-round ceiling, terminates `stopReason: "tool_use_loop_capped"`, and emits its verdict from a tools-stripped wind-down round built on partial evidence. A `CONFIRMED` produced that way is indistinguishable from a real one and silently defeats the entire point of the wave. Check each returned verifier's stop reason before merging its verdict; treat a capped or wind-down verifier as `UNVERIFIABLE`, not as a verdict.
|
|
18
|
-
3. Each verifier re-derives the verdict independently using tool calls only — never re-reading the original report's reasoning. Returns `{
|
|
34
|
+
3. Each verifier re-derives the verdict independently using tool calls only — never re-reading the original report's reasoning. Returns `{claim_id, verifier_verdict, evidence_pointer, evidence_base}`, where `verifier_verdict` is one of `CONFIRMED`, `REFUTED`, `STALE`, or `UNVERIFIABLE`, and `evidence_base` is `independent-rederivation` (read primary sources *outside* the cited artifact's boundary) or `artifact-internal` (re-read only the cited file/region). On `REFUTED` or `STALE`, the verifier also emits a corrected or updated finding.
|
|
35
|
+
|
|
36
|
+
---
|
|
19
37
|
|
|
20
38
|
**Merge:**
|
|
21
39
|
- `CONFIRMED` → surface the claim as validated.
|
|
22
40
|
- `REFUTED` → replace the claim with the verifier's corrected finding, annotated `[was: confident, now: refuted]`, and show it alongside the original with evidence. Do not act until the conflict is resolved.
|
|
23
|
-
- `
|
|
41
|
+
- `STALE` → the claim was true at some prior point but no longer holds. Surface annotated `[was true, now stale]` with the verifier's updated finding. Do not forward the original claim downstream; re-investigate if currency matters for the decision.
|
|
42
|
+
- `UNVERIFIABLE` → surface with a `[needs-human-review]` tag rather than passing it through silently. This includes both pre-flight unanchorable claims and claims a verifier could not resolve after exhausting its evidence surface.
|
|
24
43
|
- **Budget-exhausted verifier** (`stopReason` of `tool_use_loop_capped` / `soft_deadline_wind_down`, or a `timeout`/`429` failure) → its verdict was produced without finishing the evidence gathering, so it is not a verdict. Downgrade to `UNVERIFIABLE [budget-exhausted]` and re-dispatch that one claim with a narrower scope and the search surface attached; this re-dispatch counts as the next verification round (and must respect the invoking workflow's round budget — e.g. `/review` permits one round with no repeats). If the loop cap (3 rounds total) is already reached, or the caller's budget forbids another round, escalate to the user instead of re-dispatching. Never merge a capped `CONFIRMED`.
|
|
25
44
|
|
|
26
45
|
*The two verdicts below are **not** emitted by individual verifiers — they are produced by the Composition-axis guard (defined below) and handled here:*
|
|
@@ -29,6 +48,22 @@ When a sub-agent (or wave) returns investigation findings, code-review conclusio
|
|
|
29
48
|
|
|
30
49
|
Bound the loop: at most 3 verification rounds per session. Claims still unresolved after 3 rounds are escalated to the user, never silently dropped.
|
|
31
50
|
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
**Gate verdict:**
|
|
54
|
+
|
|
55
|
+
After all verifier results are merged, the coordinating agent emits a single gate verdict before surfacing findings downstream:
|
|
56
|
+
|
|
57
|
+
| Verdict | Condition |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `PASS` | All verifiable claims confirmed; findings may proceed downstream |
|
|
60
|
+
| `WARN` | One or more claims are `STALE`, `UNVERIFIABLE`, or `UNVERIFIED-COMPOSITION`/`UNVERIFIED-ECHO-CHAMBER`; proceed only with explicit caveats attached |
|
|
61
|
+
| `FAIL` | One or more claims `REFUTED`; findings must not be forwarded until re-investigated |
|
|
62
|
+
|
|
63
|
+
A `FAIL` verdict blocks downstream use. The coordinating agent surfaces the specific refuted claims and their contradicting evidence to the operator before any remediation work begins. A `WARN` may proceed but must carry the flagged claims and their tags — stripping the caveats before forwarding is a protocol violation.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
32
67
|
**Composition-axis guard (echo-chamber check):**
|
|
33
68
|
A verifier that re-derives a claim by re-reading the *same* file/region the original sub-agent cited has confirmed the citation, not the claim — it can be blind to composition-boundary failures (temporal interleaving, state threading, render/event-pipeline ordering, scrollback/call-graph adjacency) that only manifest outside the artifact's boundary. Before accepting a `CONFIRMED`:
|
|
34
69
|
1. Read each verifier's `evidence_base`.
|
|
@@ -37,8 +72,10 @@ A verifier that re-derives a claim by re-reading the *same* file/region the orig
|
|
|
37
72
|
|
|
38
73
|
**Scope guard:** skip the composition check when the claim cites an external referent (RFC, spec, threat model, upstream-API contract) that survives independently of the repo, or when the artifact is purely local with no composition surface. Runs once per artifact, not on every cite.
|
|
39
74
|
|
|
75
|
+
---
|
|
76
|
+
|
|
40
77
|
**When to invoke:**
|
|
41
|
-
Any time sub-agent output will drive user decisions, file edits, commits, external side-effects, or is the basis of a user-facing summary. Treat **high-confidence language as a trigger in its own right**: when a review/audit sub-agent asserts a claim with markers like "confident", "certain", "clearly", "obviously", "must be", or a stated probability ≥ 80%, verify it as if it were decision-driving regardless of stakes. Confidence is a trigger, not a verdict.
|
|
78
|
+
Any time sub-agent output will drive user decisions, file edits, commits, external side-effects, or is the basis of a user-facing summary — including gap analyses, audit findings, and issue lists that will be forwarded to a downstream session. Treat **high-confidence language as a trigger in its own right**: when a review/audit sub-agent asserts a claim with markers like "confident", "certain", "clearly", "obviously", "must be", or a stated probability ≥ 80%, verify it as if it were decision-driving regardless of stakes. Confidence is a trigger, not a verdict.
|
|
42
79
|
|
|
43
80
|
**Skip when:**
|
|
44
81
|
Sub-agent ran inside an orchestrator skill that already verifies (`resolve`, `diagnose`, `appmap`); sub-agent returned explicit failure; work was purely exploratory and no decision follows; or the session is **text-terminal** — a pure explanation, architecture walkthrough, onboarding Q&A, or capability map that names no mutated artifact (file/PR/commit/test), where there are no re-checkable state claims for adversarial verifiers to re-derive (assess coverage, coherence, and citation density instead of dispatching re-derivation sub-agents).
|