@meyverick/agentic 5.0.2 → 5.1.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/AGENTS.md +1 -1
- package/CHANGELOG.md +15 -0
- package/README.md +2 -1
- package/package.json +5 -5
- package/scripts/{check-deps.mjs → check-deps.ts} +124 -59
- package/scripts/{git-dl.mjs → git-dl.ts} +11 -9
- package/skills/create-skill/SKILL.md +16 -16
- package/skills/create-skill/assets/templates/SKILL.md.template +1 -1
- package/skills/create-skill/evals/evals.json +4 -4
- package/skills/create-skill/evals/grading-template.json +1 -1
- package/skills/create-skill/references/component-decomposition.md +1 -1
- package/skills/create-skill/scripts/{audit-antipatterns.mjs → audit-antipatterns.ts} +75 -31
- package/skills/create-skill/scripts/{compute-benchmark.mjs → compute-benchmark.ts} +71 -30
- package/skills/create-skill/scripts/run-cold-eval.ts +202 -0
- package/skills/create-skill/scripts/{scaffold-skill.mjs → scaffold-skill.ts} +45 -25
- package/skills/create-skill/scripts/validate-routing.ts +218 -0
- package/skills/create-skill/scripts/{validate-structure.mjs → validate-structure.ts} +97 -36
- package/skills/okf-docs/SKILL.md +1 -1
- package/skills/okf-docs/evals/evals.json +2 -2
- package/skills/okf-docs/scripts/{validate-frontmatter.mjs → validate-frontmatter.ts} +73 -32
- package/skills/openspec-learn/references/evaluation-methodology.md +2 -2
- package/skills/openspec-pi-apply/SKILL.md +129 -0
- package/skills/openspec-pi-apply/references/rpc-protocol.md +43 -0
- package/skills/openspec-pi-apply/scripts/pi-rpc-apply.ts +421 -0
- package/skills/create-skill/scripts/run-cold-eval.mjs +0 -118
- package/skills/create-skill/scripts/validate-routing.mjs +0 -137
|
@@ -1,58 +1,91 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
2
|
/**
|
|
3
|
-
* validate-frontmatter.
|
|
4
|
-
* Usage:
|
|
3
|
+
* validate-frontmatter.ts — OKF v0.2 frontmatter gate
|
|
4
|
+
* Usage: bun validate-frontmatter.ts <document.md>
|
|
5
5
|
* Output: unified JSON envelope {target, pass, checks:[{id,status,detail}], summary}
|
|
6
6
|
*
|
|
7
7
|
* Checks: required keys (type/generated.by/at) · ISO 8601 formats · actor
|
|
8
8
|
* convention values · status enum · stale_after chronology.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { readFileSync, existsSync } from 'fs';
|
|
11
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
12
|
+
|
|
13
|
+
type CheckStatus = 'PASS' | 'FAIL' | 'WARN' | 'SKIP';
|
|
14
|
+
|
|
15
|
+
interface CheckEntry {
|
|
16
|
+
id: string;
|
|
17
|
+
status: CheckStatus;
|
|
18
|
+
detail: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ValidationSummary {
|
|
22
|
+
total: number;
|
|
23
|
+
pass: number;
|
|
24
|
+
fail: number;
|
|
25
|
+
warn: number;
|
|
26
|
+
skip: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface ValidationReport {
|
|
30
|
+
target: string;
|
|
31
|
+
pass: boolean;
|
|
32
|
+
checks: CheckEntry[];
|
|
33
|
+
summary: ValidationSummary;
|
|
34
|
+
}
|
|
12
35
|
|
|
13
36
|
const docPath = process.argv[2];
|
|
14
37
|
|
|
15
|
-
if (!docPath) {
|
|
16
|
-
|
|
38
|
+
if (!docPath || docPath === '-h' || docPath === '--help') {
|
|
39
|
+
if (docPath === '-h' || docPath === '--help') {
|
|
40
|
+
console.log('Usage: bun validate-frontmatter.ts <document.md>');
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
console.error(JSON.stringify({ error: 'Usage: bun validate-frontmatter.ts <document.md>' }));
|
|
17
44
|
process.exit(2);
|
|
18
45
|
}
|
|
19
46
|
|
|
20
47
|
if (!existsSync(docPath)) {
|
|
21
|
-
|
|
48
|
+
const report: ValidationReport = {
|
|
22
49
|
target: docPath,
|
|
23
50
|
pass: false,
|
|
24
51
|
checks: [{ id: 'okf.file', status: 'FAIL', detail: 'Document not found' }],
|
|
25
52
|
summary: { total: 1, pass: 0, fail: 1, warn: 0, skip: 0 }
|
|
26
|
-
}
|
|
53
|
+
};
|
|
54
|
+
console.log(JSON.stringify(report));
|
|
27
55
|
process.exit(1);
|
|
28
56
|
}
|
|
29
57
|
|
|
30
58
|
const content = readFileSync(docPath, 'utf-8');
|
|
31
|
-
const checks = [];
|
|
59
|
+
const checks: CheckEntry[] = [];
|
|
32
60
|
|
|
33
|
-
const add = (id, ok, detail
|
|
34
|
-
|
|
61
|
+
const add = (id: string, ok: boolean, detail: string): void => {
|
|
62
|
+
checks.push({ id, status: ok ? 'PASS' : 'FAIL', detail });
|
|
63
|
+
};
|
|
64
|
+
const warn = (id: string, detail: string): void => {
|
|
65
|
+
checks.push({ id, status: 'WARN', detail });
|
|
66
|
+
};
|
|
35
67
|
|
|
36
68
|
// Extract frontmatter
|
|
37
69
|
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
38
70
|
if (!fmMatch) {
|
|
39
|
-
|
|
71
|
+
const report: ValidationReport = {
|
|
40
72
|
target: docPath,
|
|
41
73
|
pass: false,
|
|
42
74
|
checks: [{ id: 'okf.frontmatter', status: 'FAIL', detail: 'No frontmatter block found' }],
|
|
43
75
|
summary: { total: 1, pass: 0, fail: 1, warn: 0, skip: 0 }
|
|
44
|
-
}
|
|
76
|
+
};
|
|
77
|
+
console.log(JSON.stringify(report));
|
|
45
78
|
process.exit(1);
|
|
46
79
|
}
|
|
47
80
|
add('okf.frontmatter', true, 'Frontmatter block present');
|
|
48
81
|
|
|
49
82
|
// Parse simple YAML subset (top-level + one nested level for generated)
|
|
50
83
|
const fm = fmMatch[1];
|
|
51
|
-
function get(key) {
|
|
84
|
+
function get(key: string): string | null {
|
|
52
85
|
const m = fm.match(new RegExp(`^${key}:\\s*(.+)$`, 'm'));
|
|
53
86
|
return m ? m[1].trim().replace(/^["']|["']$/g, '') : null;
|
|
54
87
|
}
|
|
55
|
-
function getNested(parent, key) {
|
|
88
|
+
function getNested(parent: string, key: string): string | null {
|
|
56
89
|
const m = fm.match(new RegExp(`^${parent}:\\s*\\{\\s*([^}]*)\\}`, 'm'));
|
|
57
90
|
if (!m) return null;
|
|
58
91
|
const inner = m[1].match(new RegExp(`${key}:\\s*([^,}]+)`));
|
|
@@ -69,14 +102,22 @@ const at = getNested('generated', 'at');
|
|
|
69
102
|
add('okf.generated-by', !!by, by ? `generated.by = ${by}` : "Missing required 'generated.by'");
|
|
70
103
|
|
|
71
104
|
const actorRe = /^([a-z0-9][a-z0-9-]*\/\d+(\.\d+)*|human:[a-z0-9-]+|process:[a-z0-9-]+)$/;
|
|
72
|
-
add(
|
|
105
|
+
add(
|
|
106
|
+
'okf.actor-convention',
|
|
73
107
|
!!by && actorRe.test(by),
|
|
74
|
-
by
|
|
108
|
+
by
|
|
109
|
+
? actorRe.test(by)
|
|
110
|
+
? `Actor '${by}' matches convention`
|
|
111
|
+
: `Actor '${by}' violates convention (<producer>/<version> | human:<id> | process:<id>)`
|
|
112
|
+
: 'No actor to check'
|
|
113
|
+
);
|
|
75
114
|
|
|
76
115
|
const isoRe = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?Z)?$/;
|
|
77
|
-
add(
|
|
116
|
+
add(
|
|
117
|
+
'okf.generated-at-format',
|
|
78
118
|
!!at && isoRe.test(at),
|
|
79
|
-
at ? (isoRe.test(at) ? `generated.at = ${at}` : `'${at}' is not ISO 8601`) : "Missing required 'generated.at'"
|
|
119
|
+
at ? (isoRe.test(at) ? `generated.at = ${at}` : `'${at}' is not ISO 8601`) : "Missing required 'generated.at'"
|
|
120
|
+
);
|
|
80
121
|
|
|
81
122
|
// sources (WARN if missing — recommended not mandatory)
|
|
82
123
|
const hasSources = /^sources:/m.test(fm);
|
|
@@ -87,13 +128,10 @@ const status = get('status');
|
|
|
87
128
|
if (!status) {
|
|
88
129
|
warn('okf.status', "Missing 'status' (draft | stable | deprecated)");
|
|
89
130
|
} else if (!['draft', 'stable', 'deprecated'].includes(status)) {
|
|
90
|
-
|
|
131
|
+
add('okf.status', false, `Invalid status '${status}' — must be draft | stable | deprecated`);
|
|
91
132
|
} else {
|
|
92
133
|
add('okf.status', true, `status = ${status}`);
|
|
93
134
|
}
|
|
94
|
-
function failStatus(value) {
|
|
95
|
-
add('okf.status', false, `Invalid status '${value}' — must be draft | stable | deprecated`);
|
|
96
|
-
}
|
|
97
135
|
|
|
98
136
|
// stale_after chronology vs generated.at
|
|
99
137
|
const stale = get('stale_after');
|
|
@@ -102,8 +140,11 @@ if (stale) {
|
|
|
102
140
|
add('okf.stale-after', false, `stale_after '${stale}' is not YYYY-MM-DD`);
|
|
103
141
|
} else if (at) {
|
|
104
142
|
const genDay = at.slice(0, 10);
|
|
105
|
-
add(
|
|
106
|
-
stale
|
|
143
|
+
add(
|
|
144
|
+
'okf.stale-after',
|
|
145
|
+
stale >= genDay,
|
|
146
|
+
stale >= genDay ? `stale_after ${stale} ≥ generated ${genDay}` : `stale_after ${stale} predates generation ${genDay}`
|
|
147
|
+
);
|
|
107
148
|
} else {
|
|
108
149
|
add('okf.stale-after', true, `stale_after = ${stale} (no generated.at to compare)`);
|
|
109
150
|
}
|
|
@@ -112,19 +153,19 @@ if (stale) {
|
|
|
112
153
|
}
|
|
113
154
|
|
|
114
155
|
// Unified envelope
|
|
115
|
-
const fails = checks.filter(c => c.status === 'FAIL').length;
|
|
116
|
-
|
|
156
|
+
const fails = checks.filter((c) => c.status === 'FAIL').length;
|
|
157
|
+
const report: ValidationReport = {
|
|
117
158
|
target: docPath,
|
|
118
159
|
pass: fails === 0,
|
|
119
160
|
checks,
|
|
120
161
|
summary: {
|
|
121
162
|
total: checks.length,
|
|
122
|
-
pass: checks.filter(c => c.status === 'PASS').length,
|
|
163
|
+
pass: checks.filter((c) => c.status === 'PASS').length,
|
|
123
164
|
fail: fails,
|
|
124
|
-
warn: checks.filter(c => c.status === 'WARN').length,
|
|
125
|
-
skip: checks.filter(c => c.status === 'SKIP').length
|
|
165
|
+
warn: checks.filter((c) => c.status === 'WARN').length,
|
|
166
|
+
skip: checks.filter((c) => c.status === 'SKIP').length
|
|
126
167
|
}
|
|
127
|
-
}
|
|
168
|
+
};
|
|
128
169
|
|
|
170
|
+
console.log(JSON.stringify(report));
|
|
129
171
|
process.exit(fails > 0 ? 1 : 0);
|
|
130
|
-
|
|
@@ -10,13 +10,13 @@ Before applying improvements:
|
|
|
10
10
|
|
|
11
11
|
1. **Structural validation**:
|
|
12
12
|
```bash
|
|
13
|
-
project/skills/create-skill/scripts/validate-structure.
|
|
13
|
+
bun project/skills/create-skill/scripts/validate-structure.ts <skill-dir>
|
|
14
14
|
```
|
|
15
15
|
Extract: pass/fail, errors, warnings
|
|
16
16
|
|
|
17
17
|
2. **Antipattern audit**:
|
|
18
18
|
```bash
|
|
19
|
-
project/skills/create-skill/scripts/audit-antipatterns.
|
|
19
|
+
bun project/skills/create-skill/scripts/audit-antipatterns.ts <skill-dir>
|
|
20
20
|
```
|
|
21
21
|
Extract: pass/fail, violation count, violations
|
|
22
22
|
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: openspec-pi-apply
|
|
3
|
+
description: >
|
|
4
|
+
Delegate OpenSpec change task implementation to a headless pi worker agent via JSON-RPC.
|
|
5
|
+
Use when the user wants to apply an OpenSpec change using pi as a worker engine,
|
|
6
|
+
saying "pi apply", "opsx pi apply", or "apply change with pi".
|
|
7
|
+
Do NOT use when applying changes directly without pi (use openspec-apply-change),
|
|
8
|
+
or when proposing/planning changes (use openspec-propose).
|
|
9
|
+
allowed-tools: Bash(bun:*), Bash(openspec:*), Read, Grep
|
|
10
|
+
license: MIT
|
|
11
|
+
compatibility: Requires pi CLI, bun, and openspec CLI.
|
|
12
|
+
metadata:
|
|
13
|
+
author: agentic
|
|
14
|
+
version: "1.0.0"
|
|
15
|
+
positive_triggers:
|
|
16
|
+
- "apply change using pi"
|
|
17
|
+
- "pi apply change"
|
|
18
|
+
- "openspec pi apply"
|
|
19
|
+
- "delegate task implementation to pi"
|
|
20
|
+
anti_triggers:
|
|
21
|
+
- "implement change directly yourself"
|
|
22
|
+
- "apply change without pi"
|
|
23
|
+
- "openspec apply change"
|
|
24
|
+
- "propose a new change"
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# OpenSpec Pi Apply Workflow
|
|
28
|
+
|
|
29
|
+
Delegate task execution for an active OpenSpec change to a headless `pi` worker engine communicating over JSON-RPC. Antigravity acts as architectural supervisor, triaging worker questions and enforcing verification gates.
|
|
30
|
+
|
|
31
|
+
## Contrast Matrix
|
|
32
|
+
|
|
33
|
+
| Dimension | Direct Supervisor (`openspec-apply-change`) | Headless Pi Worker (`openspec-pi-apply`) | Why Different |
|
|
34
|
+
| :--- | :--- | :--- | :--- |
|
|
35
|
+
| **Execution** | Supervisor edits project files directly in turn context | Child process worker (`pi -a -c --mode rpc`) executes edits | Prevents supervisor context bloat & high turn latency |
|
|
36
|
+
| **Supervision** | Self-directed implementation | Supervisor monitors tool events & validates completion gates | Decouples code authoring from architectural oversight |
|
|
37
|
+
| **Clarifications** | Halts and asks human immediately | Supervisor triages autonomously against change artifacts | Eliminates unnecessary user interruptions for specified details |
|
|
38
|
+
|
|
39
|
+
## Anti-Examples (What NOT to do)
|
|
40
|
+
|
|
41
|
+
- **Do NOT edit project files directly** in this workflow. Task implementation is delegated to the worker process via `.agents/skills/openspec-pi-apply/scripts/pi-rpc-apply.ts`.
|
|
42
|
+
- **Do NOT pipe raw `pi` stdout directly** into conversational logs. Always use the bridge runner to filter high-frequency token deltas and prevent buffer stalls.
|
|
43
|
+
- **Do NOT guess unstated requirements** when the worker pauses for clarification. If an answer cannot be grounded in `specs/`, `design.md`, or `AGENTS.md`, escalate to the user.
|
|
44
|
+
- **Do NOT mark the change complete** based solely on worker claims. Verify that `openspec instructions apply --change <name> --json` confirms 0 remaining tasks.
|
|
45
|
+
|
|
46
|
+
## Workflow — 5 Steps
|
|
47
|
+
|
|
48
|
+
### Step 1: Pre-Flight & Change Discovery
|
|
49
|
+
|
|
50
|
+
1. Identify target change name (from user input or active changes):
|
|
51
|
+
```bash
|
|
52
|
+
openspec list --json
|
|
53
|
+
```
|
|
54
|
+
2. Verify that planning artifacts are complete:
|
|
55
|
+
```bash
|
|
56
|
+
openspec status --change "<name>" --json
|
|
57
|
+
```
|
|
58
|
+
Ensure `isPlanningComplete: true`. If planning is incomplete, advise completing artifacts with `/openspec-continue-change` first.
|
|
59
|
+
|
|
60
|
+
### Step 2: Spawn Pi Worker Engine
|
|
61
|
+
|
|
62
|
+
Run the bridge runner from the workspace root:
|
|
63
|
+
```bash
|
|
64
|
+
bun run .agents/skills/openspec-pi-apply/scripts/pi-rpc-apply.ts --change "<name>"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
*(For low-level RPC framing specifications, see [references/rpc-protocol.md](references/rpc-protocol.md).)*
|
|
68
|
+
|
|
69
|
+
The runner:
|
|
70
|
+
- Resolves workspace root and spawns `pi -a -c --mode rpc`
|
|
71
|
+
- Transmits `/skill:openspec-apply-change <name>` over stdin
|
|
72
|
+
- Filters raw token noise, emitting clean progress logs (`⚙ [pi:tool] Invoking: ...`)
|
|
73
|
+
- Detects `agent_settled` upon turn completion
|
|
74
|
+
|
|
75
|
+
### Step 3: Triage Worker Settlement State
|
|
76
|
+
|
|
77
|
+
Evaluate the runner's exit status:
|
|
78
|
+
|
|
79
|
+
#### Case A: `[STATUS] COMPLETED`
|
|
80
|
+
All tasks in `tasks.md` are marked complete (`remaining: 0`).
|
|
81
|
+
- Proceed directly to **Step 5: Completion Verification**.
|
|
82
|
+
|
|
83
|
+
#### Case B: `[STATUS] PAUSED_FOR_CLARIFICATION`
|
|
84
|
+
Worker paused with remaining tasks or posted a question before finishing.
|
|
85
|
+
1. Read the worker's question from the runner log.
|
|
86
|
+
2. Cross-reference the question against:
|
|
87
|
+
- `openspec/changes/<name>/specs/**/*.md`
|
|
88
|
+
- `openspec/changes/<name>/design.md`
|
|
89
|
+
- `openspec/changes/<name>/proposal.md`
|
|
90
|
+
- `AGENTS.md`
|
|
91
|
+
3. **Autonomous Resolution**:
|
|
92
|
+
- If the answer is documented in specifications or conventions, formulate the concise clarification grounded in the artifacts and resume worker execution:
|
|
93
|
+
```bash
|
|
94
|
+
bun run .agents/skills/openspec-pi-apply/scripts/pi-rpc-apply.ts --change "<name>" --reply "<clarification-answer>"
|
|
95
|
+
```
|
|
96
|
+
- Return to **Step 3** to inspect the next settlement state.
|
|
97
|
+
4. **Human Escalation**:
|
|
98
|
+
- If the question involves domain ambiguity, product preference, or missing credentials not covered by specs:
|
|
99
|
+
- Ask the user directly.
|
|
100
|
+
- Once the user answers, resume worker execution:
|
|
101
|
+
```bash
|
|
102
|
+
bun run .agents/skills/openspec-pi-apply/scripts/pi-rpc-apply.ts --change "<name>" --reply "<user-answer>"
|
|
103
|
+
```
|
|
104
|
+
- Return to **Step 3**.
|
|
105
|
+
|
|
106
|
+
#### Case C: `[STATUS] FAILED`
|
|
107
|
+
Worker exited with an error or timed out.
|
|
108
|
+
- Inspect stderr and diagnostic logs.
|
|
109
|
+
- Report failure details to user and pause.
|
|
110
|
+
|
|
111
|
+
### Step 4: Resume Iteration Loop
|
|
112
|
+
|
|
113
|
+
Repeat Step 3 until `[STATUS] COMPLETED` is reached or user intervention is requested.
|
|
114
|
+
|
|
115
|
+
### Step 5: Completion Verification
|
|
116
|
+
|
|
117
|
+
1. Run OpenSpec apply inspection:
|
|
118
|
+
```bash
|
|
119
|
+
openspec instructions apply --change "<name>" --json
|
|
120
|
+
```
|
|
121
|
+
2. Confirm `progress.remaining === 0`.
|
|
122
|
+
3. Run project verification suite (linters, typecheck, or tests) to confirm workspace health:
|
|
123
|
+
```bash
|
|
124
|
+
openspec validate --change "<name>"
|
|
125
|
+
```
|
|
126
|
+
4. Present final implementation summary:
|
|
127
|
+
- Change name and status
|
|
128
|
+
- Completed task summary
|
|
129
|
+
- Prompt user to archive: "All tasks complete! You can archive this change with `/openspec-archive-change <name>`."
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Pi JSON-RPC Protocol Reference (Level 2)
|
|
2
|
+
|
|
3
|
+
This reference outlines the JSON-RPC framing and event specifications used by `scripts/pi-rpc-apply.ts` to control `pi -a -c --mode rpc`.
|
|
4
|
+
|
|
5
|
+
## Process Invocation Flags
|
|
6
|
+
|
|
7
|
+
- `-a` (`--approve`): Auto-approves operations within the project scope, preventing interactive confirmation prompts.
|
|
8
|
+
- `-c` (`--continue`): Maintains conversational session memory and context across turns and process restarts.
|
|
9
|
+
- `--mode rpc`: Activates bidirectional JSON-RPC 2.0 streaming over standard I/O.
|
|
10
|
+
|
|
11
|
+
## Standard Input Commands
|
|
12
|
+
|
|
13
|
+
### Initial Apply Prompt
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"id": "prompt-1",
|
|
17
|
+
"type": "prompt",
|
|
18
|
+
"message": "/skill:openspec-apply-change <change-name>"
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
*Note*: `pi` natively expands `/skill:name` commands prior to session execution.
|
|
22
|
+
|
|
23
|
+
### Clarification Reply
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"id": "prompt-reply",
|
|
27
|
+
"type": "prompt",
|
|
28
|
+
"message": "<clarification-answer>"
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Standard Output Stream & Framing
|
|
33
|
+
|
|
34
|
+
Records are strictly formatted as single-line JSON objects separated by LF (`\n`):
|
|
35
|
+
|
|
36
|
+
1. **`message_update` (suppressed by runner)**:
|
|
37
|
+
Emits streaming deltas (`text_delta`, `thinking_delta`). Filtered out to avoid context flooding.
|
|
38
|
+
2. **`toolcall_start` / `toolcall_end`**:
|
|
39
|
+
Emitted when `pi` executes workspace tools (`read_file`, `write_to_file`, `run_command`).
|
|
40
|
+
3. **`message_end`**:
|
|
41
|
+
Emitted when the assistant finishes a response turn. Captured to extract any worker questions.
|
|
42
|
+
4. **`agent_settled`**:
|
|
43
|
+
Signals that the agent has settled and has no remaining automatic work.
|