@tea-agent/loop-agent 0.12.0 → 0.13.0-beta.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 +155 -153
- package/CHANGELOG.md +338 -265
- package/README.md +345 -298
- package/bin/agent-worker.js +22 -22
- package/bin/loop-agent.js +21 -21
- package/dist/application/dag/generate-task-dag.js +28 -28
- package/dist/application/evaluation/candidate-hash.js +75 -0
- package/dist/application/evaluation/candidate.js +52 -0
- package/dist/application/evaluation/replay.js +289 -0
- package/dist/application/evaluation/types.js +130 -0
- package/dist/cli/command-definitions.js +27 -7
- package/dist/cli/program.js +8 -4
- package/dist/commands/cursor-prompt.js +6 -6
- package/dist/commands/eval.js +235 -0
- package/dist/commands/init.js +544 -506
- package/dist/commands/knowledge.js +129 -31
- package/dist/commands/loop-benchmark.js +11 -11
- package/dist/commands/pi-reuse-benchmark.js +16 -16
- package/dist/executors/pi-sdk-executor.js +38 -24
- package/dist/executors/shell-executor.js +34 -2
- package/dist/executors/shell-presets.js +20 -0
- package/dist/executors/shell-verification.js +7 -0
- package/dist/governance/manifest-types.js +4 -0
- package/dist/infrastructure/evaluation/candidate-store.js +435 -0
- package/dist/infrastructure/evaluation/store.js +40 -0
- package/dist/sidecars/cursor-prompt/executor.js +1 -1
- package/dist/task/config-types.js +28 -1
- package/dist/task/runtime.js +27 -27
- package/dist/worker/cli.js +96 -1
- package/dist/worker/delivery/package.js +3 -3
- package/dist/worker/feature/decision-loader.js +37 -6
- package/dist/worker/feature/next-action.js +10 -2
- package/dist/worker/feature/ready-plan-projection.js +81 -0
- package/dist/worker/feature/reducer.js +2 -1
- package/dist/worker/feature/review.js +19 -2
- package/dist/worker/feature/run.js +27 -2
- package/dist/worker/follow-up/approve.js +5 -2
- package/dist/worker/follow-up/factory.js +1 -1
- package/dist/worker/observability/read-model.js +246 -41
- package/dist/worker/observe/routes.js +173 -15
- package/dist/worker/observe/spec-evidence.js +281 -0
- package/dist/worker/observe/static/api.js +46 -27
- package/dist/worker/observe/static/app.js +150 -150
- package/dist/worker/observe/static/constants.js +148 -148
- package/dist/worker/observe/static/copy.js +67 -67
- package/dist/worker/observe/static/dag-helpers.js +172 -172
- package/dist/worker/observe/static/dag-layout.d.ts +31 -31
- package/dist/worker/observe/static/dag-layout.js +83 -83
- package/dist/worker/observe/static/dag-model.js +72 -72
- package/dist/worker/observe/static/dom.js +61 -61
- package/dist/worker/observe/static/format-pool.js +67 -67
- package/dist/worker/observe/static/format.js +292 -292
- package/dist/worker/observe/static/index.html +308 -308
- package/dist/worker/observe/static/kpi.js +94 -94
- package/dist/worker/observe/static/relations.js +133 -128
- package/dist/worker/observe/static/router.js +93 -85
- package/dist/worker/observe/static/run-processing.js +148 -148
- package/dist/worker/observe/static/shell-chrome.js +68 -68
- package/dist/worker/observe/static/state.js +253 -253
- package/dist/worker/observe/static/styles.css +1902 -1890
- package/dist/worker/observe/static/views/batch.js +227 -226
- package/dist/worker/observe/static/views/dag-graph.js +172 -172
- package/dist/worker/observe/static/views/dag-inspector.js +607 -477
- package/dist/worker/observe/static/views/dag.js +362 -362
- package/dist/worker/observe/static/views/dashboard.js +445 -442
- package/dist/worker/observe/static/views/failures.js +143 -143
- package/dist/worker/observe/static/views/feature.js +492 -453
- package/dist/worker/observe/static/views/pool.js +350 -347
- package/dist/worker/observe/static/views/run.js +453 -453
- package/dist/worker/observe/static/views/session-timeline.js +205 -205
- package/dist/worker/observe/static/views/shell.js +7 -7
- package/dist/worker/observe/static/views/task.js +314 -260
- package/dist/worker/observe/static/views/timeline.js +163 -163
- package/dist/worker/pool/doctor.js +165 -0
- package/dist/worker/pool/migrate-state.js +303 -0
- package/dist/worker/pool/run-store.js +205 -17
- package/dist/worker/pool/types.js +17 -1
- package/dist/worker/pool/validation.js +100 -15
- package/dist/worker/report/morning-report.js +12 -2
- package/dist/worker/runner/run-ready.js +41 -26
- package/dist/worker/task-graph/ready-planner.js +136 -0
- package/dist/workflows/dag/backend-test-analysis-contract.js +120 -0
- package/dist/workflows/dag/canvas-observer.js +275 -275
- package/dist/workflows/dag/convergence/controller.js +16 -8
- package/dist/workflows/dag/dynamic-runtime/map.js +90 -2
- package/dist/workflows/dag/failure-routing.js +12 -1
- package/dist/workflows/dag/init-hybrid.js +2404 -360
- package/dist/workflows/dag/node-execution.js +9 -0
- package/dist/workflows/dag/prompt.js +9 -0
- package/dist/workflows/dag/report.js +35 -1
- package/dist/workflows/dag/runner.js +28 -2
- package/dist/workflows/dag/task-demand-routing.js +383 -0
- package/dist/workflows/dag/types.js +51 -13
- package/dist/workflows/dag/upstream-artifacts.js +1 -0
- package/dist/workflows/dag/validate.js +59 -1
- package/docs/README.md +106 -104
- package/docs/agent-dag-recovery-playbook.md +195 -184
- package/docs/agent-dag-runner.md +67 -67
- package/docs/architecture/README.md +26 -26
- package/docs/architecture/dag-execution.md +140 -140
- package/docs/architecture/evolution.md +54 -53
- package/docs/architecture/facts-and-state.md +71 -58
- package/docs/architecture/runtime-boundaries.md +191 -191
- package/docs/architecture/system-overview.md +93 -93
- package/docs/architecture/worker-and-feature.md +85 -81
- package/docs/cursor-prompt-sidecar.md +36 -36
- package/docs/decisions/README.md +18 -15
- package/docs/design/README.md +167 -77
- package/docs/development-principles.md +73 -73
- package/docs/exec-plans/README.md +6 -6
- package/docs/exec-plans/active/README.md +15 -9
- package/docs/exec-plans/completed/README.md +85 -73
- package/docs/feature-workflow.md +389 -261
- package/docs/harness-methodology-debugging.md +153 -153
- package/docs/harness-methodology-tdd.md +130 -130
- package/docs/harness-methodology-verification.md +27 -27
- package/docs/init-surface.manifest.json +289 -280
- package/docs/loop-agent-harness.md +142 -130
- package/docs/production-readiness.md +96 -96
- package/docs/progress/README.md +64 -54
- package/docs/reports/README.md +117 -94
- package/docs/skills/README.md +7 -7
- package/docs/skills/vetted-skill-registry.md +29 -27
- package/docs/templates/adr.md +60 -60
- package/docs/templates/agent-dag-authority-surface-audit.prompt.md +94 -94
- package/docs/templates/agent-dag-decision-envelope.schema.json +213 -213
- package/docs/templates/agent-dag-decision-gate-dogfood-report.md +117 -117
- package/docs/templates/agent-dag-decision-gate.prompt.md +246 -246
- package/docs/templates/agent-dag-process-supervisor.prompt.md +98 -98
- package/docs/templates/agent-dag-report.schema.json +473 -473
- package/docs/templates/agent-dag-review-verdict.prompt.md +68 -68
- package/docs/templates/agent-dag.base.json +190 -190
- package/docs/templates/agent-dag.final-verification.json +185 -185
- package/docs/templates/agent-dag.schema.json +411 -383
- package/docs/templates/agent-dag.supervised-implementation.json +501 -501
- package/docs/templates/backend-test-analysis.schema.json +44 -0
- package/docs/templates/backend-test-dag.generate-pytest.prompt.md +202 -139
- package/docs/templates/backend-test-dag.json +311 -276
- package/docs/templates/backend-test-dag.retrospect.prompt.md +125 -125
- package/docs/templates/backend-test-dag.review-cases.prompt.md +81 -81
- package/docs/templates/exec-plan.md +64 -64
- package/docs/templates/feature-spec.md +53 -53
- package/docs/templates/frontend-design-contract.md +42 -33
- package/docs/templates/frontend-task-constraints.md +35 -25
- package/docs/templates/frontend-task-requirement.md +70 -61
- package/docs/templates/frontend-test-dag.generate-cases.prompt.md +5 -0
- package/docs/templates/frontend-test-dag.json +23 -0
- package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +3 -0
- package/docs/templates/frontend-test-dag.retrospect.prompt.md +3 -0
- package/docs/templates/frontend-test-dag.review-cases.prompt.md +3 -0
- package/docs/templates/frontend-test-dag.review-execution.prompt.md +3 -0
- package/docs/templates/harness.schema.json +221 -221
- package/docs/templates/hybrid-dag.json +188 -188
- package/docs/templates/init-evolution-review.md +35 -35
- package/docs/templates/interactive-ui-round2-experiment.md +66 -66
- package/docs/templates/knowledge-graph-bootstrap-dag.json +118 -0
- package/docs/templates/knowledge-sync-dag.json +178 -0
- package/docs/templates/knowledge-sync-draft.schema.json +71 -0
- package/docs/templates/product-line/AGENTS.md +8 -8
- package/docs/templates/product-line/README.md +9 -9
- package/docs/templates/product-line/acceptance.yaml +14 -14
- package/docs/templates/product-line/closeout.yaml +9 -9
- package/docs/templates/product-line/design.md +13 -13
- package/docs/templates/product-line/links.md +10 -10
- package/docs/templates/product-line/requirement.md +17 -17
- package/docs/templates/product-line/task-graph.yaml +15 -15
- package/docs/templates/product-line/task.yaml +64 -64
- package/docs/templates/product-line/test-plan.md +7 -7
- package/docs/templates/production-readiness-checklist.md +57 -57
- package/docs/templates/progress-log.md +17 -17
- package/docs/templates/project-start-checklist.md +9 -9
- package/docs/templates/qa-report.md +48 -48
- package/docs/templates/sprint-contract.md +29 -29
- package/docs/templates/worker-dogfood-evidence.md +80 -80
- package/docs/templates/worker-dogfood-setup.md +68 -68
- package/docs/verification-matrix.md +70 -66
- package/examples/decision-gate-agent-dag.json +177 -177
- package/examples/example-dag.json +46 -46
- package/examples/hybrid-loop-agent-dag.json +189 -189
- package/harness.json +66 -66
- package/package.json +88 -46
- package/scripts/check-product-line-docs.sh +29 -29
- package/scripts/check-task-pool-root.sh +32 -32
- package/scripts/kb-bootstrap-init-skeleton.sh +240 -0
- package/scripts/kb-graph-incremental-prepare.mjs +386 -0
- package/scripts/kb-graph-incremental-prepare.sh +5 -0
- package/scripts/kb-graph-materialize.mjs +105 -0
- package/scripts/kb-graph-materialize.sh +4 -0
- package/scripts/kb-graph-promote.mjs +164 -0
- package/scripts/kb-graph-promote.sh +4 -0
- package/scripts/kb-query.mjs +554 -0
- package/scripts/kb-query.sh +5 -0
- package/skills/agent-worker/SKILL.md +39 -37
- package/skills/agent-worker/references/agent-worker-operator.md +60 -43
- package/skills/ai-engineering-context/SKILL.md +48 -48
- package/skills/analyze-product-dependencies/SKILL.md +67 -0
- package/skills/analyze-product-dependencies/agents/openai.yaml +4 -0
- package/skills/analyze-product-dependencies/references/api-documentation-schema.md +30 -0
- package/skills/analyze-product-dependencies/references/dependency-analysis-schema.md +28 -0
- package/skills/analyze-product-dependencies/references/example.md +76 -0
- package/skills/analyze-product-dependencies/references/forward-test-cases.md +35 -0
- package/skills/analyze-product-dependencies/references/input-contract.md +11 -0
- package/skills/analyze-product-dependencies/references/scouting-rules.md +61 -0
- package/skills/analyze-product-dependencies/scripts/test-validators.mjs +267 -0
- package/skills/analyze-product-dependencies/scripts/validate-api-documentation.mjs +101 -0
- package/skills/analyze-product-dependencies/scripts/validate-dependency-analysis.mjs +142 -0
- package/skills/analyze-product-dependencies/scripts/validate-product-requirement-input.mjs +76 -0
- package/skills/analyze-product-dependencies/scripts/validation-helpers.mjs +146 -0
- package/skills/analyze-product-requirements/SKILL.md +90 -0
- package/skills/analyze-product-requirements/agents/openai.yaml +4 -0
- package/skills/analyze-product-requirements/references/acceptance-criteria.md +91 -0
- package/skills/analyze-product-requirements/references/clarification-and-knowledge.md +56 -0
- package/skills/analyze-product-requirements/references/example.md +86 -0
- package/skills/analyze-product-requirements/references/forward-test-cases.md +66 -0
- package/skills/analyze-product-requirements/references/product-analysis-schema.md +32 -0
- package/skills/analyze-product-requirements/references/product-requirement-schema.md +33 -0
- package/skills/analyze-product-requirements/references/requirement-clarification-schema.md +35 -0
- package/skills/analyze-product-requirements/scripts/test-validators.mjs +193 -0
- package/skills/analyze-product-requirements/scripts/validate-product-analysis.mjs +69 -0
- package/skills/analyze-product-requirements/scripts/validate-product-requirement.mjs +97 -0
- package/skills/analyze-product-requirements/scripts/validate-requirement-clarification.mjs +98 -0
- package/skills/analyze-product-requirements/scripts/validation-helpers.mjs +156 -0
- package/skills/code-review-core/SKILL.md +20 -20
- package/skills/codebase-scout/SKILL.md +19 -19
- package/skills/frontend-design-review/SKILL.md +66 -59
- package/skills/frontend-design-review/references/review-checklist.md +58 -37
- package/skills/frontend-implementation/SKILL.md +47 -51
- package/skills/frontend-implementation/references/code-standards.md +32 -34
- package/skills/frontend-implementation/references/design-spec.md +46 -46
- package/skills/frontend-implementation/references/node-contracts.md +76 -32
- package/skills/frontend-review/SKILL.md +59 -53
- package/skills/frontend-review/references/review-findings.md +47 -42
- package/skills/frontend-verification/SKILL.md +53 -40
- package/skills/frontend-verification/references/verification-checklist.md +68 -56
- package/skills/grill-me/SKILL.md +10 -10
- package/skills/grill-with-docs/SKILL.md +88 -88
- package/skills/grill-with-docs/adr-format.md +47 -47
- package/skills/grill-with-docs/context-format.md +60 -60
- package/skills/init-capability-evolution/SKILL.md +70 -70
- package/skills/loop-agent/SKILL.md +151 -151
- package/skills/loop-agent/references/README.md +67 -67
- package/skills/loop-agent/references/command-reference.md +505 -452
- package/skills/loop-agent/references/docs-converge.md +126 -126
- package/skills/loop-agent/references/harness-policy.md +263 -263
- package/skills/loop-agent/references/hybrid-dag.md +238 -233
- package/skills/loop-agent/references/learned/README.md +21 -21
- package/skills/loop-agent/references/long-running-loop.md +57 -57
- package/skills/loop-agent/references/model-routing.md +36 -36
- package/skills/loop-agent/references/multi-worktree.md +54 -54
- package/skills/loop-agent/references/one-shot-runs.md +85 -85
- package/skills/loop-agent/references/orchestrator-and-interventions.md +169 -169
- package/skills/loop-agent/references/pi-prompt.md +23 -23
- package/skills/loop-agent/references/pi-subagent-assisted-mode.md +84 -84
- package/skills/loop-agent/references/post-implementation-and-patterns.md +44 -44
- package/skills/loop-agent/references/task-workflow.md +89 -89
- package/skills/loop-agent/references/verification-and-failure-handling.md +139 -139
- package/skills/playwright-cli/SKILL.md +420 -0
- package/skills/playwright-cli/references/element-attributes.md +23 -0
- package/skills/playwright-cli/references/playwright-tests.md +39 -0
- package/skills/playwright-cli/references/request-mocking.md +87 -0
- package/skills/playwright-cli/references/running-code.md +241 -0
- package/skills/playwright-cli/references/session-management.md +225 -0
- package/skills/playwright-cli/references/storage-state.md +275 -0
- package/skills/playwright-cli/references/test-generation.md +433 -0
- package/skills/playwright-cli/references/tracing.md +139 -0
- package/skills/playwright-cli/references/video-recording.md +143 -0
- package/skills/playwright-cli-case-generator/SKILL.md +74 -0
- package/skills/requesting-code-review/SKILL.md +101 -101
- package/skills/requesting-code-review/code-reviewer.md +168 -168
- package/skills/systematic-debugging/CREATION-LOG.md +119 -119
- package/skills/systematic-debugging/SKILL.md +296 -296
- package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
- package/skills/systematic-debugging/condition-based-waiting.md +115 -115
- package/skills/systematic-debugging/defense-in-depth.md +122 -122
- package/skills/systematic-debugging/find-polluter.sh +63 -63
- package/skills/systematic-debugging/root-cause-tracing.md +169 -169
- package/skills/systematic-debugging/test-academic.md +14 -14
- package/skills/systematic-debugging/test-pressure-1.md +58 -58
- package/skills/systematic-debugging/test-pressure-2.md +68 -68
- package/skills/systematic-debugging/test-pressure-3.md +69 -69
- package/skills/test-driven-development/SKILL.md +20 -20
- package/skills/using-git-worktrees/SKILL.md +215 -215
- package/skills/verification-before-completion/SKILL.md +154 -154
- package/skills/webapp-testing/SKILL.md +19 -19
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Phase A knowledge-base query (by_id / by_feature / search).
|
|
4
|
+
* Authority: Git files under knowledge/ and features/. Not RAG.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node scripts/kb-query.mjs --mode by_feature --feature F-2026-004 --json
|
|
8
|
+
* node scripts/kb-query.mjs --mode by_id --id SVC-order --json
|
|
9
|
+
* node scripts/kb-query.mjs --mode search --text 预占 --json
|
|
10
|
+
*/
|
|
11
|
+
import fs from "node:fs";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import process from "node:process";
|
|
14
|
+
|
|
15
|
+
function usage(exitCode = 2) {
|
|
16
|
+
const text = `Usage: node scripts/kb-query.mjs --mode <by_id|by_feature|search> [options]
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--root <dir> Repository root (default: cwd)
|
|
20
|
+
--mode <mode> by_id | by_feature | search
|
|
21
|
+
--id <id> Entity id (by_id)
|
|
22
|
+
--feature <F-id> Feature id (by_feature)
|
|
23
|
+
--text <q> Search text (search)
|
|
24
|
+
--glob <pattern> Optional path substring filter for search (repeatable)
|
|
25
|
+
--include-staging Also scan knowledge/bootstrap/staging/**
|
|
26
|
+
--json JSON response (default)
|
|
27
|
+
--markdown Human markdown summary
|
|
28
|
+
-h, --help Help
|
|
29
|
+
`;
|
|
30
|
+
if (exitCode === 0) console.log(text);
|
|
31
|
+
else console.error(text);
|
|
32
|
+
process.exit(exitCode);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function parseArgs(argv) {
|
|
36
|
+
const out = {
|
|
37
|
+
root: process.cwd(),
|
|
38
|
+
mode: null,
|
|
39
|
+
id: null,
|
|
40
|
+
feature: null,
|
|
41
|
+
text: null,
|
|
42
|
+
globs: [],
|
|
43
|
+
includeStaging: false,
|
|
44
|
+
format: "json",
|
|
45
|
+
};
|
|
46
|
+
for (let i = 0; i < argv.length; i++) {
|
|
47
|
+
const a = argv[i];
|
|
48
|
+
const next = () => {
|
|
49
|
+
const v = argv[++i];
|
|
50
|
+
if (v === undefined) throw new Error(`missing value for ${a}`);
|
|
51
|
+
return v;
|
|
52
|
+
};
|
|
53
|
+
switch (a) {
|
|
54
|
+
case "--root":
|
|
55
|
+
out.root = path.resolve(next());
|
|
56
|
+
break;
|
|
57
|
+
case "--mode":
|
|
58
|
+
out.mode = next();
|
|
59
|
+
break;
|
|
60
|
+
case "--id":
|
|
61
|
+
out.id = next();
|
|
62
|
+
break;
|
|
63
|
+
case "--feature":
|
|
64
|
+
out.feature = next();
|
|
65
|
+
break;
|
|
66
|
+
case "--text":
|
|
67
|
+
out.text = next();
|
|
68
|
+
break;
|
|
69
|
+
case "--glob":
|
|
70
|
+
out.globs.push(next());
|
|
71
|
+
break;
|
|
72
|
+
case "--include-staging":
|
|
73
|
+
out.includeStaging = true;
|
|
74
|
+
break;
|
|
75
|
+
case "--json":
|
|
76
|
+
out.format = "json";
|
|
77
|
+
break;
|
|
78
|
+
case "--markdown":
|
|
79
|
+
out.format = "markdown";
|
|
80
|
+
break;
|
|
81
|
+
case "-h":
|
|
82
|
+
case "--help":
|
|
83
|
+
usage(0);
|
|
84
|
+
break;
|
|
85
|
+
default:
|
|
86
|
+
throw new Error(`unknown argument: ${a}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function exists(p) {
|
|
93
|
+
try {
|
|
94
|
+
fs.accessSync(p);
|
|
95
|
+
return true;
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function readText(p) {
|
|
102
|
+
return fs.readFileSync(p, "utf8");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function walkFiles(dir, acc = []) {
|
|
106
|
+
if (!exists(dir)) return acc;
|
|
107
|
+
for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
108
|
+
const p = path.join(dir, ent.name);
|
|
109
|
+
if (ent.isDirectory()) walkFiles(p, acc);
|
|
110
|
+
else acc.push(p);
|
|
111
|
+
}
|
|
112
|
+
return acc;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function toPosix(root, abs) {
|
|
116
|
+
return path.relative(root, abs).split(path.sep).join("/");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function excerpt(text, max = 240) {
|
|
120
|
+
const one = text.replace(/\s+/g, " ").trim();
|
|
121
|
+
if (one.length <= max) return one;
|
|
122
|
+
return `${one.slice(0, max)}…`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function parseYamlishEntitiesIndex(text) {
|
|
126
|
+
/** Minimal line parser for entities-index.yaml written by materialize / hand. */
|
|
127
|
+
const entities = [];
|
|
128
|
+
let cur = null;
|
|
129
|
+
for (const line of text.split(/\r?\n/)) {
|
|
130
|
+
const id = line.match(/^\s+id:\s*(.+)\s*$/);
|
|
131
|
+
const kind = line.match(/^\s+kind:\s*(.+)\s*$/);
|
|
132
|
+
const p = line.match(/^\s+path:\s*(.+)\s*$/);
|
|
133
|
+
const item = line.match(/^\s*-\s+kind:\s*(.+)\s*$/);
|
|
134
|
+
if (item) {
|
|
135
|
+
if (cur?.id) entities.push(cur);
|
|
136
|
+
cur = { kind: item[1].trim(), id: null, path: null };
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (!cur) continue;
|
|
140
|
+
if (kind) cur.kind = kind[1].trim();
|
|
141
|
+
if (id) cur.id = id[1].trim().replace(/^["']|["']$/g, "");
|
|
142
|
+
if (p) cur.path = p[1].trim().replace(/^["']|["']$/g, "");
|
|
143
|
+
}
|
|
144
|
+
if (cur?.id) entities.push(cur);
|
|
145
|
+
return entities.filter((e) => e.id && e.path);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function parseKnowledgeLinks(text) {
|
|
149
|
+
const edges = [];
|
|
150
|
+
// Very small subset: lines like "- type: feature_touches_service" then " to: SVC-x" or "target: "
|
|
151
|
+
let pendingType = null;
|
|
152
|
+
for (const line of text.split(/\r?\n/)) {
|
|
153
|
+
const t = line.match(/^\s*-\s*type:\s*(\S+)/);
|
|
154
|
+
const to =
|
|
155
|
+
line.match(/^\s+(?:to|target|id):\s*(\S+)/) ||
|
|
156
|
+
line.match(/^\s+service_id:\s*(\S+)/);
|
|
157
|
+
if (t) pendingType = t[1];
|
|
158
|
+
if (to && pendingType) {
|
|
159
|
+
edges.push({ type: pendingType, to: to[1].replace(/[",']/g, "") });
|
|
160
|
+
pendingType = null;
|
|
161
|
+
}
|
|
162
|
+
// compact: - feature_touches_service: SVC-order
|
|
163
|
+
const compact = line.match(
|
|
164
|
+
/^\s*-\s*(feature_touches_\w+|touches_\w+|depends_on):\s*(\S+)/,
|
|
165
|
+
);
|
|
166
|
+
if (compact) edges.push({ type: compact[1], to: compact[2] });
|
|
167
|
+
}
|
|
168
|
+
return edges;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function loadEntitiesIndex(root) {
|
|
172
|
+
const p = path.join(root, "knowledge/graph/entities-index.yaml");
|
|
173
|
+
if (!exists(p)) return [];
|
|
174
|
+
return parseYamlishEntitiesIndex(readText(p));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function scanMetaEntities(root, includeStaging) {
|
|
178
|
+
const bases = [
|
|
179
|
+
"knowledge/domains",
|
|
180
|
+
"knowledge/services",
|
|
181
|
+
"knowledge/modules",
|
|
182
|
+
];
|
|
183
|
+
if (includeStaging) {
|
|
184
|
+
bases.push(
|
|
185
|
+
"knowledge/bootstrap/staging/domains",
|
|
186
|
+
"knowledge/bootstrap/staging/services",
|
|
187
|
+
"knowledge/bootstrap/staging/modules",
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
const entities = [];
|
|
191
|
+
for (const base of bases) {
|
|
192
|
+
for (const file of walkFiles(path.join(root, base))) {
|
|
193
|
+
if (!file.endsWith("meta.yaml") && !file.endsWith("meta.yml")) continue;
|
|
194
|
+
const text = readText(file);
|
|
195
|
+
const id = (text.match(/^id:\s*(\S+)/m) || [])[1];
|
|
196
|
+
const kind = (text.match(/^kind:\s*(\S+)/m) || [])[1] || "unknown";
|
|
197
|
+
if (!id) continue;
|
|
198
|
+
entities.push({
|
|
199
|
+
kind,
|
|
200
|
+
id: id.replace(/["']/g, ""),
|
|
201
|
+
path: toPosix(root, file),
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return entities;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function mergeEntities(root, includeStaging) {
|
|
209
|
+
const map = new Map();
|
|
210
|
+
for (const e of [
|
|
211
|
+
...loadEntitiesIndex(root),
|
|
212
|
+
...scanMetaEntities(root, includeStaging),
|
|
213
|
+
]) {
|
|
214
|
+
map.set(`${e.kind}:${e.id}`, e);
|
|
215
|
+
}
|
|
216
|
+
// Features as entities
|
|
217
|
+
const featRoot = path.join(root, "features");
|
|
218
|
+
if (exists(featRoot)) {
|
|
219
|
+
for (const name of fs.readdirSync(featRoot)) {
|
|
220
|
+
if (!/^F-/.test(name)) continue;
|
|
221
|
+
const dir = path.join(featRoot, name);
|
|
222
|
+
if (!fs.statSync(dir).isDirectory()) continue;
|
|
223
|
+
map.set(`feature:${name}`, {
|
|
224
|
+
kind: "feature",
|
|
225
|
+
id: name,
|
|
226
|
+
path: `features/${name}/`,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return [...map.values()];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function resultFromEntity(root, entity, matchReason, score = 1.0) {
|
|
234
|
+
const abs = path.join(root, entity.path);
|
|
235
|
+
let title = entity.id;
|
|
236
|
+
let bodyExcerpt = "";
|
|
237
|
+
if (exists(abs) && fs.statSync(abs).isFile()) {
|
|
238
|
+
const text = readText(abs);
|
|
239
|
+
const t = text.match(/^title:\s*(.+)$/m) || text.match(/^#\s+(.+)$/m);
|
|
240
|
+
if (t) title = t[1].trim();
|
|
241
|
+
bodyExcerpt = excerpt(text);
|
|
242
|
+
} else if (exists(abs) && fs.statSync(abs).isDirectory()) {
|
|
243
|
+
const readme = path.join(abs, "requirement.md");
|
|
244
|
+
const overview = path.join(abs, "overview.md");
|
|
245
|
+
const pick = exists(readme) ? readme : exists(overview) ? overview : null;
|
|
246
|
+
if (pick) {
|
|
247
|
+
const text = readText(pick);
|
|
248
|
+
const t = text.match(/^#\s+(.+)$/m);
|
|
249
|
+
if (t) title = t[1].trim();
|
|
250
|
+
bodyExcerpt = excerpt(text);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
entity: { kind: entity.kind, id: entity.id },
|
|
255
|
+
path: entity.path,
|
|
256
|
+
title,
|
|
257
|
+
excerpt: bodyExcerpt,
|
|
258
|
+
score,
|
|
259
|
+
match_reason: matchReason,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function queryById(root, id, includeStaging) {
|
|
264
|
+
const entities = mergeEntities(root, includeStaging);
|
|
265
|
+
const hits = entities.filter((e) => e.id === id);
|
|
266
|
+
const results = hits.map((e) =>
|
|
267
|
+
resultFromEntity(root, e, hits.length === 1 ? "exact_id" : "id_match"),
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
// Also direct path conventions for testing cases
|
|
271
|
+
if (results.length === 0) {
|
|
272
|
+
const candidates = [
|
|
273
|
+
`features/${id}/`,
|
|
274
|
+
`knowledge/services/${id}/meta.yaml`,
|
|
275
|
+
`knowledge/domains/${id}/meta.yaml`,
|
|
276
|
+
`knowledge/modules/${id}/meta.yaml`,
|
|
277
|
+
];
|
|
278
|
+
for (const rel of candidates) {
|
|
279
|
+
const abs = path.join(root, rel);
|
|
280
|
+
if (exists(abs)) {
|
|
281
|
+
results.push(
|
|
282
|
+
resultFromEntity(
|
|
283
|
+
root,
|
|
284
|
+
{
|
|
285
|
+
kind: rel.startsWith("features/") ? "feature" : "unknown",
|
|
286
|
+
id,
|
|
287
|
+
path: rel,
|
|
288
|
+
},
|
|
289
|
+
"path_convention",
|
|
290
|
+
),
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
schema_version: 1,
|
|
298
|
+
ok: results.length > 0,
|
|
299
|
+
mode: "by_id",
|
|
300
|
+
results,
|
|
301
|
+
edges_trace: [],
|
|
302
|
+
diagnostics: {
|
|
303
|
+
levels_used: ["Q1"],
|
|
304
|
+
truncated: false,
|
|
305
|
+
entity_count_scanned: entities.length,
|
|
306
|
+
},
|
|
307
|
+
error:
|
|
308
|
+
results.length === 0
|
|
309
|
+
? `no entity with id=${id}; run materialize or check knowledge/graph/entities-index.yaml`
|
|
310
|
+
: undefined,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function queryByFeature(root, featureId, includeStaging) {
|
|
315
|
+
const featureDir = path.join(root, "features", featureId);
|
|
316
|
+
if (!exists(featureDir)) {
|
|
317
|
+
return {
|
|
318
|
+
schema_version: 1,
|
|
319
|
+
ok: false,
|
|
320
|
+
mode: "by_feature",
|
|
321
|
+
results: [],
|
|
322
|
+
edges_trace: [],
|
|
323
|
+
diagnostics: { levels_used: ["Q0"], truncated: false },
|
|
324
|
+
error: `missing features/${featureId}/`,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const results = [];
|
|
329
|
+
const edgesTrace = [];
|
|
330
|
+
results.push(
|
|
331
|
+
resultFromEntity(
|
|
332
|
+
root,
|
|
333
|
+
{ kind: "feature", id: featureId, path: `features/${featureId}/` },
|
|
334
|
+
"feature_root",
|
|
335
|
+
),
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
const interesting = [
|
|
339
|
+
"requirement.md",
|
|
340
|
+
"acceptance.yaml",
|
|
341
|
+
"knowledge-links.yaml",
|
|
342
|
+
"testing/acceptance-verdict.yaml",
|
|
343
|
+
"testing/coverage-matrix.yaml",
|
|
344
|
+
"testing/automation-map.yaml",
|
|
345
|
+
"testing/defects/registry.yaml",
|
|
346
|
+
"testing/cases/index.yaml",
|
|
347
|
+
"testing/cases/backend/index.yaml",
|
|
348
|
+
"testing/runs/latest.md",
|
|
349
|
+
];
|
|
350
|
+
for (const rel of interesting) {
|
|
351
|
+
const abs = path.join(featureDir, rel);
|
|
352
|
+
if (!exists(abs)) continue;
|
|
353
|
+
const posix = `features/${featureId}/${rel}`;
|
|
354
|
+
const text = readText(abs);
|
|
355
|
+
results.push({
|
|
356
|
+
entity: {
|
|
357
|
+
kind: rel.includes("testing") ? "testing-asset" : "feature-doc",
|
|
358
|
+
id: `${featureId}:${rel}`,
|
|
359
|
+
},
|
|
360
|
+
path: posix,
|
|
361
|
+
title: rel,
|
|
362
|
+
excerpt: excerpt(text),
|
|
363
|
+
score: 1.0,
|
|
364
|
+
match_reason: "feature_pack",
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const linksPath = path.join(featureDir, "knowledge-links.yaml");
|
|
369
|
+
const entities = mergeEntities(root, includeStaging);
|
|
370
|
+
if (exists(linksPath)) {
|
|
371
|
+
const edges = parseKnowledgeLinks(readText(linksPath));
|
|
372
|
+
for (const edge of edges) {
|
|
373
|
+
edgesTrace.push(`${edge.type}->${edge.to}`);
|
|
374
|
+
const hit = entities.find((e) => e.id === edge.to);
|
|
375
|
+
if (hit) {
|
|
376
|
+
results.push(
|
|
377
|
+
resultFromEntity(root, hit, `edge:${edge.type}`),
|
|
378
|
+
);
|
|
379
|
+
} else {
|
|
380
|
+
results.push({
|
|
381
|
+
entity: { kind: "unknown", id: edge.to },
|
|
382
|
+
path: `features/${featureId}/knowledge-links.yaml`,
|
|
383
|
+
title: edge.to,
|
|
384
|
+
excerpt: `linked via ${edge.type}; entity body not in index`,
|
|
385
|
+
score: 1.0,
|
|
386
|
+
match_reason: `edge:${edge.type}:unresolved`,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// edges.yaml mentions
|
|
393
|
+
const edgesFile = path.join(root, "knowledge/graph/edges.yaml");
|
|
394
|
+
if (exists(edgesFile)) {
|
|
395
|
+
const text = readText(edgesFile);
|
|
396
|
+
if (text.includes(featureId)) {
|
|
397
|
+
results.push({
|
|
398
|
+
entity: { kind: "graph-edges", id: "edges.yaml" },
|
|
399
|
+
path: "knowledge/graph/edges.yaml",
|
|
400
|
+
title: "graph edges",
|
|
401
|
+
excerpt: excerpt(
|
|
402
|
+
text
|
|
403
|
+
.split(/\r?\n/)
|
|
404
|
+
.filter((l) => l.includes(featureId))
|
|
405
|
+
.join("\n") || text,
|
|
406
|
+
),
|
|
407
|
+
score: 1.0,
|
|
408
|
+
match_reason: "graph_edges_mention",
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return {
|
|
414
|
+
schema_version: 1,
|
|
415
|
+
ok: true,
|
|
416
|
+
mode: "by_feature",
|
|
417
|
+
results,
|
|
418
|
+
edges_trace: edgesTrace,
|
|
419
|
+
diagnostics: {
|
|
420
|
+
levels_used: ["Q0", "Q1", "Q2"],
|
|
421
|
+
truncated: false,
|
|
422
|
+
},
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function matchesGlobFilters(rel, globs) {
|
|
427
|
+
if (!globs.length) return true;
|
|
428
|
+
return globs.some((g) => {
|
|
429
|
+
const simple = g.replace(/\*\*/g, "").replace(/\*/g, "");
|
|
430
|
+
if (simple && rel.includes(simple)) return true;
|
|
431
|
+
try {
|
|
432
|
+
return globToLoose(g).test(rel);
|
|
433
|
+
} catch {
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function querySearch(root, text, globs, includeStaging) {
|
|
440
|
+
const q = text.toLowerCase();
|
|
441
|
+
const roots = ["knowledge", "features"];
|
|
442
|
+
if (includeStaging) roots.push("knowledge/bootstrap/staging");
|
|
443
|
+
const results = [];
|
|
444
|
+
for (const base of roots) {
|
|
445
|
+
for (const file of walkFiles(path.join(root, base))) {
|
|
446
|
+
const rel = toPosix(root, file);
|
|
447
|
+
if (!matchesGlobFilters(rel, globs)) continue;
|
|
448
|
+
let body;
|
|
449
|
+
try {
|
|
450
|
+
body = readText(file);
|
|
451
|
+
} catch {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
if (!body.toLowerCase().includes(q)) continue;
|
|
455
|
+
const idx = body.toLowerCase().indexOf(q);
|
|
456
|
+
const slice = body.slice(Math.max(0, idx - 40), idx + q.length + 80);
|
|
457
|
+
results.push({
|
|
458
|
+
entity: { kind: "file", id: rel },
|
|
459
|
+
path: rel,
|
|
460
|
+
title: path.basename(file),
|
|
461
|
+
excerpt: excerpt(slice, 200),
|
|
462
|
+
score: 0.5,
|
|
463
|
+
match_reason: "search_text",
|
|
464
|
+
});
|
|
465
|
+
if (results.length >= 20) break;
|
|
466
|
+
}
|
|
467
|
+
if (results.length >= 20) break;
|
|
468
|
+
}
|
|
469
|
+
return {
|
|
470
|
+
schema_version: 1,
|
|
471
|
+
ok: results.length > 0,
|
|
472
|
+
mode: "search",
|
|
473
|
+
results,
|
|
474
|
+
edges_trace: [],
|
|
475
|
+
diagnostics: {
|
|
476
|
+
levels_used: ["Q3"],
|
|
477
|
+
truncated: results.length >= 20,
|
|
478
|
+
},
|
|
479
|
+
error:
|
|
480
|
+
results.length === 0
|
|
481
|
+
? `no matches for ${JSON.stringify(text)}`
|
|
482
|
+
: undefined,
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function globToLoose(g) {
|
|
487
|
+
// minimal: treat * as .*
|
|
488
|
+
const esc = g.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*");
|
|
489
|
+
return new RegExp(esc);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function toMarkdown(resp) {
|
|
493
|
+
const lines = [
|
|
494
|
+
`# kb-query ${resp.mode}`,
|
|
495
|
+
`ok: ${resp.ok}`,
|
|
496
|
+
resp.error ? `error: ${resp.error}` : null,
|
|
497
|
+
"",
|
|
498
|
+
"## results",
|
|
499
|
+
].filter(Boolean);
|
|
500
|
+
for (const r of resp.results || []) {
|
|
501
|
+
lines.push(
|
|
502
|
+
`- **${r.entity?.id ?? "?"}** (${r.entity?.kind ?? "?"}) \`${r.path}\` — ${r.match_reason}`,
|
|
503
|
+
);
|
|
504
|
+
if (r.excerpt) lines.push(` - ${r.excerpt}`);
|
|
505
|
+
}
|
|
506
|
+
if (resp.edges_trace?.length) {
|
|
507
|
+
lines.push("", "## edges_trace", ...resp.edges_trace.map((e) => `- ${e}`));
|
|
508
|
+
}
|
|
509
|
+
return `${lines.join("\n")}\n`;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function main() {
|
|
513
|
+
let args;
|
|
514
|
+
try {
|
|
515
|
+
args = parseArgs(process.argv.slice(2));
|
|
516
|
+
} catch (e) {
|
|
517
|
+
console.error(String(e?.message || e));
|
|
518
|
+
usage(2);
|
|
519
|
+
}
|
|
520
|
+
if (!args.mode) {
|
|
521
|
+
console.error("--mode is required");
|
|
522
|
+
usage(2);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
let resp;
|
|
526
|
+
if (args.mode === "by_id") {
|
|
527
|
+
if (!args.id) {
|
|
528
|
+
console.error("by_id requires --id");
|
|
529
|
+
process.exit(2);
|
|
530
|
+
}
|
|
531
|
+
resp = queryById(args.root, args.id, args.includeStaging);
|
|
532
|
+
} else if (args.mode === "by_feature") {
|
|
533
|
+
if (!args.feature) {
|
|
534
|
+
console.error("by_feature requires --feature");
|
|
535
|
+
process.exit(2);
|
|
536
|
+
}
|
|
537
|
+
resp = queryByFeature(args.root, args.feature, args.includeStaging);
|
|
538
|
+
} else if (args.mode === "search") {
|
|
539
|
+
if (!args.text) {
|
|
540
|
+
console.error("search requires --text");
|
|
541
|
+
process.exit(2);
|
|
542
|
+
}
|
|
543
|
+
resp = querySearch(args.root, args.text, args.globs, args.includeStaging);
|
|
544
|
+
} else {
|
|
545
|
+
console.error(`unsupported mode: ${args.mode}`);
|
|
546
|
+
process.exit(2);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
if (args.format === "markdown") process.stdout.write(toMarkdown(resp));
|
|
550
|
+
else process.stdout.write(`${JSON.stringify(resp, null, 2)}\n`);
|
|
551
|
+
process.exit(resp.ok ? 0 : 1);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
main();
|
|
@@ -1,37 +1,39 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: agent-worker
|
|
3
|
-
description: Use when work involves agent-worker, Feature Packet, TaskSpec, Task Pool, Feature or batch orchestration, controller pinning, versioned self-hosting (自举) release trains, candidate takeover canaries (候选接棒验证), or worker failure recovery; use loop-agent instead for a single DAG implementation or DAG runtime/kernel repair.
|
|
4
|
-
references:
|
|
5
|
-
- path: references/agent-worker-operator.md
|
|
6
|
-
required: true
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Agent Worker Operator
|
|
10
|
-
|
|
11
|
-
当工作起点是 Feature Packet、TaskSpec、Task Pool、Worker batch 或 versioned self-hosting release train 时使用本 skill。它负责在单次 loop-agent DAG run 之外选择并监督工作。
|
|
12
|
-
|
|
13
|
-
## Route the Work
|
|
14
|
-
|
|
15
|
-
- 用 `agent-worker` 做 Feature validation 与 lifecycle 决策、Ready-task 选择、batch 推进、controller identity freeze、candidate takeover canary,以及失败 Worker run 的恢复。
|
|
16
|
-
- 对单个有界 DAG task、DAG diagnostics、node implementation,或 DAG runtime/kernel 修复,直接用 `loop-agent`。
|
|
17
|
-
- 不要让 DAG leaf node 递归启动 `agent-worker`;Worker 是 outer loop,不是另一个 node executor。
|
|
18
|
-
|
|
19
|
-
## Boundaries
|
|
20
|
-
|
|
21
|
-
- `agent-worker` 读取 Feature Packet 与 Task Pool facts,选择任务,冻结 controller identity,启动 Feature/batch lifecycle 命令,并收集 evidence。
|
|
22
|
-
- `loop-agent` 仍是 DAG executor,负责 Pi-only implementation nodes、write-set governance、skill snapshots 与 run facts。
|
|
23
|
-
- Controller identity 冻结驱动 batch 的 published package;loop-agent skill snapshot 则单独冻结注入单次 DAG run 的 instructions。
|
|
24
|
-
- 本 skill 不复制 command catalog。精确 flags 见 CLI help 与同级 `../loop-agent/references/command-reference.md`。
|
|
25
|
-
- 不要把本 skill 加入默认 DAG role skills;仅对 outer-loop operator 工作显式路由。
|
|
26
|
-
|
|
27
|
-
## Operator Flow
|
|
28
|
-
|
|
29
|
-
1. 校验 Feature Packet 与 TaskSpecs,再从 Task Pool facts 选择 Ready 工作,而不是从 chat state。
|
|
30
|
-
2. 在写入前解析并冻结目标 published controller;在 batch、task 与 run evidence 中保留 controller identity。
|
|
31
|
-
3. 将仓库写入委托给受治理的 loop-agent DAG nodes,并审查其 task boundaries 与 write sets。
|
|
32
|
-
4. 自举时保持 published version N 固定,由它维护 candidate N+1,再通过 deterministic isolated canary 证明 candidate takeover。
|
|
33
|
-
5. 失败时先保留原始 run record、evidence 与 failure handoff,再重试或创建后续工作。
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
1
|
+
---
|
|
2
|
+
name: agent-worker
|
|
3
|
+
description: Use when work involves agent-worker, Feature Packet, TaskSpec, Task Pool, Feature or batch orchestration, controller pinning, versioned self-hosting (自举) release trains, candidate takeover canaries (候选接棒验证), or worker failure recovery; use loop-agent instead for a single DAG implementation or DAG runtime/kernel repair.
|
|
4
|
+
references:
|
|
5
|
+
- path: references/agent-worker-operator.md
|
|
6
|
+
required: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Agent Worker Operator
|
|
10
|
+
|
|
11
|
+
当工作起点是 Feature Packet、TaskSpec、Task Pool、Worker batch 或 versioned self-hosting release train 时使用本 skill。它负责在单次 loop-agent DAG run 之外选择并监督工作。
|
|
12
|
+
|
|
13
|
+
## Route the Work
|
|
14
|
+
|
|
15
|
+
- 用 `agent-worker` 做 Feature validation 与 lifecycle 决策、Ready-task 选择、batch 推进、controller identity freeze、candidate takeover canary,以及失败 Worker run 的恢复。
|
|
16
|
+
- 对单个有界 DAG task、DAG diagnostics、node implementation,或 DAG runtime/kernel 修复,直接用 `loop-agent`。
|
|
17
|
+
- 不要让 DAG leaf node 递归启动 `agent-worker`;Worker 是 outer loop,不是另一个 node executor。
|
|
18
|
+
|
|
19
|
+
## Boundaries
|
|
20
|
+
|
|
21
|
+
- `agent-worker` 读取 Feature Packet 与 Task Pool facts,选择任务,冻结 controller identity,启动 Feature/batch lifecycle 命令,并收集 evidence。
|
|
22
|
+
- `loop-agent` 仍是 DAG executor,负责 Pi-only implementation nodes、write-set governance、skill snapshots 与 run facts。
|
|
23
|
+
- Controller identity 冻结驱动 batch 的 published package;loop-agent skill snapshot 则单独冻结注入单次 DAG run 的 instructions。
|
|
24
|
+
- 本 skill 不复制 command catalog。精确 flags 见 CLI help 与同级 `../loop-agent/references/command-reference.md`。
|
|
25
|
+
- 不要把本 skill 加入默认 DAG role skills;仅对 outer-loop operator 工作显式路由。
|
|
26
|
+
|
|
27
|
+
## Operator Flow
|
|
28
|
+
|
|
29
|
+
1. 校验 Feature Packet 与 TaskSpecs,再从 Task Pool facts 选择 Ready 工作,而不是从 chat state。Task Pool 身份是 `{ featureId, taskId }`,不是裸 taskId。
|
|
30
|
+
2. 在写入前解析并冻结目标 published controller;在 batch、task 与 run evidence 中保留 controller identity。
|
|
31
|
+
3. 将仓库写入委托给受治理的 loop-agent DAG nodes,并审查其 task boundaries 与 write sets。
|
|
32
|
+
4. 自举时保持 published version N 固定,由它维护 candidate N+1,再通过 deterministic isolated canary 证明 candidate takeover。
|
|
33
|
+
5. 失败时先保留原始 run record、evidence 与 failure handoff,再重试或创建后续工作。
|
|
34
|
+
6. Failed task 重试使用 `agent-worker task retry <task-id> --feature-id <feature-id> --repo <repo> --reason <reason>`;跨 Feature 同名时禁止省略 `--feature-id`。
|
|
35
|
+
7. 升级或发现 legacy state 时先 `pool doctor`,再用 `pool migrate-state`(默认 dry-run;apply 需 `--owner` + `--reason`)。Observe 保持只读。
|
|
36
|
+
|
|
37
|
+
## References
|
|
38
|
+
|
|
39
|
+
- `references/agent-worker-operator.md`
|