agestra 4.13.1 → 4.13.2

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.
@@ -12,7 +12,7 @@
12
12
  "name": "agestra",
13
13
  "source": "./",
14
14
  "description": "Orchestrate Ollama, Gemini, and Codex for multi-AI debates, code review, and cross-validation",
15
- "version": "4.13.1",
15
+ "version": "4.13.2",
16
16
  "author": {
17
17
  "name": "mua-vtuber"
18
18
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agestra",
3
- "version": "4.13.1",
3
+ "version": "4.13.2",
4
4
  "description": "Claude Code plugin — orchestrate Ollama, Gemini, and Codex for multi-AI debates, code review, and cross-validation",
5
5
  "mcpServers": {
6
6
  "agestra": {
package/README.md CHANGED
@@ -92,7 +92,7 @@ All three hosts drive the same MCP server and shared workflow specs from `comman
92
92
  | `/agestra design [subject]` | Explore architecture and design trade-offs before implementation |
93
93
  | `/agestra implement [task]` | Execute implementation through Leader-host-only or suggested AI distribution mode |
94
94
 
95
- When external providers are available, review, QA, security, design, and idea workflows route through the team lead for multi-AI cross-validation. When no providers are detected, the current leader host works with its local specialist agent automatically. Implementation requests first classify the task and can ask whether to propose an AI task distribution.
95
+ When external providers are available, review, QA, security, design, and idea workflows route through the team lead for multi-AI cross-validation. For QA, the team lead forms a QA Brigade from the configured provider set by default, then hands it to the moderator engine's existing `ITEM-*` / JSON stance ledger: host QA collects executable evidence, providers take distinct verification lenses, candidate findings are challenged before inclusion, and the synthesis preserves consensus plus dissent. E2E/browser/runtime execution remains host-owned, and external providers review the resulting evidence. When no providers are detected, the current leader host works with its local specialist agent automatically. Implementation requests first classify the task and can ask whether to propose an AI task distribution.
96
96
 
97
97
  ## Agents
98
98
 
@@ -154,10 +154,10 @@ Turborepo monorepo with 8 packages:
154
154
 
155
155
  ### Work Modes
156
156
 
157
- **Text work** (review, QA, security, design, idea): providers available → consensus debate mode; no providers → Leader-host only
157
+ **Text work** (review, QA, security, design, idea): providers available → consensus debate mode; no providers → Leader-host only. For QA, the team lead runs a QA Brigade by default while E2E/runtime checks stay host-owned.
158
158
 
159
159
  **Implementation work** (team-lead orchestration):
160
- - **Leader-host only** — `agestra-implementer` applies scoped code changes; reviewer/QA verify.
160
+ - **Leader-host only** — `agestra-implementer` applies scoped code changes; the team lead still routes QA through the QA Brigade by default, with host-only review/QA available on request.
161
161
  - **Suggested AI distribution** — the team lead proposes a routing table, asks for approval, then dispatches Codex/Gemini CLI workers for suitable code edits and Ollama for simple/repetitive proposal work.
162
162
 
163
163
  ---
@@ -1,18 +1,29 @@
1
1
  ---
2
2
  name: agestra-qa
3
3
  description: |
4
- Host-local document-first QA verifier. Validates implementation against docs/plans design
4
+ Host-local document-first QA evidence verifier. Validates implementation against docs/plans design
5
5
  contracts, Implementation Progress evidence, build/test results, runtime behavior, basic safety
6
6
  hygiene, and optional E2E/browser flows. Writes QA report artifacts under docs/reports/qa/.
7
- Does NOT modify source code or add persistent test files. For multi-AI joint QA, route through
8
- agestra-team-lead.
7
+ Does NOT modify source code or add persistent test files. When configured external providers are
8
+ available, normal /agestra qa requests should route through agestra-team-lead for the QA Brigade;
9
+ this agent supplies the host-owned evidence pass, especially for build/test and
10
+ E2E/runtime checks.
9
11
 
10
12
  <example>
11
- Context: Implementation is done and needs single-host verification
13
+ Context: Implementation is done and configured providers are available
12
14
  user: "구현 다 했는데 QA 돌려줘"
15
+ assistant: "I'll use the agestra-team-lead agent to run the QA Brigade, with host-owned runtime evidence."
16
+ <commentary>
17
+ Default QA with providers — team-lead forms the QA Brigade, runs host QA evidence collection, then coordinates provider verdicts.
18
+ </commentary>
19
+ </example>
20
+
21
+ <example>
22
+ Context: Implementation is done and needs explicit single-host verification
23
+ user: "호스트만 써서 QA 돌려줘"
13
24
  assistant: "I'll use the agestra-qa agent to verify the implementation against the design."
14
25
  <commentary>
15
- Single-host post-implementation verification — QA checks the design document, progress ledger,
26
+ Explicit host-only post-implementation verification — QA checks the design document, progress ledger,
16
27
  build/test commands, and selected runtime flows.
17
28
  </commentary>
18
29
  </example>
@@ -22,8 +33,9 @@ description: |
22
33
  user: "실제 화면 흐름까지 QA 해줘"
23
34
  assistant: "I'll use the agestra-qa agent and ask whether to run the full E2E path."
24
35
  <commentary>
25
- QA explains E2E cost, then verifies existing E2E tests or temporary browser flows. Persistent
26
- test-file creation or maintenance is handed to agestra-e2e-writer after approval.
36
+ QA explains E2E cost, then the host verifies existing E2E tests or temporary browser flows. Persistent
37
+ test-file creation or maintenance is handed to agestra-e2e-writer after approval. External providers
38
+ may review the resulting artifacts through team-lead, but do not run E2E/browser flows themselves.
27
39
  </commentary>
28
40
  </example>
29
41
 
@@ -32,8 +44,8 @@ description: |
32
44
  user: "코덱스랑 제미니로 같이 검증해줘"
33
45
  assistant: "I'll use the agestra-team-lead agent to run a multi-AI structured QA debate."
34
46
  <commentary>
35
- Multi-AI verification — must go through team-lead which runs structured debate (mode:review)
36
- with external providers cross-validating. Do NOT call agestra-qa directly here.
47
+ Multi-AI verification — must go through team-lead which forms the QA Brigade and runs structured debate (mode:review)
48
+ with external providers cross-validating host evidence. Do NOT call agestra-qa directly here.
37
49
  </commentary>
38
50
  </example>
39
51
  model: opus
@@ -100,13 +100,14 @@ If invoked with **Domain: review**, do not enter implementation decomposition, w
100
100
 
101
101
  If invoked with **Domain: security**, do not enter implementation decomposition, worker routing, or code-changing phases. Execute the structured security workflow in `commands/security.md`, then report security findings, tool-assisted checks run/skipped/declined/unavailable, report artifact path, residual risk, and SECURITY PASS / PASS WITH HARDENING / SECURITY BLOCK. Security must not run destructive exploit tests, and must not install tools or run heavyweight/networked scans without explicit user approval.
102
102
 
103
- If invoked with **Domain: qa** or **Domain: implement, Submode: qa-only**, skip Phase 2 (Task Design), Phase 3 (Parallel Execution), and Phase 4 (Result Inspection) entirely — there is no code to write. Instead:
103
+ If invoked with **Domain: qa** or **Domain: implement, Submode: qa-only**, skip Phase 2 (Task Design), Phase 3 (Parallel Execution), and Phase 4 (Result Inspection) entirely — there is no product code to write. Instead:
104
104
 
105
105
  1. Run Phase 1 (Situation Assessment) to confirm available providers and the design document scope.
106
106
  2. Preserve the QA depth from the handoff packet: Standard QA / Full QA with E2E / Decide automatically.
107
- 3. Jump directly to verification:
108
- - **Leader-host-only mode** Phase 5 (QA Cycle): spawn `agestra-qa` against the existing changes, classify failures, report verdict. No QA Fix Loop unless the user explicitly requests follow-up fixes.
109
- - **Multi-AI mode** Phase 5M (Structured Debate) with `mode: "review"` and the QA-oriented `topic` framing (e.g. "spec-compliance verification of {scope}"). Participants: host `agestra-qa` + external review-capable providers (excluding `ollama`). Treat the structured debate as cross-validation: each participant produces an independent QA verdict, then the JSON consensus ledger merges into a final PASS / CONDITIONAL / FAIL.
107
+ 3. Choose QA verification routing independently from implementation routing:
108
+ - If the user explicitly requested host-only QA, or no configured external providers are available, run Phase 5 (Host QA Evidence Pass): spawn `agestra-qa` against the existing changes, classify failures, and report verdict. No QA Fix Loop unless the user explicitly requests follow-up fixes.
109
+ - Otherwise, run Phase 5M (QA Brigade) by default. Start with host-owned `agestra-qa` evidence collection, then hand off to the moderator engine via `agent_debate_structured`. The moderator engine runs the configured and available review-capable providers plus the host QA participant through the existing `ITEM-*` / JSON stance ledger flow. Give each participant an explicit QA lens and require independent PASS / CONDITIONAL / FAIL recommendations in their source material. Treat the structured debate as a brigade cross-check: every participant reviews the design, code, diff, host evidence, and peer findings; the JSON consensus ledger merges consensus and preserves dissent.
110
+ - E2E/runtime execution is host-owned only. External providers may review the host QA report, command output, screenshots, traces, and E2E findings, but must not run browser/dev-server flows or create persistent E2E files directly.
110
111
  4. Skip Phase 6 (Post-implementation Review) — that's the reviewer's territory, not QA-only.
111
112
  5. Phase 7 report: surface QA depth, E2E status, QA verdict, spec-to-code mapping summary, classified failures (`BUILD_ERROR` / `DESIGN_GAP` / `PROGRESS_MISMATCH` / `INTEGRATION_BREAK` / `TEST_FAILURE` / `E2E_FAILURE` / `SAFETY_HYGIENE_RISK`), any `E2E_TEST_WORK_REQUEST`, and the synthesis path (multi-AI) or QA agent report path (host-local).
112
113
 
@@ -154,7 +155,7 @@ Decompose the work into independent, assignable tasks:
154
155
 
155
156
  | Option | Description |
156
157
  |--------|-------------|
157
- | **Leader-host only** | The current host uses `agestra-implementer` and specialist agents/prompts; no external coding workers |
158
+ | **Leader-host only** | The current host uses `agestra-implementer` and specialist agents/prompts; no external coding workers. QA routing still follows the configured-provider default unless host-only QA is requested |
158
159
  | **Multi-AI** | CLI AIs work autonomously when suitable, Ollama handles simple proposal work, host-local agents handle scoped implementation/review/QA |
159
160
 
160
161
  If no external providers available: skip selection, proceed with Leader-host only.
@@ -278,12 +279,12 @@ After each task completes:
278
279
  - **Autonomous:** Record the review evidence in your status update (files, design alignment notes), then call `agent_changes_accept`. Escalate to the user instead of auto-accepting when the diff exceeds the worker's stated scope, adds unrequested files, or touches a file flagged as high-risk in Phase 2.
279
280
  - For rejected CLI worker tasks: call `agent_changes_reject` with reason
280
281
  - Proceed to verification:
281
- - **Multi-AI mode** Phase 5M (Structured Debate) replaces the separate QA and post-implementation review phases.
282
- - **Leader-host-only mode** → Phase 5 (QA Cycle) followed by Phase 6 (Post-implementation Review).
282
+ - If configured external providers are available and the user did not explicitly request host-only QA → Phase 5M (QA Brigade).
283
+ - If no configured external providers are available, or the user explicitly requested host-only QA → Phase 5 (Host QA Evidence Pass) followed by Phase 6 (Post-implementation Review).
283
284
 
284
- ### Phase 5: QA Cycle (Leader-host-only mode)
285
+ ### Phase 5: Host QA Evidence Pass
285
286
 
286
- > Used when Work Mode in Phase 2 was **Leader-host only**. In Multi-AI mode, skip to Phase 5M.
287
+ > Used when no configured external providers are available, the user explicitly requested host-only QA, or Phase 5M needs host-owned executable evidence before provider cross-validation.
287
288
 
288
289
  Run formal verification with automatic fix loop:
289
290
 
@@ -324,9 +325,59 @@ Run formal verification with automatic fix loop:
324
325
  - After the tests exist or are updated, re-run `agestra-qa`.
325
326
  - If declined, keep the QA verdict/residual risk honest and do not mark E2E as covered.
326
327
 
327
- ### Phase 5M: Structured Debate (Multi-AI mode)
328
+ ### Phase 5M: QA Brigade
328
329
 
329
- > Used when Work Mode in Phase 2 was **Multi-AI**. Replaces Phase 5 (QA) and Phase 6 (Post-implementation Review) in a single coordinated cross-AI review. In Leader-host-only mode, skip this phase.
330
+ > Used for QA whenever configured external providers are available, unless the user explicitly requested host-only QA. This is the default for `/agestra qa` and post-implementation QA. It can also be used after Leader-host-only implementation because QA routing is separate from code-writing routing.
331
+
332
+ The QA Brigade should feel like the review workflow's full formation, not a lightweight second opinion. Build a broad verification team and make the differences between providers useful.
333
+
334
+ For QA topics, collect host-owned executable evidence first:
335
+
336
+ 1. Spawn `agestra-qa` with the design document, change scope, QA depth, and report artifact expectation under `docs/reports/qa/`.
337
+ 2. If QA depth includes E2E/runtime verification, only the host QA path runs browser/dev-server flows, screenshots, traces, or existing E2E commands.
338
+ 3. If `agestra-qa` returns `E2E_TEST_WORK_REQUEST`, pause for user approval before routing that packet to `agestra-e2e-writer`; do not ask external providers to create or repair persistent E2E tests.
339
+ 4. Use the host QA report path, command output, screenshots/traces, and E2E findings as evidence for provider cross-validation.
340
+
341
+ #### 5M.0 Brigade formation
342
+
343
+ Build the QA Brigade handoff before starting the moderator debate:
344
+
345
+ | Brigade member | Role |
346
+ |---|---|
347
+ | Host `agestra-qa` / structured `claude-qa` participant | Evidence lead and debate participant: design/progress audit, build/test commands, host-owned E2E/runtime evidence, report artifact, and JSON stance turns |
348
+ | Configured review-capable providers | Independent QA judges: each reviews the design, diff/code, host QA evidence, and peer claims |
349
+ | `agestra-reviewer` lens | Optional support lens for production readiness, UX/product feel, maintainability, and test adequacy when those affect acceptability; do not turn QA into a general review |
350
+ | `agestra-security` lens | Optional support lens for basic safety hygiene escalation when QA finds secrets, auth, file, command, network, or permission risk; use `/agestra security` for a dedicated audit |
351
+ | `agestra-e2e-writer` | Not a brigade reviewer. Use only after an approved `E2E_TEST_WORK_REQUEST` for persistent E2E test work |
352
+
353
+ Default participant policy:
354
+ - Include every configured and available review-capable provider by default, not only the "best" one. Use `trace_summary` to assign lenses and order attention, not to shrink the brigade unless a provider is unavailable, explicitly excluded, or clearly unqualified for the requested lens.
355
+ - Exclude `ollama` by default unless the user explicitly requested it for lightweight cross-checking.
356
+ - Keep the host QA participant in the flow even when external providers are present, because executable evidence, E2E/runtime observation, and local command output are host-owned. In structured debate, this is the `claude-qa` compatibility participant when auto-injected or explicitly listed.
357
+ - Assign distinct lenses so the output is not three copies of the same review. Suggested lenses: spec-to-code compliance, progress-table truthfulness, integration/regression risk, edge/error states, test adequacy, safety hygiene, and E2E artifact interpretation.
358
+ - Each brigade member must issue an independent PASS / CONDITIONAL PASS / FAIL recommendation with evidence and confidence in its individual source material. Disagreement is useful; preserve minority reports in the final synthesis.
359
+
360
+ #### 5M.0a QA mapping onto the existing JSON ledger
361
+
362
+ Do not invent a separate QA adjudication schema. Use the moderator's existing structured-debate contract.
363
+
364
+ Each candidate QA finding must become a normal consensus `ITEM-*` with source references. Participants vote through the existing JSON stance contract:
365
+
366
+ | Stance | QA meaning |
367
+ |---|---|
368
+ | `agree` | Include this finding as a QA issue; the evidence supports it and the severity/scope are acceptable |
369
+ | `disagree` | Do not include this finding: false positive, over-severe, duplicate, out-of-scope, already covered, or evidence is insufficient |
370
+ | `revise` | The issue is real, but the claim, severity, scope, wording, or fix direction must change; include `proposedItem` |
371
+ | `opinion` | The item requires a product/design/leader judgment rather than a QA fact decision |
372
+
373
+ Ledger interpretation:
374
+ - `accepted` means all active participants agree; only accepted blocking/conditional QA items can drive the final FAIL / CONDITIONAL PASS.
375
+ - `excluded` means all active participants disagree; do not include it in the final QA issue list except as a brief overruled/minority note when useful.
376
+ - `superseded` means the moderator accepted a revision or merge into another item; report the canonical item, not both duplicates.
377
+ - `needs_opinion`, `unresolved`, and `no_response` mean the item is still open. Continue rounds when useful; if escalated to the leader, report it as open/dissenting rather than pretending consensus.
378
+ - Evidence-insufficient findings should normally receive `disagree`, not `opinion`. Use `opinion` only for genuine product/design judgment calls.
379
+ - The moderator handles duplicate/merge/superseded state in the ledger. Participants may point out duplication in comments or propose a `revise`, but they do not manually merge markdown.
380
+ - The leader does not decide item inclusion by hand. The leader inspects the JSON ledger and chooses approve / continue / reject at the approval gate.
330
381
 
331
382
  Run the structured-debate MCP flow. This is a **background lifecycle**: `agent_debate_structured` creates a durable session record immediately and returns `status: running`; the leader polls `agent_debate_status` until the moderator parks the session in `ready-for-approval`, `escalated`, or `error`. The moderator does NOT write the synthesis file on its own — approval must be explicit.
332
383
 
@@ -334,11 +385,11 @@ Run the structured-debate MCP flow. This is a **background lifecycle**: `agent_d
334
385
 
335
386
  Call `agent_debate_structured` with:
336
387
 
337
- - `topic` — short slug (used in file names under `.agestra/workspace/`).
388
+ - `topic` — short slug (used in file names under `.agestra/workspace/`), prefixed or framed as QA Brigade when useful.
338
389
  - `mode` — `"review"` for QA/review/security consensus, `"idea"` for exploratory design or option discovery.
339
- - `scope` — concrete framing: file list, task description, or the design doc path.
340
- - `participants` — the provider/agent IDs the user specified at Work Mode selection, or the qualified set from `trace_summary`.
341
- - `source_documents` — optional pre-created individual documents, each as `{ "document_id": "...", "provider": "..." }`.
390
+ - `scope` — concrete framing: file list, task description, design doc path, changed files, and host QA report/evidence path.
391
+ - `participants` — the provider/agent IDs the user specified, or all configured and available review-capable providers from `provider_list`, plus the host QA participant (`claude-qa` compatibility ID) through auto-injection or explicit listing. For QA, use `trace_summary` for lens assignment rather than narrowing by default. Exclude `ollama` unless explicitly requested for lightweight cross-checking.
392
+ - `source_documents` — optional pre-created individual documents, each as `{ "document_id": "...", "provider": "..." }`. For QA, pass the host QA report/evidence packet as source material for the matching host QA participant. The `provider` value must be present in `participants`.
342
393
  - `auto_inject_specialists` — default `true`. When true, the moderator auto-adds host reviewer/QA/security specialists on top of `participants` based on topic heuristics (currently exposed as `claude-reviewer`, `claude-qa`, and/or `claude-security` for compatibility). When the user wants verbatim participants only, pass `false`.
343
394
  - `exclude_participants` — participant IDs to never include, applied regardless of `auto_inject_specialists`. Use this when the user explicitly wants a provider (including Ollama — there is no automatic Ollama filter anymore) kept out.
344
395
  - `leader` — omit unless you need to override the session-context leader.
@@ -370,11 +421,20 @@ Before deciding, read the on-disk outputs — the debate writes three folders un
370
421
 
371
422
  Use `Read` / `Grep` against these paths plus the in-result snapshot to judge whether the debate outcome matches the design.
372
423
 
424
+ For QA Brigade sessions, inspect whether the synthesis contains:
425
+ - Participant list and assigned lenses.
426
+ - Independent verdicts from each participant.
427
+ - `ITEM-*` ledger status summary: accepted, excluded, superseded, needs_opinion, unresolved, and no_response items.
428
+ - Consensus verdict and confidence.
429
+ - Dissenting findings or minority concerns.
430
+ - Evidence mapping back to design requirements, code locations, commands, reports, screenshots, or traces.
431
+ - Clear distinction between QA-blocking failures, conditional concerns, and general review suggestions.
432
+
373
433
  #### 5M.4 Finalize (leader decision)
374
434
 
375
435
  Pick exactly one of the three follow-up tools, based on inspection:
376
436
 
377
- 1. **Accept the outcome** → call `agent_debate_approve` with `session_id` and an optional `leader_note` (appended to the synthesis footer under "Leader approval notes"). The moderator writes the synthesis markdown, updates the session record to `approved`, and returns `synthesisDocPath`. Proceed to Phase 7 and relay the path to the user.
437
+ 1. **Accept the outcome** → call `agent_debate_approve` with `session_id` and an optional `leader_note` (appended to the synthesis footer under "Leader approval notes"). The moderator writes the synthesis markdown, updates the session record to `approved`, and returns `synthesisDocPath`. If this is QA-only, proceed to Phase 7. If this is an implementation flow and the QA verdict is PASS or CONDITIONAL PASS, proceed to Phase 6 unless the debate explicitly included the post-implementation review lens. If this is an implementation flow and the QA verdict is FAIL, return to Phase 3 with targeted fixes or escalate to the user instead of claiming completion.
378
438
  2. **Need more deliberation** → call `agent_debate_continue` with `session_id` and `additional_rounds` (`3`, `5`, or `10` only). The handler returns `status: running`; poll `agent_debate_status` again until it reaches the approval gate. Use this when the debate was close but unresolved, or when `escalated` came too early.
379
439
  3. **Reject the outcome** → call `agent_debate_reject` with `session_id` and a `reason` (captured in the transcript footer). Optionally set `spawn_issue: true` to write a lightweight issue branch document into `individual/` listing non-accepted proposals for later handling. No synthesis is produced. The debate is closed.
380
440
 
@@ -382,9 +442,9 @@ All three tools are idempotent on terminal states — re-calling returns the cac
382
442
 
383
443
  When the session is `escalated`, explain the situation to the user in supervised mode before choosing `continue` vs `reject`. In autonomous mode, prefer `continue` with `additional_rounds: 5` once; if it escalates again, `reject` with a clear reason and fall back to targeted fix tasks in Phase 3.
384
444
 
385
- ### Phase 6: Post-implementation Review (Leader-host-only mode)
445
+ ### Phase 6: Post-implementation Review
386
446
 
387
- > Used when Work Mode in Phase 2 was **Leader-host only**. In Multi-AI mode, the structured debate in Phase 5M subsumes this review.
447
+ > Used for implementation flows after QA passes when review was not already included in Phase 5M. Skip this phase for QA-only submode.
388
448
 
389
449
  Run the `agestra-reviewer` agent for review/critique:
390
450
 
@@ -408,8 +468,8 @@ Provide a clear summary to the user:
408
468
  - Task completion summary: total tasks, completed, failed, re-routed
409
469
  - What changed (files modified, features added)
410
470
  - Verification summary:
411
- - Leader-host-only: QA depth, E2E status, QA report path, QA cycle count + what was auto-fixed, review report path, review verdict
412
- - Multi-AI: structured debate outcome (`approved` / `rejected`, with round count), `auto_inject_specialists` state, final synthesis path (if approved) from `.agestra/workspace/synthesis/`, and links to the individual reviews under `.agestra/workspace/individual/` and the transcript under `.agestra/workspace/debates/`
471
+ - Host-only QA/review: QA depth, E2E status, QA report path, QA cycle count + what was auto-fixed, review report path, review verdict
472
+ - QA Brigade / configured-provider QA: host QA report path, E2E host-only status, participant list, assigned lenses, accepted ledger items, excluded ledger items, open/opinion items, consensus verdict, dissenting findings, structured debate outcome (`approved` / `rejected`, with round count), `auto_inject_specialists` state, final synthesis path (if approved) from `.agestra/workspace/synthesis/`, and links to the individual reviews under `.agestra/workspace/individual/` and the transcript under `.agestra/workspace/debates/`
413
473
  - Any issues found and how they were resolved
414
474
 
415
475
  </Workflow>
@@ -45,7 +45,7 @@ Use AskUserQuestion to present the recommended routing in the user's language, o
45
45
 
46
46
  | Option | Condition | Description |
47
47
  |--------|-----------|-------------|
48
- | **Leader-host only** | Always | The current host delegates code changes to `agestra-implementer` and verifies locally |
48
+ | **Leader-host only** | Always | The current host delegates code changes to `agestra-implementer`; QA still follows the configured-provider default unless host-only QA is requested |
49
49
  | **Suggested AI distribution** | team mode available | The leader proposes which enabled AIs should handle which tasks, asks for approval, then dispatches |
50
50
 
51
51
  If team mode is not available, skip the question and use Leader-host only.
@@ -67,6 +67,11 @@ Determine QA depth for the post-implementation verification:
67
67
  - **Full QA with E2E** when the user explicitly asks for E2E/runtime verification, or when the work is centered on UI flows, auth, file operations, public release, destructive actions, or complex state transitions.
68
68
  - If Full QA may require long setup, a dev server, browser automation, screenshots, or persistent E2E test files, explain the time/token cost and ask before enabling it.
69
69
 
70
+ Determine QA routing separately from implementation routing:
71
+ - When configured external providers are available, team-lead routes post-implementation QA through the QA Brigade, even if implementation itself used Leader-host-only mode.
72
+ - If the user explicitly asks for host-only QA, or no external providers are available, use host-local QA only.
73
+ - E2E/runtime execution is always host-owned. External providers may review the host QA report, command output, screenshots, traces, and E2E findings, but they must not run browser/dev-server flows or create persistent E2E files directly.
74
+
70
75
  ## Step 5: Execute via team-lead
71
76
 
72
77
  Spawn `agestra:agestra-team-lead` with a self-contained handoff packet. The team-lead agent is the single execution entry point — this command does NOT call `cli_worker_spawn`, `ai_chat`, `agent_debate_*`, or spawn `agestra-implementer` / `agestra-qa` directly.
@@ -80,6 +85,9 @@ Handoff packet:
80
85
  - **Design doc reference:** path under `docs/plans/` if Step 4 produced or referenced one
81
86
  - **Progress tracking:** implementers must update the design document's top-level Implementation Progress table with Planned / In Progress / Implemented / Verified / Blocked / Deferred status and evidence; they must not rewrite approved scope to hide incomplete work
82
87
  - **QA depth:** Standard QA / Full QA with E2E / Decide automatically, based on Step 4
88
+ - **QA routing:** team-lead orchestrates the QA Brigade by default when external providers are available; host-only only when explicitly requested or unavailable
89
+ - **QA formation:** host executable evidence lead + all configured and available review-capable providers with distinct QA lenses
90
+ - **E2E/runtime execution:** host-owned only
83
91
  - **Available providers:** from `environment_check` / `provider_list`
84
92
  - **Requested providers:** explicit names captured from user wording; otherwise "all available"
85
93
  - **Locale:** from `setup_status`
@@ -90,7 +98,8 @@ Team-lead owns the rest:
90
98
 
91
99
  **Leader-host-only mode:**
92
100
  - Delegates code edits to `agestra:agestra-implementer`
93
- - Runs Phase 5 QA Cycle (`agestra:agestra-qa`) with auto-fix loop
101
+ - Runs host-owned QA evidence collection (`agestra:agestra-qa`) with auto-fix loop when fixes are needed
102
+ - Orchestrates the QA Brigade by default when external providers are available
94
103
  - Routes approved persistent E2E test work to `agestra:agestra-e2e-writer` only when QA requests it
95
104
  - Runs Phase 6 post-implementation review (`agestra:agestra-reviewer`) for critique, blast radius, AI-slop/cleanup notes, and blocking concerns
96
105
 
@@ -103,7 +112,7 @@ Team-lead owns the rest:
103
112
 
104
113
  **QA-only submode (`submode: qa-only`):**
105
114
  - Skips Phase 2/3/4 (no code changes)
106
- - Runs only Phase 5 (host-local QA) or Phase 5M (multi-AI QA debate) against existing code
115
+ - Runs Phase 5M (QA Brigade) by default when providers are available; otherwise runs Phase 5 (host-local QA) against existing code
107
116
  - Returns PASS / CONDITIONAL / FAIL verdict — never spawns implementer or CLI workers
108
117
  - Exception: if QA returns `E2E_TEST_WORK_REQUEST`, ask the user whether to create or update persistent E2E tests. If approved, route only that packet to `agestra:agestra-e2e-writer` as a separate E2E test-writing task, then re-run QA.
109
118
 
@@ -116,6 +125,7 @@ When team-lead returns, surface:
116
125
  - QA report path under `docs/reports/qa/`
117
126
  - Test/build outcome (`qa_run` result if executed)
118
127
  - QA verdict (PASS / CONDITIONAL PASS / FAIL with classified failures if any)
128
+ - QA Brigade participants, assigned lenses, accepted ledger items, excluded ledger items, open/opinion items, consensus, and notable dissenting findings when multi-AI QA ran
119
129
  - Review report path under `docs/reports/review/` and review verdict (APPROVE / APPROVE WITH CONCERNS / BLOCKING CONCERNS) when review ran
120
130
  - Synthesis paths under `.agestra/workspace/synthesis/` if structured debate ran
121
131
  - Communicate in the user's language
package/commands/qa.md CHANGED
@@ -40,13 +40,15 @@ Ask the user once:
40
40
 
41
41
  If the user chooses Full QA and persistent E2E test files must be added or updated, QA must ask approval and route test-file work to `agestra-e2e-writer`. QA itself remains read-only for source code and persistent tests.
42
42
 
43
+ Even in multi-AI QA, E2E/runtime execution is host-owned. External providers may review the design, code, host QA report, command output, screenshots, traces, and E2E findings, but they must not run browser/dev-server flows or create persistent E2E files directly.
44
+
43
45
  QA writes a Markdown report under `docs/reports/qa/` unless the user explicitly asks for chat-only output.
44
46
 
45
47
  ## Step 3: Route execution
46
48
 
47
49
  Call `environment_check` and `provider_list`.
48
50
 
49
- **Branch A — No external providers available or no multi-AI request:**
51
+ **Branch A — No external providers available, or the user explicitly requested host-only QA:**
50
52
  Spawn `agestra:agestra-qa` host specialist directly with:
51
53
  - QA target
52
54
  - Design document path
@@ -55,22 +57,26 @@ Spawn `agestra:agestra-qa` host specialist directly with:
55
57
  - Report artifact path expectation: `docs/reports/qa/YYYY-MM-DD-qa-[target].md`
56
58
  - Locale
57
59
 
58
- **Branch B — External providers requested or multi-AI QA requested:**
60
+ **Branch B — 1+ configured external providers available (default QA Brigade):**
59
61
  Hand off to `agestra:agestra-team-lead` with:
60
62
 
61
63
  - **Domain:** `qa`
62
64
  - **Submode:** `qa-only`
63
65
  - **Mode:** `multi-ai`
66
+ - **QA formation:** QA Brigade
64
67
  - **QA target:** from Step 1
65
68
  - **QA depth:** Standard QA / Full QA with E2E / Decide automatically
69
+ - **E2E/runtime execution:** host-owned only; external providers cross-validate artifacts and findings, not browser/dev-server execution
66
70
  - **Design doc reference:** path under `docs/plans/`
67
71
  - **Report artifact path expectation:** `docs/reports/qa/YYYY-MM-DD-qa-[target].md`
68
72
  - **Available providers:** from `environment_check`, exclude `ollama` unless explicitly requested for lightweight cross-checking
69
- - **Requested providers:** explicit names captured from user wording; otherwise "all available review-capable"
73
+ - **Requested providers:** explicit names captured from user wording; otherwise "all configured and available review-capable providers"
74
+ - **Brigade lenses:** host executable evidence, spec-to-code compliance, implementation progress truthfulness, integration/regression risk, edge/error states, test adequacy, basic safety hygiene, and E2E artifact review when E2E ran
75
+ - **JSON finding flow:** candidate findings become `ITEM-*` ledger items; participants use the existing `agree` / `disagree` / `opinion` / `revise` stance contract; only ledger-accepted items affect the final verdict
70
76
  - **Locale:** from `setup_status`
71
77
  - **Original user request:** preserve verbatim
72
78
 
73
- Team-lead owns cross-provider QA debate and aggregation. This command must not call `agent_debate_structured` directly.
79
+ Team-lead owns the QA Brigade handoff and leader approval gate. The moderator engine owns provider fan-out, `ITEM-*` creation, JSON stance turns, consensus ledger aggregation, minority/open items, and synthesis after approval. This command must not call `agent_debate_structured` directly. Do not ask for a separate multi-AI confirmation in Branch B; provider selection already came from setup. Honor explicit host-only wording.
74
80
 
75
81
  ## Step 4: Present the final result
76
82
 
@@ -79,6 +85,7 @@ When QA returns:
79
85
  - Link or name the design document used
80
86
  - Link the QA report artifact under `docs/reports/qa/`
81
87
  - Show PASS / CONDITIONAL PASS / FAIL
88
+ - In QA Brigade mode, summarize participants, assigned lenses, accepted ledger items, excluded ledger items, open/opinion items, consensus, and notable dissenting findings
82
89
  - Summarize progress-table mismatches, design gaps, build/test failures, E2E failures, and basic safety hygiene risks
83
90
  - If QA returned `E2E_TEST_WORK_REQUEST`, ask the user whether to create or update persistent E2E tests. If approved, route the request to `agestra:agestra-e2e-writer` or team-lead as a separate E2E test-writing task, then re-run QA after tests exist. If declined, record E2E as residual risk.
84
91
  - Recommend `/agestra review` for critique or `/agestra security` for dedicated security audit when needed
package/dist/bundle.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as ___cr } from 'module';import { fileURLToPath as ___fu } from 'url';import { dirname as ___dn } from 'path';const __filename = ___fu(import.meta.url);const __dirname = ___dn(__filename);const require = ___cr(import.meta.url);
3
- var IR=Object.create;var Cd=Object.defineProperty;var RR=Object.getOwnPropertyDescriptor;var AR=Object.getOwnPropertyNames;var CR=Object.getPrototypeOf,DR=Object.prototype.hasOwnProperty;var Ar=(t,e)=>()=>(t&&(e=t(t=0)),e);var S=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),rt=(t,e)=>{for(var r in e)Cd(t,r,{get:e[r],enumerable:!0})},OR=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of AR(e))!DR.call(t,s)&&s!==r&&Cd(t,s,{get:()=>e[s],enumerable:!(n=RR(e,s))||n.enumerable});return t};var Gy=(t,e,r)=>(r=t!=null?IR(CR(t)):{},OR(e||!t||!t.__esModule?Cd(r,"default",{value:t,enumerable:!0}):r,t));var Yy,si,Xy,Qy,ev,tv,rv,oi,nv,As,sv,ov,iv,av,cv,uv,In,Dd,Od,PK,kK,Md,lv,dv,ic,Rn,zd,pv,fv,Cs,Cr=Ar(()=>{"use strict";Yy="4.13.1",si="http://localhost:11434",Xy="llama3",Qy=".agestra/.jobs",ev=".agestra/traces",tv=".agestra/worktrees",rv=".agestra/sessions",oi=".agestra/workspace",nv="individual",As="debates",sv="synthesis",ov="issue",iv=".agestra/workers",av=Object.freeze(["PATH","HOME","USER","USERPROFILE","APPDATA","LOCALAPPDATA","TEMP","TMP","TMPDIR","SHELL","LANG","LC_ALL","NODE_PATH","SystemRoot","SystemDrive","COMSPEC","ComSpec","windir"]),cv=2,uv=6e4,In=20,Dd=5e4,Od=10,PK=Object.freeze([3,5,10]),kK=Object.freeze(["agree","disagree","abstain","revise"]),Md=2,lv=1440*60*1e3,dv=3600*1e3,ic=Object.freeze(["ko","zh","ja","en"]),Rn="ko",zd="en",pv="[REDACTED]",fv=["","--- REQUIRED RESPONSE FORMAT ---","Respond with JSON only, matching exactly this shape:",'{ "agrees": true | false, "feedback": "specific issues or why you agree", "suggestions": "concrete changes if you disagree (optional, may be omitted)" }',"No prose, markdown, or explanation outside the JSON object. The JSON must be the entire response or wrapped in a single ```json code fence.","-------------------------------"].join(`
3
+ var IR=Object.create;var Cd=Object.defineProperty;var RR=Object.getOwnPropertyDescriptor;var AR=Object.getOwnPropertyNames;var CR=Object.getPrototypeOf,DR=Object.prototype.hasOwnProperty;var Ar=(t,e)=>()=>(t&&(e=t(t=0)),e);var S=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),rt=(t,e)=>{for(var r in e)Cd(t,r,{get:e[r],enumerable:!0})},OR=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of AR(e))!DR.call(t,s)&&s!==r&&Cd(t,s,{get:()=>e[s],enumerable:!(n=RR(e,s))||n.enumerable});return t};var Gy=(t,e,r)=>(r=t!=null?IR(CR(t)):{},OR(e||!t||!t.__esModule?Cd(r,"default",{value:t,enumerable:!0}):r,t));var Yy,si,Xy,Qy,ev,tv,rv,oi,nv,As,sv,ov,iv,av,cv,uv,In,Dd,Od,PK,kK,Md,lv,dv,ic,Rn,zd,pv,fv,Cs,Cr=Ar(()=>{"use strict";Yy="4.13.2",si="http://localhost:11434",Xy="llama3",Qy=".agestra/.jobs",ev=".agestra/traces",tv=".agestra/worktrees",rv=".agestra/sessions",oi=".agestra/workspace",nv="individual",As="debates",sv="synthesis",ov="issue",iv=".agestra/workers",av=Object.freeze(["PATH","HOME","USER","USERPROFILE","APPDATA","LOCALAPPDATA","TEMP","TMP","TMPDIR","SHELL","LANG","LC_ALL","NODE_PATH","SystemRoot","SystemDrive","COMSPEC","ComSpec","windir"]),cv=2,uv=6e4,In=20,Dd=5e4,Od=10,PK=Object.freeze([3,5,10]),kK=Object.freeze(["agree","disagree","abstain","revise"]),Md=2,lv=1440*60*1e3,dv=3600*1e3,ic=Object.freeze(["ko","zh","ja","en"]),Rn="ko",zd="en",pv="[REDACTED]",fv=["","--- REQUIRED RESPONSE FORMAT ---","Respond with JSON only, matching exactly this shape:",'{ "agrees": true | false, "feedback": "specific issues or why you agree", "suggestions": "concrete changes if you disagree (optional, may be omitted)" }',"No prose, markdown, or explanation outside the JSON object. The JSON must be the entire response or wrapped in a single ```json code fence.","-------------------------------"].join(`
4
4
  `),Cs=Object.freeze({auto:Object.freeze({name:"auto",description:"Auto-detect build profile from project structure (package.json scripts, tsconfig, vitest config, etc.).",command:"npx",args:Object.freeze([])}),tsc:Object.freeze({name:"tsc",description:"TypeScript project-references build via `npx tsc -b --noEmit`.",command:"npx",args:Object.freeze(["tsc","-b","--noEmit"])}),vitest:Object.freeze({name:"vitest",description:"Run the Vitest unit-test suite in CI mode.",command:"npx",args:Object.freeze(["vitest","run","--reporter=dot"])}),"npm-build":Object.freeze({name:"npm-build",description:"Run the project's `npm run build` script.",command:"npm",args:Object.freeze(["run","build"])}),"npm-test":Object.freeze({name:"npm-test",description:"Run the project's `npm test` script.",command:"npm",args:Object.freeze(["test","--","--run"])})})});import{execFileSync as MR}from"child_process";function Ds(t){if(!Number.isFinite(t)||t<=0)return{delivered:!1};if(process.platform==="win32")try{return MR("taskkill",["/PID",String(t),"/T","/F"],{stdio:"ignore",windowsHide:!0}),{delivered:!0}}catch{try{return process.kill(t),{delivered:!0}}catch{return{delivered:!1}}}try{return process.kill(-t,"SIGTERM"),{delivered:!0}}catch{try{return process.kill(t,"SIGTERM"),{delivered:!0}}catch{return{delivered:!1}}}}function Qt(t,e=3e3){let r=t.pid;if(r)Ds(r);else try{t.kill("SIGTERM")}catch{}setTimeout(()=>{try{t.kill("SIGKILL")}catch{}},e).unref?.()}var Os=Ar(()=>{"use strict"});import{execFileSync as zR,spawn as jR}from"child_process";import{existsSync as NR}from"fs";function mv(t){let e=t.replace(/\s+/g," ").trim();return e.length>200?`${e.slice(0,200)}...`:e}function Yr(t,e){if(t)try{t({...e,at:new Date().toISOString()})}catch{}}function qR(t){return process.platform!=="win32"||t.includes("/")||t.includes("\\")?!1:LR.has(t.toLowerCase())}function FR(t){if(t.includes("\0"))throw new Error(`Windows shim arg contains null byte: ${JSON.stringify(t)}`);if(t.includes("%"))throw new Error(`Windows shim arg contains '%' which would trigger cmd.exe env expansion: ${JSON.stringify(t)}`);return/[\s"&^<>|()!]/.test(t)?`"${t.replace(/"/g,'""')}"`:t}function UR(t){let e=t.toLowerCase();if(Ms.has(e))return Ms.get(e)??null;try{let n=zR("where.exe",[t],{encoding:"utf-8",stdio:["ignore","pipe","ignore"],windowsHide:!0,timeout:5e3}).split(/\r?\n/).map(a=>a.trim()).filter(Boolean);if(n.length===0)return Ms.set(e,null),null;let s=n.find(a=>/\.(cmd|bat)$/i.test(a));if(s){let a={type:"cmd",path:s};return Ms.set(e,a),a}let i=`${n[0]}.ps1`;if(NR(i)){let a={type:"powershell",path:i};return Ms.set(e,a),a}}catch{}return Ms.set(e,null),null}function An(t,e){if(!qR(t))return{command:t,args:e};let r=UR(t);return r?r.type==="cmd"?{command:"cmd.exe",args:["/d","/s","/c",r.path,...e.map(n=>FR(n))]}:{command:"powershell.exe",args:["-NoProfile","-ExecutionPolicy","RemoteSigned","-File",r.path,...e]}:{command:t,args:e}}function vt(t){let{command:e,args:r,timeout:n=12e4,overallTimeoutMs:s,cwd:o,env:i,stdin:a,maxBuffer:c=10485760,onStderrChunk:u,onActivity:l,signal:d}=t;return new Promise((p,f)=>{if(d?.aborted){Yr(l,{type:"abort",command:e,args:r,reason:String(d.reason??"aborted before spawn")}),f(new jt(d.reason));return}let m=An(e,r);Yr(l,{type:"start",command:m.command,args:m.args,timeoutMs:n});let h=jR(m.command,m.args,{cwd:o,env:i?{...process.env,...i}:void 0,stdio:[a?"pipe":"ignore","pipe","pipe"],windowsHide:!0}),y="",g="",b=0,_=0,P=!1,x=null,N=!1,k=null,O=()=>{k&&d&&d.removeEventListener("abort",k)},L=!1,q=()=>{!L&&b+_>c&&(P=!0,L=!0,Qt(h))},$e=null,We=()=>{$e&&(clearTimeout($e),$e=null)},Rt=()=>{N||(Qt(h),N=!0,We(),O(),Yr(l,{type:"timeout",command:e,args:r,timeoutMs:n}),f(new Error(`CLI timeout after ${n}ms of inactivity: ${e} ${r.join(" ")}`)))},zt=setTimeout(Rt,n);$e=s!==void 0?setTimeout(()=>{N||(Qt(h),N=!0,clearTimeout(zt),We(),O(),Yr(l,{type:"timeout",command:e,args:r,timeoutMs:s}),f(new Error(`CLI overall timeout after ${s}ms: ${e} ${r.join(" ")}`)))},s):null,d&&(k=()=>{N||(N=!0,clearTimeout(zt),We(),Qt(h),O(),Yr(l,{type:"abort",command:e,args:r,reason:String(d.reason??"aborted")}),f(new jt(d.reason)))},d.addEventListener("abort",k));let Ts=()=>{L||(clearTimeout(zt),zt=setTimeout(Rt,n))};if(h.stdout.on("data",At=>{b+=At.length,Yr(l,{type:"stdout",command:e,args:r,preview:mv(At.toString())}),b<=c&&(y+=At.toString()),q(),Ts()}),h.stderr.on("data",At=>{_+=At.length;let Tn=At.toString();if(Yr(l,{type:"stderr",command:e,args:r,preview:mv(Tn)}),_<=c&&(g+=Tn),q(),!L&&u){let ni=u(Tn);ni&&(x=ni,L=!0,Qt(h))}Ts()}),a&&h.stdin){h.stdin.on("error",()=>{});try{h.stdin.write(a),h.stdin.end()}catch{}}h.on("close",(At,Tn)=>{if(clearTimeout(zt),We(),!N){if(Yr(l,{type:"close",command:e,args:r,exitCode:At,signalCode:Tn}),x){N=!0,O(),f(x);return}N=!0,O(),p({stdout:y,stderr:g,exitCode:At??1,truncated:P})}}),h.on("error",At=>{clearTimeout(zt),We(),!N&&(N=!0,O(),f(new Error(`CLI spawn error: ${At.message}`)))})})}var jt,LR,Ms,ii=Ar(()=>{"use strict";Os();jt=class extends Error{constructor(e){let r=e instanceof Error?`: ${e.message}`:typeof e=="string"&&e?`: ${e}`:"";super(`CLI aborted${r}`),this.name="CliAbortedError"}};LR=new Set(["codex","gemini","npm","npx"]),Ms=new Map});import{writeFileSync as dC,mkdirSync as di,openSync as Fd,writeSync as Ud,fsyncSync as Ov,closeSync as Zd,renameSync as pC,unlinkSync as Dv,appendFileSync as fC,copyFileSync as mC}from"fs";import{dirname as pi,join as hC}from"path";import{randomUUID as gC}from"crypto";function ge(t,e){let r=pi(t);di(r,{recursive:!0});let n=hC(r,`.tmp-${gC().slice(0,8)}`);try{dC(n,e,"utf-8");try{pC(n,t)}catch(s){if(s.code!=="EXDEV")throw s;mC(n,t),Dv(n)}}catch(s){try{Dv(n)}catch{}throw s}}function Ze(t,e){ge(t,JSON.stringify(e,null,2))}function _c(t,e){let r=pi(t);di(r,{recursive:!0});let n=Fd(t,"a");try{Ud(n,e),Ov(n)}finally{Zd(n)}}var vc,nn=Ar(()=>{"use strict";vc=class{buffer=new Map;flushTimer=null;flushIntervalMs;maxBufferSize;auditFsync;destroyed=!1;constructor(e){this.flushIntervalMs=e?.flushIntervalMs??2e3,this.maxBufferSize=e?.maxBufferSize??100,this.auditFsync=e?.auditFsync??!0,this.flushIntervalMs>0&&(this.flushTimer=setInterval(()=>this.flush(),this.flushIntervalMs),this.flushTimer&&typeof this.flushTimer.unref=="function"&&this.flushTimer.unref())}append(e,r,n){if(this.destroyed)throw new Error("DurableAppendWriter has been destroyed");if(n==="audit"){if(this.auditFsync)_c(e,r);else{let o=pi(e);di(o,{recursive:!0}),fC(e,r)}return}let s=this.buffer.get(e);s||(s=[],this.buffer.set(e,s)),s.push(r),s.length>=this.maxBufferSize&&this.flushFile(e),this.flushIntervalMs===0&&this.flushFile(e)}flush(){for(let e of this.buffer.keys())this.flushFile(e)}panicFlush(){for(let[e,r]of this.buffer)if(r.length!==0)try{let n=pi(e);di(n,{recursive:!0});let s=Fd(e,"a");try{Ud(s,r.join("")),Ov(s)}finally{Zd(s)}}catch{}this.buffer.clear()}destroy(){this.destroyed||(this.destroyed=!0,this.flushTimer!==null&&(clearInterval(this.flushTimer),this.flushTimer=null),this.flush())}flushFile(e){let r=this.buffer.get(e);if(!r||r.length===0)return;let n=pi(e);di(n,{recursive:!0});let s=Fd(e,"a");try{Ud(s,r.join(""))}finally{Zd(s)}this.buffer.delete(e)}}});import{openSync as yC,writeSync as vC,closeSync as _C,unlinkSync as Mv,statSync as bC,mkdirSync as wC,existsSync as SC}from"fs";import{dirname as $C}from"path";function EC(t){if(t<=0)return;let e=new SharedArrayBuffer(4),r=new Int32Array(e);Atomics.wait(r,0,0,t)}function Kn(t,e,r={}){let n=r.staleMs??xC,s=r.acquireTimeoutMs??PC,o=r.pollMs??kC;wC($C(t),{recursive:!0});let i=Date.now(),a=null;for(;a===null;)try{a=yC(t,"wx")}catch(c){let u=c.code;if(!(u==="EEXIST"||process.platform==="win32"&&u==="EPERM"&&SC(t)))throw c;let d=!1;try{let f=bC(t);d=Date.now()-f.mtimeMs>n}catch{continue}if(d){try{Mv(t)}catch{}continue}let p=Date.now()-i;if(p>=s)throw new Vd(t,p);EC(o)}try{try{vC(a,`${process.pid}@${Date.now()}
5
5
  `)}catch{}return e()}finally{try{_C(a)}catch{}try{Mv(t)}catch{}}}var xC,PC,kC,Vd,bc=Ar(()=>{"use strict";xC=3e4,PC=5e3,kC=10,Vd=class extends Error{constructor(e,r){super(`withFileLock: timed out after ${r}ms waiting for ${e}`),this.name="FileLockTimeoutError"}}});import{existsSync as zv,realpathSync as TC}from"fs";import{basename as IC,dirname as RC,isAbsolute as Hd,join as AC,normalize as Nv,resolve as Wd,relative as CC}from"path";function DC(t){return t===""||!t.startsWith("..")&&!Hd(t)}function Bd(t){let e=[],r=Wd(t);for(;!zv(r);){let s=RC(r);if(s===r)break;e.unshift(IC(r)),r=s}let n=zv(r)?TC(r):r;return e.reduce((s,o)=>AC(s,o),n)}function Lv(t,e){let r=Bd(e),n=Bd(t),s=CC(r,n);return DC(s)}function Kd(t,e){let r=Wd(e,t);return Lv(r,e)}function Ft(t,e){let r=Wd(e,t);if(!Lv(r,e))throw new Error(`Path traversal blocked: ${t} escapes ${e}`);return r}function Je(t,e){if(t.length===0)throw new Error("Filename must not be empty");if(t.includes("\0"))throw new Error(`Filename contains null byte: ${JSON.stringify(t)}`);if(t.includes("/")||t.includes("\\"))throw new Error(`Filename must not contain path separators: ${JSON.stringify(t)}`);if(t.includes(".."))throw new Error(`Filename must not contain '..': ${JSON.stringify(t)}`);return Ft(t,e)}function sn(t,e){if(Hd(t)){let r=Nv(t);if(!Kd(r,e))throw new Error(`Read path outside base directory: ${t} is not within ${e}`);return r}return Ft(t,e)}function qv(t,e){return Hd(t)?Bd(Nv(t)):Ft(t,e)}function Nr(t){return OC.test(t)}function wc(t,e){if(!t||typeof t!="string")throw new Ct(String(t),"command must be a non-empty string");if(t.includes("\0"))throw new Ct(t,"command contains null byte");if(t.includes("/")||t.includes("\\"))throw new Ct(t,"command must not contain path separators");if(!jv.has(t))throw new Ct(t,`command is not in the allowlist (${[...jv].join(", ")})`);for(let r of e){if(typeof r!="string")throw new Ct(t,`args contain a non-string entry: ${JSON.stringify(r)}`);if(r.includes("\0"))throw new Ct(t,`arg contains null byte: ${JSON.stringify(r)}`);if(MC.has(r))throw new Ct(t,`arg ${JSON.stringify(r)} is a code-execution flag and is not permitted`)}}var OC,jv,MC,Ct,Vs=Ar(()=>{"use strict";OC=/^[a-zA-Z0-9_-]+-\d+-[a-f0-9]{6}$/;jv=new Set(["gemini","codex","claude","npx","node","npm","tsc"]),MC=new Set(["-e","--eval","-c","--command","-E","--execute","--exec"]),Ct=class extends Error{command;reason;constructor(e,r){super(`CLI command rejected: ${e} \u2014 ${r}`),this.command=e,this.reason=r,this.name="CliCommandRejectedError"}}});import{readFileSync as zC}from"fs";import{join as jC}from"path";function Ve(t,e){let r=jC(t,"status.json"),n=`${r}.lock`;Kn(n,()=>{let s=JSON.parse(zC(r,"utf-8"));Ze(r,{...s,...e})})}var fi=Ar(()=>{"use strict";nn();bc()});import{spawn as NC}from"child_process";import{join as Jd}from"path";function Fv(t){let e=t.replace(/\s+/g," ").trim();return e.length>200?`${e.slice(0,200)}...`:e}function Sc(t){return new Promise(e=>{let r=An(t.command,t.args),n={kind:"start",updatedAt:new Date().toISOString(),message:"CLI process started",command:r.command,timeoutMs:t.timeoutMs,stdoutBytes:0,stderrBytes:0},s=0,o,i=(y,g={})=>{Object.assign(n,y,{updatedAt:new Date().toISOString()});let b=Date.now(),_=n.kind!==o;if(!(!g.force&&!_&&b-s<LC))try{Ve(t.jobDir,{activity:{...n}}),s=b,o=n.kind}catch{}};i(n,{force:!0});let a=NC(r.command,r.args,{cwd:t.cwd,stdio:["ignore","pipe","pipe"],windowsHide:!0});if(t.recordPid&&typeof a.pid=="number"&&a.pid>0)try{Ve(t.jobDir,{pid:a.pid})}catch{}if(!a.stdout||!a.stderr){try{a.kill()}catch{}try{ge(Jd(t.jobDir,"error.txt"),"Worker stdout/stderr streams unavailable (pipe allocation failed)"),Ve(t.jobDir,{state:"error",completedAt:new Date().toISOString()})}catch{}e();return}let c="",u="",l=0,d=0,p=!1,f=!1;a.stdout.on("data",y=>{l+=y.length,i({kind:"stdout",message:"stdout received",stdoutBytes:l,stderrBytes:d,lastStdoutPreview:Fv(y.toString())}),l<=10485760?c+=y.toString():p||(p=!0,Qt(a))}),a.stderr.on("data",y=>{d+=y.length,i({kind:"stderr",message:"stderr received",stdoutBytes:l,stderrBytes:d,lastStderrPreview:Fv(y.toString())}),d<=10485760&&(u+=y.toString())});let m=(y,g)=>{if(!f){f=!0,clearTimeout(h);try{ge(Jd(t.jobDir,"output.txt"),c),ge(Jd(t.jobDir,"error.txt"),g!==void 0?g:u),Ve(t.jobDir,y)}catch{}e()}},h=setTimeout(()=>{Qt(a),i({kind:"timeout",message:`timed out after ${t.timeoutMs}ms`,timeoutMs:t.timeoutMs,stdoutBytes:l,stderrBytes:d},{force:!0}),m({state:"timed_out",completedAt:new Date().toISOString()})},t.timeoutMs);a.on("close",y=>{if(f)return;let g=c.trim().length>0,b=y===0||g?"completed":"error";i({kind:"close",message:"CLI process closed",exitCode:y??1,stdoutBytes:l,stderrBytes:d},{force:!0}),m({state:b,exitCode:y??1,completedAt:new Date().toISOString()})}),a.on("error",y=>{if(f)return;let g=y.code==="ENOENT"?"missing_cli":"error";i({kind:"close",message:`CLI spawn error: ${y.message}`,stdoutBytes:l,stderrBytes:d},{force:!0}),m({state:g,completedAt:new Date().toISOString()},y.message)})})}var LC,Gd=Ar(()=>{"use strict";nn();ii();Os();fi();LC=1e3});var Bv={};rt(Bv,{CLI_PROVIDERS:()=>Zv,resolveCliConfig:()=>Vv});import{readFileSync as Uv}from"fs";import{join as Jn}from"path";function Vv(t){let e=qC[t.provider]??t.provider;return Zv[e]??null}async function FC(){let t=process.argv[2];t||process.exit(1);let e;try{e=JSON.parse(Uv(Jn(t,"job.json"),"utf-8"))}catch{try{Ze(Jn(t,"status.json"),{id:"unknown",state:"error",provider:"unknown",completedAt:new Date().toISOString()}),ge(Jn(t,"error.txt"),"Failed to read job.json")}catch{}process.exit(1)}let r=Vv(e);r||(Ve(t,{state:"missing_cli",completedAt:new Date().toISOString()}),ge(Jn(t,"error.txt"),`No CLI mapping for provider: ${e.provider}`),process.exit(1));let{command:n,buildArgs:s}=r;Ve(t,{state:"running",startedAt:new Date().toISOString()});let o=Uv(Jn(t,"prompt.txt"),"utf-8"),i=s(o);try{wc(n,i)}catch(c){let u=c instanceof Ct?c.message:`Argv rejected: ${c.message}`;Ve(t,{state:"error",completedAt:new Date().toISOString()}),ge(Jn(t,"error.txt"),u);return}let a;if(e.cwd)try{a=Ft(e.cwd,process.cwd())}catch(c){Ve(t,{state:"error",completedAt:new Date().toISOString()}),ge(Jn(t,"error.txt"),`Rejected descriptor.cwd: ${c.message}`);return}await Sc({jobDir:t,command:n,args:i,cwd:a,timeoutMs:e.timeout,recordPid:!1})}var qC,Zv,UC,Hv=Ar(()=>{"use strict";nn();Vs();Gd();fi();qC={"gemini-cli":"gemini","codex-cli":"codex","claude-cli":"claude"},Zv={gemini:{command:"gemini",buildArgs:t=>["-p",t]},codex:{command:"codex",buildArgs:t=>["exec","--skip-git-repo-check","--full-auto","--ephemeral",t]},claude:{command:"claude",buildArgs:t=>["-p",t]}};UC=process.argv[1]?.endsWith("job-worker.js")||process.argv[1]?.endsWith("job-worker.ts");UC&&FC().catch(()=>process.exit(1))});var Qi=S(me=>{"use strict";Object.defineProperty(me,"__esModule",{value:!0});me.regexpCode=me.getEsmExportName=me.getProperty=me.safeStringify=me.stringify=me.strConcat=me.addCodeArg=me.str=me._=me.nil=me._Code=me.Name=me.IDENTIFIER=me._CodeOrName=void 0;var Yi=class{};me._CodeOrName=Yi;me.IDENTIFIER=/^[a-z$_][a-z$_0-9]*$/i;var ss=class extends Yi{constructor(e){if(super(),!me.IDENTIFIER.test(e))throw new Error("CodeGen: name must be a valid identifier");this.str=e}toString(){return this.str}emptyStr(){return!1}get names(){return{[this.str]:1}}};me.Name=ss;var Bt=class extends Yi{constructor(e){super(),this._items=typeof e=="string"?[e]:e}toString(){return this.str}emptyStr(){if(this._items.length>1)return!1;let e=this._items[0];return e===""||e==='""'}get str(){var e;return(e=this._str)!==null&&e!==void 0?e:this._str=this._items.reduce((r,n)=>`${r}${n}`,"")}get names(){var e;return(e=this._names)!==null&&e!==void 0?e:this._names=this._items.reduce((r,n)=>(n instanceof ss&&(r[n.str]=(r[n.str]||0)+1),r),{})}};me._Code=Bt;me.nil=new Bt("");function Q$(t,...e){let r=[t[0]],n=0;for(;n<e.length;)Df(r,e[n]),r.push(t[++n]);return new Bt(r)}me._=Q$;var Cf=new Bt("+");function ex(t,...e){let r=[Xi(t[0])],n=0;for(;n<e.length;)r.push(Cf),Df(r,e[n]),r.push(Cf,Xi(t[++n]));return Bj(r),new Bt(r)}me.str=ex;function Df(t,e){e instanceof Bt?t.push(...e._items):e instanceof ss?t.push(e):t.push(Kj(e))}me.addCodeArg=Df;function Bj(t){let e=1;for(;e<t.length-1;){if(t[e]===Cf){let r=Hj(t[e-1],t[e+1]);if(r!==void 0){t.splice(e-1,3,r);continue}t[e++]="+"}e++}}function Hj(t,e){if(e==='""')return t;if(t==='""')return e;if(typeof t=="string")return e instanceof ss||t[t.length-1]!=='"'?void 0:typeof e!="string"?`${t.slice(0,-1)}${e}"`:e[0]==='"'?t.slice(0,-1)+e.slice(1):void 0;if(typeof e=="string"&&e[0]==='"'&&!(t instanceof ss))return`"${t}${e.slice(1)}`}function Wj(t,e){return e.emptyStr()?t:t.emptyStr()?e:ex`${t}${e}`}me.strConcat=Wj;function Kj(t){return typeof t=="number"||typeof t=="boolean"||t===null?t:Xi(Array.isArray(t)?t.join(","):t)}function Jj(t){return new Bt(Xi(t))}me.stringify=Jj;function Xi(t){return JSON.stringify(t).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}me.safeStringify=Xi;function Gj(t){return typeof t=="string"&&me.IDENTIFIER.test(t)?new Bt(`.${t}`):Q$`[${t}]`}me.getProperty=Gj;function Yj(t){if(typeof t=="string"&&me.IDENTIFIER.test(t))return new Bt(`${t}`);throw new Error(`CodeGen: invalid export name: ${t}, use explicit $id name mapping`)}me.getEsmExportName=Yj;function Xj(t){return new Bt(t.toString())}me.regexpCode=Xj});var zf=S($t=>{"use strict";Object.defineProperty($t,"__esModule",{value:!0});$t.ValueScope=$t.ValueScopeName=$t.Scope=$t.varKinds=$t.UsedValueState=void 0;var St=Qi(),Of=class extends Error{constructor(e){super(`CodeGen: "code" for ${e} not defined`),this.value=e.value}},Iu;(function(t){t[t.Started=0]="Started",t[t.Completed=1]="Completed"})(Iu||($t.UsedValueState=Iu={}));$t.varKinds={const:new St.Name("const"),let:new St.Name("let"),var:new St.Name("var")};var Ru=class{constructor({prefixes:e,parent:r}={}){this._names={},this._prefixes=e,this._parent=r}toName(e){return e instanceof St.Name?e:this.name(e)}name(e){return new St.Name(this._newName(e))}_newName(e){let r=this._names[e]||this._nameGroup(e);return`${e}${r.index++}`}_nameGroup(e){var r,n;if(!((n=(r=this._parent)===null||r===void 0?void 0:r._prefixes)===null||n===void 0)&&n.has(e)||this._prefixes&&!this._prefixes.has(e))throw new Error(`CodeGen: prefix "${e}" is not allowed in this scope`);return this._names[e]={prefix:e,index:0}}};$t.Scope=Ru;var Au=class extends St.Name{constructor(e,r){super(r),this.prefix=e}setValue(e,{property:r,itemIndex:n}){this.value=e,this.scopePath=(0,St._)`.${new St.Name(r)}[${n}]`}};$t.ValueScopeName=Au;var Qj=(0,St._)`\n`,Mf=class extends Ru{constructor(e){super(e),this._values={},this._scope=e.scope,this.opts={...e,_n:e.lines?Qj:St.nil}}get(){return this._scope}name(e){return new Au(e,this._newName(e))}value(e,r){var n;if(r.ref===void 0)throw new Error("CodeGen: ref must be passed in value");let s=this.toName(e),{prefix:o}=s,i=(n=r.key)!==null&&n!==void 0?n:r.ref,a=this._values[o];if(a){let l=a.get(i);if(l)return l}else a=this._values[o]=new Map;a.set(i,s);let c=this._scope[o]||(this._scope[o]=[]),u=c.length;return c[u]=r.ref,s.setValue(r,{property:o,itemIndex:u}),s}getValue(e,r){let n=this._values[e];if(n)return n.get(r)}scopeRefs(e,r=this._values){return this._reduceValues(r,n=>{if(n.scopePath===void 0)throw new Error(`CodeGen: name "${n}" has no value`);return(0,St._)`${e}${n.scopePath}`})}scopeCode(e=this._values,r,n){return this._reduceValues(e,s=>{if(s.value===void 0)throw new Error(`CodeGen: name "${s}" has no value`);return s.value.code},r,n)}_reduceValues(e,r,n={},s){let o=St.nil;for(let i in e){let a=e[i];if(!a)continue;let c=n[i]=n[i]||new Map;a.forEach(u=>{if(c.has(u))return;c.set(u,Iu.Started);let l=r(u);if(l){let d=this.opts.es5?$t.varKinds.var:$t.varKinds.const;o=(0,St._)`${o}${d} ${u} = ${l};${this.opts._n}`}else if(l=s?.(u))o=(0,St._)`${o}${l}${this.opts._n}`;else throw new Of(u);c.set(u,Iu.Completed)})}return o}};$t.ValueScope=Mf});var te=S(Q=>{"use strict";Object.defineProperty(Q,"__esModule",{value:!0});Q.or=Q.and=Q.not=Q.CodeGen=Q.operators=Q.varKinds=Q.ValueScopeName=Q.ValueScope=Q.Scope=Q.Name=Q.regexpCode=Q.stringify=Q.getProperty=Q.nil=Q.strConcat=Q.str=Q._=void 0;var ce=Qi(),sr=zf(),dn=Qi();Object.defineProperty(Q,"_",{enumerable:!0,get:function(){return dn._}});Object.defineProperty(Q,"str",{enumerable:!0,get:function(){return dn.str}});Object.defineProperty(Q,"strConcat",{enumerable:!0,get:function(){return dn.strConcat}});Object.defineProperty(Q,"nil",{enumerable:!0,get:function(){return dn.nil}});Object.defineProperty(Q,"getProperty",{enumerable:!0,get:function(){return dn.getProperty}});Object.defineProperty(Q,"stringify",{enumerable:!0,get:function(){return dn.stringify}});Object.defineProperty(Q,"regexpCode",{enumerable:!0,get:function(){return dn.regexpCode}});Object.defineProperty(Q,"Name",{enumerable:!0,get:function(){return dn.Name}});var Mu=zf();Object.defineProperty(Q,"Scope",{enumerable:!0,get:function(){return Mu.Scope}});Object.defineProperty(Q,"ValueScope",{enumerable:!0,get:function(){return Mu.ValueScope}});Object.defineProperty(Q,"ValueScopeName",{enumerable:!0,get:function(){return Mu.ValueScopeName}});Object.defineProperty(Q,"varKinds",{enumerable:!0,get:function(){return Mu.varKinds}});Q.operators={GT:new ce._Code(">"),GTE:new ce._Code(">="),LT:new ce._Code("<"),LTE:new ce._Code("<="),EQ:new ce._Code("==="),NEQ:new ce._Code("!=="),NOT:new ce._Code("!"),OR:new ce._Code("||"),AND:new ce._Code("&&"),ADD:new ce._Code("+")};var Fr=class{optimizeNodes(){return this}optimizeNames(e,r){return this}},jf=class extends Fr{constructor(e,r,n){super(),this.varKind=e,this.name=r,this.rhs=n}render({es5:e,_n:r}){let n=e?sr.varKinds.var:this.varKind,s=this.rhs===void 0?"":` = ${this.rhs}`;return`${n} ${this.name}${s};`+r}optimizeNames(e,r){if(e[this.name.str])return this.rhs&&(this.rhs=go(this.rhs,e,r)),this}get names(){return this.rhs instanceof ce._CodeOrName?this.rhs.names:{}}},Cu=class extends Fr{constructor(e,r,n){super(),this.lhs=e,this.rhs=r,this.sideEffects=n}render({_n:e}){return`${this.lhs} = ${this.rhs};`+e}optimizeNames(e,r){if(!(this.lhs instanceof ce.Name&&!e[this.lhs.str]&&!this.sideEffects))return this.rhs=go(this.rhs,e,r),this}get names(){let e=this.lhs instanceof ce.Name?{}:{...this.lhs.names};return Ou(e,this.rhs)}},Nf=class extends Cu{constructor(e,r,n,s){super(e,n,s),this.op=r}render({_n:e}){return`${this.lhs} ${this.op}= ${this.rhs};`+e}},Lf=class extends Fr{constructor(e){super(),this.label=e,this.names={}}render({_n:e}){return`${this.label}:`+e}},qf=class extends Fr{constructor(e){super(),this.label=e,this.names={}}render({_n:e}){return`break${this.label?` ${this.label}`:""};`+e}},Ff=class extends Fr{constructor(e){super(),this.error=e}render({_n:e}){return`throw ${this.error};`+e}get names(){return this.error.names}},Uf=class extends Fr{constructor(e){super(),this.code=e}render({_n:e}){return`${this.code};`+e}optimizeNodes(){return`${this.code}`?this:void 0}optimizeNames(e,r){return this.code=go(this.code,e,r),this}get names(){return this.code instanceof ce._CodeOrName?this.code.names:{}}},ea=class extends Fr{constructor(e=[]){super(),this.nodes=e}render(e){return this.nodes.reduce((r,n)=>r+n.render(e),"")}optimizeNodes(){let{nodes:e}=this,r=e.length;for(;r--;){let n=e[r].optimizeNodes();Array.isArray(n)?e.splice(r,1,...n):n?e[r]=n:e.splice(r,1)}return e.length>0?this:void 0}optimizeNames(e,r){let{nodes:n}=this,s=n.length;for(;s--;){let o=n[s];o.optimizeNames(e,r)||(eN(e,o.names),n.splice(s,1))}return n.length>0?this:void 0}get names(){return this.nodes.reduce((e,r)=>as(e,r.names),{})}},Ur=class extends ea{render(e){return"{"+e._n+super.render(e)+"}"+e._n}},Zf=class extends ea{},ho=class extends Ur{};ho.kind="else";var os=class t extends Ur{constructor(e,r){super(r),this.condition=e}render(e){let r=`if(${this.condition})`+super.render(e);return this.else&&(r+="else "+this.else.render(e)),r}optimizeNodes(){super.optimizeNodes();let e=this.condition;if(e===!0)return this.nodes;let r=this.else;if(r){let n=r.optimizeNodes();r=this.else=Array.isArray(n)?new ho(n):n}if(r)return e===!1?r instanceof t?r:r.nodes:this.nodes.length?this:new t(tx(e),r instanceof t?[r]:r.nodes);if(!(e===!1||!this.nodes.length))return this}optimizeNames(e,r){var n;if(this.else=(n=this.else)===null||n===void 0?void 0:n.optimizeNames(e,r),!!(super.optimizeNames(e,r)||this.else))return this.condition=go(this.condition,e,r),this}get names(){let e=super.names;return Ou(e,this.condition),this.else&&as(e,this.else.names),e}};os.kind="if";var is=class extends Ur{};is.kind="for";var Vf=class extends is{constructor(e){super(),this.iteration=e}render(e){return`for(${this.iteration})`+super.render(e)}optimizeNames(e,r){if(super.optimizeNames(e,r))return this.iteration=go(this.iteration,e,r),this}get names(){return as(super.names,this.iteration.names)}},Bf=class extends is{constructor(e,r,n,s){super(),this.varKind=e,this.name=r,this.from=n,this.to=s}render(e){let r=e.es5?sr.varKinds.var:this.varKind,{name:n,from:s,to:o}=this;return`for(${r} ${n}=${s}; ${n}<${o}; ${n}++)`+super.render(e)}get names(){let e=Ou(super.names,this.from);return Ou(e,this.to)}},Du=class extends is{constructor(e,r,n,s){super(),this.loop=e,this.varKind=r,this.name=n,this.iterable=s}render(e){return`for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})`+super.render(e)}optimizeNames(e,r){if(super.optimizeNames(e,r))return this.iterable=go(this.iterable,e,r),this}get names(){return as(super.names,this.iterable.names)}},ta=class extends Ur{constructor(e,r,n){super(),this.name=e,this.args=r,this.async=n}render(e){return`${this.async?"async ":""}function ${this.name}(${this.args})`+super.render(e)}};ta.kind="func";var ra=class extends ea{render(e){return"return "+super.render(e)}};ra.kind="return";var Hf=class extends Ur{render(e){let r="try"+super.render(e);return this.catch&&(r+=this.catch.render(e)),this.finally&&(r+=this.finally.render(e)),r}optimizeNodes(){var e,r;return super.optimizeNodes(),(e=this.catch)===null||e===void 0||e.optimizeNodes(),(r=this.finally)===null||r===void 0||r.optimizeNodes(),this}optimizeNames(e,r){var n,s;return super.optimizeNames(e,r),(n=this.catch)===null||n===void 0||n.optimizeNames(e,r),(s=this.finally)===null||s===void 0||s.optimizeNames(e,r),this}get names(){let e=super.names;return this.catch&&as(e,this.catch.names),this.finally&&as(e,this.finally.names),e}},na=class extends Ur{constructor(e){super(),this.error=e}render(e){return`catch(${this.error})`+super.render(e)}};na.kind="catch";var sa=class extends Ur{render(e){return"finally"+super.render(e)}};sa.kind="finally";var Wf=class{constructor(e,r={}){this._values={},this._blockStarts=[],this._constants={},this.opts={...r,_n:r.lines?`
6
6
  `:""},this._extScope=e,this._scope=new sr.Scope({parent:e}),this._nodes=[new Zf]}toString(){return this._root.render(this.opts)}name(e){return this._scope.name(e)}scopeName(e){return this._extScope.name(e)}scopeValue(e,r){let n=this._extScope.value(e,r);return(this._values[n.prefix]||(this._values[n.prefix]=new Set)).add(n),n}getScopeValue(e,r){return this._extScope.getValue(e,r)}scopeRefs(e){return this._extScope.scopeRefs(e,this._values)}scopeCode(){return this._extScope.scopeCode(this._values)}_def(e,r,n,s){let o=this._scope.toName(r);return n!==void 0&&s&&(this._constants[o.str]=n),this._leafNode(new jf(e,o,n)),o}const(e,r,n){return this._def(sr.varKinds.const,e,r,n)}let(e,r,n){return this._def(sr.varKinds.let,e,r,n)}var(e,r,n){return this._def(sr.varKinds.var,e,r,n)}assign(e,r,n){return this._leafNode(new Cu(e,r,n))}add(e,r){return this._leafNode(new Nf(e,Q.operators.ADD,r))}code(e){return typeof e=="function"?e():e!==ce.nil&&this._leafNode(new Uf(e)),this}object(...e){let r=["{"];for(let[n,s]of e)r.length>1&&r.push(","),r.push(n),(n!==s||this.opts.es5)&&(r.push(":"),(0,ce.addCodeArg)(r,s));return r.push("}"),new ce._Code(r)}if(e,r,n){if(this._blockNode(new os(e)),r&&n)this.code(r).else().code(n).endIf();else if(r)this.code(r).endIf();else if(n)throw new Error('CodeGen: "else" body without "then" body');return this}elseIf(e){return this._elseNode(new os(e))}else(){return this._elseNode(new ho)}endIf(){return this._endBlockNode(os,ho)}_for(e,r){return this._blockNode(e),r&&this.code(r).endFor(),this}for(e,r){return this._for(new Vf(e),r)}forRange(e,r,n,s,o=this.opts.es5?sr.varKinds.var:sr.varKinds.let){let i=this._scope.toName(e);return this._for(new Bf(o,i,r,n),()=>s(i))}forOf(e,r,n,s=sr.varKinds.const){let o=this._scope.toName(e);if(this.opts.es5){let i=r instanceof ce.Name?r:this.var("_arr",r);return this.forRange("_i",0,(0,ce._)`${i}.length`,a=>{this.var(o,(0,ce._)`${i}[${a}]`),n(o)})}return this._for(new Du("of",s,o,r),()=>n(o))}forIn(e,r,n,s=this.opts.es5?sr.varKinds.var:sr.varKinds.const){if(this.opts.ownProperties)return this.forOf(e,(0,ce._)`Object.keys(${r})`,n);let o=this._scope.toName(e);return this._for(new Du("in",s,o,r),()=>n(o))}endFor(){return this._endBlockNode(is)}label(e){return this._leafNode(new Lf(e))}break(e){return this._leafNode(new qf(e))}return(e){let r=new ra;if(this._blockNode(r),this.code(e),r.nodes.length!==1)throw new Error('CodeGen: "return" should have one node');return this._endBlockNode(ra)}try(e,r,n){if(!r&&!n)throw new Error('CodeGen: "try" without "catch" and "finally"');let s=new Hf;if(this._blockNode(s),this.code(e),r){let o=this.name("e");this._currNode=s.catch=new na(o),r(o)}return n&&(this._currNode=s.finally=new sa,this.code(n)),this._endBlockNode(na,sa)}throw(e){return this._leafNode(new Ff(e))}block(e,r){return this._blockStarts.push(this._nodes.length),e&&this.code(e).endBlock(r),this}endBlock(e){let r=this._blockStarts.pop();if(r===void 0)throw new Error("CodeGen: not in self-balancing block");let n=this._nodes.length-r;if(n<0||e!==void 0&&n!==e)throw new Error(`CodeGen: wrong number of nodes: ${n} vs ${e} expected`);return this._nodes.length=r,this}func(e,r=ce.nil,n,s){return this._blockNode(new ta(e,r,n)),s&&this.code(s).endFunc(),this}endFunc(){return this._endBlockNode(ta)}optimize(e=1){for(;e-- >0;)this._root.optimizeNodes(),this._root.optimizeNames(this._root.names,this._constants)}_leafNode(e){return this._currNode.nodes.push(e),this}_blockNode(e){this._currNode.nodes.push(e),this._nodes.push(e)}_endBlockNode(e,r){let n=this._currNode;if(n instanceof e||r&&n instanceof r)return this._nodes.pop(),this;throw new Error(`CodeGen: not in block "${r?`${e.kind}/${r.kind}`:e.kind}"`)}_elseNode(e){let r=this._currNode;if(!(r instanceof os))throw new Error('CodeGen: "else" without "if"');return this._currNode=r.else=e,this}get _root(){return this._nodes[0]}get _currNode(){let e=this._nodes;return e[e.length-1]}set _currNode(e){let r=this._nodes;r[r.length-1]=e}};Q.CodeGen=Wf;function as(t,e){for(let r in e)t[r]=(t[r]||0)+(e[r]||0);return t}function Ou(t,e){return e instanceof ce._CodeOrName?as(t,e.names):t}function go(t,e,r){if(t instanceof ce.Name)return n(t);if(!s(t))return t;return new ce._Code(t._items.reduce((o,i)=>(i instanceof ce.Name&&(i=n(i)),i instanceof ce._Code?o.push(...i._items):o.push(i),o),[]));function n(o){let i=r[o.str];return i===void 0||e[o.str]!==1?o:(delete e[o.str],i)}function s(o){return o instanceof ce._Code&&o._items.some(i=>i instanceof ce.Name&&e[i.str]===1&&r[i.str]!==void 0)}}function eN(t,e){for(let r in e)t[r]=(t[r]||0)-(e[r]||0)}function tx(t){return typeof t=="boolean"||typeof t=="number"||t===null?!t:(0,ce._)`!${Kf(t)}`}Q.not=tx;var tN=rx(Q.operators.AND);function rN(...t){return t.reduce(tN)}Q.and=rN;var nN=rx(Q.operators.OR);function sN(...t){return t.reduce(nN)}Q.or=sN;function rx(t){return(e,r)=>e===ce.nil?r:r===ce.nil?e:(0,ce._)`${Kf(e)} ${t} ${Kf(r)}`}function Kf(t){return t instanceof ce.Name?t:(0,ce._)`(${t})`}});var le=S(re=>{"use strict";Object.defineProperty(re,"__esModule",{value:!0});re.checkStrictMode=re.getErrorPath=re.Type=re.useFunc=re.setEvaluated=re.evaluatedPropsToName=re.mergeEvaluated=re.eachItem=re.unescapeJsonPointer=re.escapeJsonPointer=re.escapeFragment=re.unescapeFragment=re.schemaRefOrVal=re.schemaHasRulesButRef=re.schemaHasRules=re.checkUnknownRules=re.alwaysValidSchema=re.toHash=void 0;var we=te(),oN=Qi();function iN(t){let e={};for(let r of t)e[r]=!0;return e}re.toHash=iN;function aN(t,e){return typeof e=="boolean"?e:Object.keys(e).length===0?!0:(ox(t,e),!ix(e,t.self.RULES.all))}re.alwaysValidSchema=aN;function ox(t,e=t.schema){let{opts:r,self:n}=t;if(!r.strictSchema||typeof e=="boolean")return;let s=n.RULES.keywords;for(let o in e)s[o]||ux(t,`unknown keyword: "${o}"`)}re.checkUnknownRules=ox;function ix(t,e){if(typeof t=="boolean")return!t;for(let r in t)if(e[r])return!0;return!1}re.schemaHasRules=ix;function cN(t,e){if(typeof t=="boolean")return!t;for(let r in t)if(r!=="$ref"&&e.all[r])return!0;return!1}re.schemaHasRulesButRef=cN;function uN({topSchemaRef:t,schemaPath:e},r,n,s){if(!s){if(typeof r=="number"||typeof r=="boolean")return r;if(typeof r=="string")return(0,we._)`${r}`}return(0,we._)`${t}${e}${(0,we.getProperty)(n)}`}re.schemaRefOrVal=uN;function lN(t){return ax(decodeURIComponent(t))}re.unescapeFragment=lN;function dN(t){return encodeURIComponent(Gf(t))}re.escapeFragment=dN;function Gf(t){return typeof t=="number"?`${t}`:t.replace(/~/g,"~0").replace(/\//g,"~1")}re.escapeJsonPointer=Gf;function ax(t){return t.replace(/~1/g,"/").replace(/~0/g,"~")}re.unescapeJsonPointer=ax;function pN(t,e){if(Array.isArray(t))for(let r of t)e(r);else e(t)}re.eachItem=pN;function nx({mergeNames:t,mergeToName:e,mergeValues:r,resultToName:n}){return(s,o,i,a)=>{let c=i===void 0?o:i instanceof we.Name?(o instanceof we.Name?t(s,o,i):e(s,o,i),i):o instanceof we.Name?(e(s,i,o),o):r(o,i);return a===we.Name&&!(c instanceof we.Name)?n(s,c):c}}re.mergeEvaluated={props:nx({mergeNames:(t,e,r)=>t.if((0,we._)`${r} !== true && ${e} !== undefined`,()=>{t.if((0,we._)`${e} === true`,()=>t.assign(r,!0),()=>t.assign(r,(0,we._)`${r} || {}`).code((0,we._)`Object.assign(${r}, ${e})`))}),mergeToName:(t,e,r)=>t.if((0,we._)`${r} !== true`,()=>{e===!0?t.assign(r,!0):(t.assign(r,(0,we._)`${r} || {}`),Yf(t,r,e))}),mergeValues:(t,e)=>t===!0?!0:{...t,...e},resultToName:cx}),items:nx({mergeNames:(t,e,r)=>t.if((0,we._)`${r} !== true && ${e} !== undefined`,()=>t.assign(r,(0,we._)`${e} === true ? true : ${r} > ${e} ? ${r} : ${e}`)),mergeToName:(t,e,r)=>t.if((0,we._)`${r} !== true`,()=>t.assign(r,e===!0?!0:(0,we._)`${r} > ${e} ? ${r} : ${e}`)),mergeValues:(t,e)=>t===!0?!0:Math.max(t,e),resultToName:(t,e)=>t.var("items",e)})};function cx(t,e){if(e===!0)return t.var("props",!0);let r=t.var("props",(0,we._)`{}`);return e!==void 0&&Yf(t,r,e),r}re.evaluatedPropsToName=cx;function Yf(t,e,r){Object.keys(r).forEach(n=>t.assign((0,we._)`${e}${(0,we.getProperty)(n)}`,!0))}re.setEvaluated=Yf;var sx={};function fN(t,e){return t.scopeValue("func",{ref:e,code:sx[e.code]||(sx[e.code]=new oN._Code(e.code))})}re.useFunc=fN;var Jf;(function(t){t[t.Num=0]="Num",t[t.Str=1]="Str"})(Jf||(re.Type=Jf={}));function mN(t,e,r){if(t instanceof we.Name){let n=e===Jf.Num;return r?n?(0,we._)`"[" + ${t} + "]"`:(0,we._)`"['" + ${t} + "']"`:n?(0,we._)`"/" + ${t}`:(0,we._)`"/" + ${t}.replace(/~/g, "~0").replace(/\\//g, "~1")`}return r?(0,we.getProperty)(t).toString():"/"+Gf(t)}re.getErrorPath=mN;function ux(t,e,r=t.opts.strictSchema){if(r){if(e=`strict mode: ${e}`,r===!0)throw new Error(e);t.self.logger.warn(e)}}re.checkStrictMode=ux});var Zr=S(Xf=>{"use strict";Object.defineProperty(Xf,"__esModule",{value:!0});var ot=te(),hN={data:new ot.Name("data"),valCxt:new ot.Name("valCxt"),instancePath:new ot.Name("instancePath"),parentData:new ot.Name("parentData"),parentDataProperty:new ot.Name("parentDataProperty"),rootData:new ot.Name("rootData"),dynamicAnchors:new ot.Name("dynamicAnchors"),vErrors:new ot.Name("vErrors"),errors:new ot.Name("errors"),this:new ot.Name("this"),self:new ot.Name("self"),scope:new ot.Name("scope"),json:new ot.Name("json"),jsonPos:new ot.Name("jsonPos"),jsonLen:new ot.Name("jsonLen"),jsonPart:new ot.Name("jsonPart")};Xf.default=hN});var oa=S(it=>{"use strict";Object.defineProperty(it,"__esModule",{value:!0});it.extendErrors=it.resetErrorsCount=it.reportExtraError=it.reportError=it.keyword$DataError=it.keywordError=void 0;var de=te(),zu=le(),mt=Zr();it.keywordError={message:({keyword:t})=>(0,de.str)`must pass "${t}" keyword validation`};it.keyword$DataError={message:({keyword:t,schemaType:e})=>e?(0,de.str)`"${t}" keyword must be ${e} ($data)`:(0,de.str)`"${t}" keyword is invalid ($data)`};function gN(t,e=it.keywordError,r,n){let{it:s}=t,{gen:o,compositeRule:i,allErrors:a}=s,c=px(t,e,r);n??(i||a)?lx(o,c):dx(s,(0,de._)`[${c}]`)}it.reportError=gN;function yN(t,e=it.keywordError,r){let{it:n}=t,{gen:s,compositeRule:o,allErrors:i}=n,a=px(t,e,r);lx(s,a),o||i||dx(n,mt.default.vErrors)}it.reportExtraError=yN;function vN(t,e){t.assign(mt.default.errors,e),t.if((0,de._)`${mt.default.vErrors} !== null`,()=>t.if(e,()=>t.assign((0,de._)`${mt.default.vErrors}.length`,e),()=>t.assign(mt.default.vErrors,null)))}it.resetErrorsCount=vN;function _N({gen:t,keyword:e,schemaValue:r,data:n,errsCount:s,it:o}){if(s===void 0)throw new Error("ajv implementation error");let i=t.name("err");t.forRange("i",s,mt.default.errors,a=>{t.const(i,(0,de._)`${mt.default.vErrors}[${a}]`),t.if((0,de._)`${i}.instancePath === undefined`,()=>t.assign((0,de._)`${i}.instancePath`,(0,de.strConcat)(mt.default.instancePath,o.errorPath))),t.assign((0,de._)`${i}.schemaPath`,(0,de.str)`${o.errSchemaPath}/${e}`),o.opts.verbose&&(t.assign((0,de._)`${i}.schema`,r),t.assign((0,de._)`${i}.data`,n))})}it.extendErrors=_N;function lx(t,e){let r=t.const("err",e);t.if((0,de._)`${mt.default.vErrors} === null`,()=>t.assign(mt.default.vErrors,(0,de._)`[${r}]`),(0,de._)`${mt.default.vErrors}.push(${r})`),t.code((0,de._)`${mt.default.errors}++`)}function dx(t,e){let{gen:r,validateName:n,schemaEnv:s}=t;s.$async?r.throw((0,de._)`new ${t.ValidationError}(${e})`):(r.assign((0,de._)`${n}.errors`,e),r.return(!1))}var cs={keyword:new de.Name("keyword"),schemaPath:new de.Name("schemaPath"),params:new de.Name("params"),propertyName:new de.Name("propertyName"),message:new de.Name("message"),schema:new de.Name("schema"),parentSchema:new de.Name("parentSchema")};function px(t,e,r){let{createErrors:n}=t.it;return n===!1?(0,de._)`{}`:bN(t,e,r)}function bN(t,e,r={}){let{gen:n,it:s}=t,o=[wN(s,r),SN(t,r)];return $N(t,e,o),n.object(...o)}function wN({errorPath:t},{instancePath:e}){let r=e?(0,de.str)`${t}${(0,zu.getErrorPath)(e,zu.Type.Str)}`:t;return[mt.default.instancePath,(0,de.strConcat)(mt.default.instancePath,r)]}function SN({keyword:t,it:{errSchemaPath:e}},{schemaPath:r,parentSchema:n}){let s=n?e:(0,de.str)`${e}/${t}`;return r&&(s=(0,de.str)`${s}${(0,zu.getErrorPath)(r,zu.Type.Str)}`),[cs.schemaPath,s]}function $N(t,{params:e,message:r},n){let{keyword:s,data:o,schemaValue:i,it:a}=t,{opts:c,propertyName:u,topSchemaRef:l,schemaPath:d}=a;n.push([cs.keyword,s],[cs.params,typeof e=="function"?e(t):e||(0,de._)`{}`]),c.messages&&n.push([cs.message,typeof r=="function"?r(t):r]),c.verbose&&n.push([cs.schema,i],[cs.parentSchema,(0,de._)`${l}${d}`],[mt.default.data,o]),u&&n.push([cs.propertyName,u])}});var mx=S(yo=>{"use strict";Object.defineProperty(yo,"__esModule",{value:!0});yo.boolOrEmptySchema=yo.topBoolOrEmptySchema=void 0;var xN=oa(),PN=te(),kN=Zr(),EN={message:"boolean schema is false"};function TN(t){let{gen:e,schema:r,validateName:n}=t;r===!1?fx(t,!1):typeof r=="object"&&r.$async===!0?e.return(kN.default.data):(e.assign((0,PN._)`${n}.errors`,null),e.return(!0))}yo.topBoolOrEmptySchema=TN;function IN(t,e){let{gen:r,schema:n}=t;n===!1?(r.var(e,!1),fx(t)):r.var(e,!0)}yo.boolOrEmptySchema=IN;function fx(t,e){let{gen:r,data:n}=t,s={gen:r,keyword:"false schema",data:n,schema:!1,schemaCode:!1,schemaValue:!1,params:{},it:t};(0,xN.reportError)(s,EN,void 0,e)}});var Qf=S(vo=>{"use strict";Object.defineProperty(vo,"__esModule",{value:!0});vo.getRules=vo.isJSONType=void 0;var RN=["string","number","integer","boolean","null","object","array"],AN=new Set(RN);function CN(t){return typeof t=="string"&&AN.has(t)}vo.isJSONType=CN;function DN(){let t={number:{type:"number",rules:[]},string:{type:"string",rules:[]},array:{type:"array",rules:[]},object:{type:"object",rules:[]}};return{types:{...t,integer:!0,boolean:!0,null:!0},rules:[{rules:[]},t.number,t.string,t.array,t.object],post:{rules:[]},all:{},keywords:{}}}vo.getRules=DN});var em=S(pn=>{"use strict";Object.defineProperty(pn,"__esModule",{value:!0});pn.shouldUseRule=pn.shouldUseGroup=pn.schemaHasRulesForType=void 0;function ON({schema:t,self:e},r){let n=e.RULES.types[r];return n&&n!==!0&&hx(t,n)}pn.schemaHasRulesForType=ON;function hx(t,e){return e.rules.some(r=>gx(t,r))}pn.shouldUseGroup=hx;function gx(t,e){var r;return t[e.keyword]!==void 0||((r=e.definition.implements)===null||r===void 0?void 0:r.some(n=>t[n]!==void 0))}pn.shouldUseRule=gx});var ia=S(at=>{"use strict";Object.defineProperty(at,"__esModule",{value:!0});at.reportTypeError=at.checkDataTypes=at.checkDataType=at.coerceAndCheckDataType=at.getJSONTypes=at.getSchemaTypes=at.DataType=void 0;var MN=Qf(),zN=em(),jN=oa(),K=te(),yx=le(),_o;(function(t){t[t.Correct=0]="Correct",t[t.Wrong=1]="Wrong"})(_o||(at.DataType=_o={}));function NN(t){let e=vx(t.type);if(e.includes("null")){if(t.nullable===!1)throw new Error("type: null contradicts nullable: false")}else{if(!e.length&&t.nullable!==void 0)throw new Error('"nullable" cannot be used without "type"');t.nullable===!0&&e.push("null")}return e}at.getSchemaTypes=NN;function vx(t){let e=Array.isArray(t)?t:t?[t]:[];if(e.every(MN.isJSONType))return e;throw new Error("type must be JSONType or JSONType[]: "+e.join(","))}at.getJSONTypes=vx;function LN(t,e){let{gen:r,data:n,opts:s}=t,o=qN(e,s.coerceTypes),i=e.length>0&&!(o.length===0&&e.length===1&&(0,zN.schemaHasRulesForType)(t,e[0]));if(i){let a=rm(e,n,s.strictNumbers,_o.Wrong);r.if(a,()=>{o.length?FN(t,e,o):nm(t)})}return i}at.coerceAndCheckDataType=LN;var _x=new Set(["string","number","integer","boolean","null"]);function qN(t,e){return e?t.filter(r=>_x.has(r)||e==="array"&&r==="array"):[]}function FN(t,e,r){let{gen:n,data:s,opts:o}=t,i=n.let("dataType",(0,K._)`typeof ${s}`),a=n.let("coerced",(0,K._)`undefined`);o.coerceTypes==="array"&&n.if((0,K._)`${i} == 'object' && Array.isArray(${s}) && ${s}.length == 1`,()=>n.assign(s,(0,K._)`${s}[0]`).assign(i,(0,K._)`typeof ${s}`).if(rm(e,s,o.strictNumbers),()=>n.assign(a,s))),n.if((0,K._)`${a} !== undefined`);for(let u of r)(_x.has(u)||u==="array"&&o.coerceTypes==="array")&&c(u);n.else(),nm(t),n.endIf(),n.if((0,K._)`${a} !== undefined`,()=>{n.assign(s,a),UN(t,a)});function c(u){switch(u){case"string":n.elseIf((0,K._)`${i} == "number" || ${i} == "boolean"`).assign(a,(0,K._)`"" + ${s}`).elseIf((0,K._)`${s} === null`).assign(a,(0,K._)`""`);return;case"number":n.elseIf((0,K._)`${i} == "boolean" || ${s} === null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agestra",
3
- "version": "4.13.1",
3
+ "version": "4.13.2",
4
4
  "description": "Multi-host AI orchestration toolkit for Claude Code, Codex CLI, and Gemini CLI",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.11.0",