opencode-swarm 6.19.6 → 6.19.7
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/README.md +2 -0
- package/dist/cli/index.js +66 -5
- package/dist/index.js +279 -55
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/plugin-registration-adversarial.test.d.ts +1 -0
- package/dist/tools/tool-names.d.ts +1 -1
- package/dist/tools/update-task-status.d.ts +47 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -694,7 +694,9 @@ The following tools can be assigned to agents via overrides:
|
|
|
694
694
|
| `secretscan` | Scan for secrets in code |
|
|
695
695
|
| `symbols` | Extract exported symbols |
|
|
696
696
|
| `test_runner` | Run project tests |
|
|
697
|
+
| `update_task_status` | Mark plan tasks as pending/in_progress/completed/blocked; track phase progress |
|
|
697
698
|
| `todo_extract` | Extract TODO/FIXME comments |
|
|
699
|
+
| `write_retro` | Document phase retrospectives via the phase_complete workflow; capture lessons learned |
|
|
698
700
|
| `phase_complete` | Enforces phase completion, verifies required agents, logs events, resets state |
|
|
699
701
|
|
|
700
702
|
---
|
package/dist/cli/index.js
CHANGED
|
@@ -14326,16 +14326,68 @@ async function saveEvidence(directory, taskId, evidence) {
|
|
|
14326
14326
|
}
|
|
14327
14327
|
return updatedBundle;
|
|
14328
14328
|
}
|
|
14329
|
+
function isFlatRetrospective(parsed) {
|
|
14330
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && parsed.type === "retrospective" && !parsed.schema_version;
|
|
14331
|
+
}
|
|
14332
|
+
function remapLegacyTaskComplexity(entry) {
|
|
14333
|
+
const taskComplexity = entry.task_complexity;
|
|
14334
|
+
if (typeof taskComplexity === "string" && taskComplexity in LEGACY_TASK_COMPLEXITY_MAP) {
|
|
14335
|
+
return {
|
|
14336
|
+
...entry,
|
|
14337
|
+
task_complexity: LEGACY_TASK_COMPLEXITY_MAP[taskComplexity]
|
|
14338
|
+
};
|
|
14339
|
+
}
|
|
14340
|
+
return entry;
|
|
14341
|
+
}
|
|
14342
|
+
function wrapFlatRetrospective(flatEntry, taskId) {
|
|
14343
|
+
const now = new Date().toISOString();
|
|
14344
|
+
const remappedEntry = remapLegacyTaskComplexity(flatEntry);
|
|
14345
|
+
return {
|
|
14346
|
+
schema_version: "1.0.0",
|
|
14347
|
+
task_id: remappedEntry.task_id ?? taskId,
|
|
14348
|
+
created_at: remappedEntry.timestamp ?? now,
|
|
14349
|
+
updated_at: remappedEntry.timestamp ?? now,
|
|
14350
|
+
entries: [remappedEntry]
|
|
14351
|
+
};
|
|
14352
|
+
}
|
|
14329
14353
|
async function loadEvidence(directory, taskId) {
|
|
14330
14354
|
const sanitizedTaskId = sanitizeTaskId(taskId);
|
|
14331
14355
|
const relativePath = path3.join("evidence", sanitizedTaskId, "evidence.json");
|
|
14332
|
-
validateSwarmPath(directory, relativePath);
|
|
14356
|
+
const evidencePath = validateSwarmPath(directory, relativePath);
|
|
14333
14357
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
14334
14358
|
if (content === null) {
|
|
14335
14359
|
return { status: "not_found" };
|
|
14336
14360
|
}
|
|
14361
|
+
let parsed;
|
|
14362
|
+
try {
|
|
14363
|
+
parsed = JSON.parse(content);
|
|
14364
|
+
} catch {
|
|
14365
|
+
return { status: "invalid_schema", errors: ["Invalid JSON"] };
|
|
14366
|
+
}
|
|
14367
|
+
if (isFlatRetrospective(parsed)) {
|
|
14368
|
+
const wrappedBundle = wrapFlatRetrospective(parsed, sanitizedTaskId);
|
|
14369
|
+
try {
|
|
14370
|
+
const validated = EvidenceBundleSchema.parse(wrappedBundle);
|
|
14371
|
+
const evidenceDir = path3.dirname(evidencePath);
|
|
14372
|
+
const bundleJson = JSON.stringify(validated);
|
|
14373
|
+
const tempPath = path3.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
14374
|
+
try {
|
|
14375
|
+
await Bun.write(tempPath, bundleJson);
|
|
14376
|
+
renameSync(tempPath, evidencePath);
|
|
14377
|
+
} catch (writeError) {
|
|
14378
|
+
try {
|
|
14379
|
+
rmSync(tempPath, { force: true });
|
|
14380
|
+
} catch {}
|
|
14381
|
+
warn(`Failed to persist repaired flat retrospective for task ${sanitizedTaskId}: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
14382
|
+
}
|
|
14383
|
+
return { status: "found", bundle: validated };
|
|
14384
|
+
} catch (error49) {
|
|
14385
|
+
warn(`Wrapped flat retrospective failed validation for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
14386
|
+
const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => e.path.join(".") + ": " + e.message) : [String(error49)];
|
|
14387
|
+
return { status: "invalid_schema", errors: errors3 };
|
|
14388
|
+
}
|
|
14389
|
+
}
|
|
14337
14390
|
try {
|
|
14338
|
-
const parsed = JSON.parse(content);
|
|
14339
14391
|
const validated = EvidenceBundleSchema.parse(parsed);
|
|
14340
14392
|
return { status: "found", bundle: validated };
|
|
14341
14393
|
} catch (error49) {
|
|
@@ -14428,7 +14480,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
|
|
|
14428
14480
|
}
|
|
14429
14481
|
return archived;
|
|
14430
14482
|
}
|
|
14431
|
-
var VALID_EVIDENCE_TYPES, TASK_ID_REGEX;
|
|
14483
|
+
var VALID_EVIDENCE_TYPES, TASK_ID_REGEX, LEGACY_TASK_COMPLEXITY_MAP;
|
|
14432
14484
|
var init_manager = __esm(() => {
|
|
14433
14485
|
init_zod();
|
|
14434
14486
|
init_evidence_schema();
|
|
@@ -14449,6 +14501,11 @@ var init_manager = __esm(() => {
|
|
|
14449
14501
|
"quality_budget"
|
|
14450
14502
|
];
|
|
14451
14503
|
TASK_ID_REGEX = /^[\w-]+(\.[\w-]+)*$/;
|
|
14504
|
+
LEGACY_TASK_COMPLEXITY_MAP = {
|
|
14505
|
+
low: "simple",
|
|
14506
|
+
medium: "moderate",
|
|
14507
|
+
high: "complex"
|
|
14508
|
+
};
|
|
14452
14509
|
});
|
|
14453
14510
|
|
|
14454
14511
|
// node_modules/graceful-fs/polyfills.js
|
|
@@ -17468,7 +17525,9 @@ var TOOL_NAMES = [
|
|
|
17468
17525
|
"retrieve_summary",
|
|
17469
17526
|
"extract_code_blocks",
|
|
17470
17527
|
"phase_complete",
|
|
17471
|
-
"save_plan"
|
|
17528
|
+
"save_plan",
|
|
17529
|
+
"update_task_status",
|
|
17530
|
+
"write_retro"
|
|
17472
17531
|
];
|
|
17473
17532
|
var TOOL_NAME_SET = new Set(TOOL_NAMES);
|
|
17474
17533
|
|
|
@@ -17506,7 +17565,9 @@ var AGENT_TOOL_MAP = {
|
|
|
17506
17565
|
"secretscan",
|
|
17507
17566
|
"symbols",
|
|
17508
17567
|
"test_runner",
|
|
17509
|
-
"todo_extract"
|
|
17568
|
+
"todo_extract",
|
|
17569
|
+
"update_task_status",
|
|
17570
|
+
"write_retro"
|
|
17510
17571
|
],
|
|
17511
17572
|
explorer: [
|
|
17512
17573
|
"complexity_hotspots",
|
package/dist/index.js
CHANGED
|
@@ -14490,16 +14490,68 @@ async function saveEvidence(directory, taskId, evidence) {
|
|
|
14490
14490
|
}
|
|
14491
14491
|
return updatedBundle;
|
|
14492
14492
|
}
|
|
14493
|
+
function isFlatRetrospective(parsed) {
|
|
14494
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && parsed.type === "retrospective" && !parsed.schema_version;
|
|
14495
|
+
}
|
|
14496
|
+
function remapLegacyTaskComplexity(entry) {
|
|
14497
|
+
const taskComplexity = entry.task_complexity;
|
|
14498
|
+
if (typeof taskComplexity === "string" && taskComplexity in LEGACY_TASK_COMPLEXITY_MAP) {
|
|
14499
|
+
return {
|
|
14500
|
+
...entry,
|
|
14501
|
+
task_complexity: LEGACY_TASK_COMPLEXITY_MAP[taskComplexity]
|
|
14502
|
+
};
|
|
14503
|
+
}
|
|
14504
|
+
return entry;
|
|
14505
|
+
}
|
|
14506
|
+
function wrapFlatRetrospective(flatEntry, taskId) {
|
|
14507
|
+
const now = new Date().toISOString();
|
|
14508
|
+
const remappedEntry = remapLegacyTaskComplexity(flatEntry);
|
|
14509
|
+
return {
|
|
14510
|
+
schema_version: "1.0.0",
|
|
14511
|
+
task_id: remappedEntry.task_id ?? taskId,
|
|
14512
|
+
created_at: remappedEntry.timestamp ?? now,
|
|
14513
|
+
updated_at: remappedEntry.timestamp ?? now,
|
|
14514
|
+
entries: [remappedEntry]
|
|
14515
|
+
};
|
|
14516
|
+
}
|
|
14493
14517
|
async function loadEvidence(directory, taskId) {
|
|
14494
14518
|
const sanitizedTaskId = sanitizeTaskId(taskId);
|
|
14495
14519
|
const relativePath = path3.join("evidence", sanitizedTaskId, "evidence.json");
|
|
14496
|
-
validateSwarmPath(directory, relativePath);
|
|
14520
|
+
const evidencePath = validateSwarmPath(directory, relativePath);
|
|
14497
14521
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
14498
14522
|
if (content === null) {
|
|
14499
14523
|
return { status: "not_found" };
|
|
14500
14524
|
}
|
|
14525
|
+
let parsed;
|
|
14526
|
+
try {
|
|
14527
|
+
parsed = JSON.parse(content);
|
|
14528
|
+
} catch {
|
|
14529
|
+
return { status: "invalid_schema", errors: ["Invalid JSON"] };
|
|
14530
|
+
}
|
|
14531
|
+
if (isFlatRetrospective(parsed)) {
|
|
14532
|
+
const wrappedBundle = wrapFlatRetrospective(parsed, sanitizedTaskId);
|
|
14533
|
+
try {
|
|
14534
|
+
const validated = EvidenceBundleSchema.parse(wrappedBundle);
|
|
14535
|
+
const evidenceDir = path3.dirname(evidencePath);
|
|
14536
|
+
const bundleJson = JSON.stringify(validated);
|
|
14537
|
+
const tempPath = path3.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
14538
|
+
try {
|
|
14539
|
+
await Bun.write(tempPath, bundleJson);
|
|
14540
|
+
renameSync(tempPath, evidencePath);
|
|
14541
|
+
} catch (writeError) {
|
|
14542
|
+
try {
|
|
14543
|
+
rmSync(tempPath, { force: true });
|
|
14544
|
+
} catch {}
|
|
14545
|
+
warn(`Failed to persist repaired flat retrospective for task ${sanitizedTaskId}: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
14546
|
+
}
|
|
14547
|
+
return { status: "found", bundle: validated };
|
|
14548
|
+
} catch (error49) {
|
|
14549
|
+
warn(`Wrapped flat retrospective failed validation for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
14550
|
+
const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => e.path.join(".") + ": " + e.message) : [String(error49)];
|
|
14551
|
+
return { status: "invalid_schema", errors: errors3 };
|
|
14552
|
+
}
|
|
14553
|
+
}
|
|
14501
14554
|
try {
|
|
14502
|
-
const parsed = JSON.parse(content);
|
|
14503
14555
|
const validated = EvidenceBundleSchema.parse(parsed);
|
|
14504
14556
|
return { status: "found", bundle: validated };
|
|
14505
14557
|
} catch (error49) {
|
|
@@ -14592,7 +14644,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
|
|
|
14592
14644
|
}
|
|
14593
14645
|
return archived;
|
|
14594
14646
|
}
|
|
14595
|
-
var VALID_EVIDENCE_TYPES, TASK_ID_REGEX;
|
|
14647
|
+
var VALID_EVIDENCE_TYPES, TASK_ID_REGEX, LEGACY_TASK_COMPLEXITY_MAP;
|
|
14596
14648
|
var init_manager = __esm(() => {
|
|
14597
14649
|
init_zod();
|
|
14598
14650
|
init_evidence_schema();
|
|
@@ -14613,6 +14665,11 @@ var init_manager = __esm(() => {
|
|
|
14613
14665
|
"quality_budget"
|
|
14614
14666
|
];
|
|
14615
14667
|
TASK_ID_REGEX = /^[\w-]+(\.[\w-]+)*$/;
|
|
14668
|
+
LEGACY_TASK_COMPLEXITY_MAP = {
|
|
14669
|
+
low: "simple",
|
|
14670
|
+
medium: "moderate",
|
|
14671
|
+
high: "complex"
|
|
14672
|
+
};
|
|
14616
14673
|
});
|
|
14617
14674
|
|
|
14618
14675
|
// src/plan/manager.ts
|
|
@@ -14783,6 +14840,29 @@ ${markdown}`;
|
|
|
14783
14840
|
} catch {}
|
|
14784
14841
|
}
|
|
14785
14842
|
}
|
|
14843
|
+
async function updateTaskStatus(directory, taskId, status) {
|
|
14844
|
+
const plan = await loadPlan(directory);
|
|
14845
|
+
if (plan === null) {
|
|
14846
|
+
throw new Error(`Plan not found in directory: ${directory}`);
|
|
14847
|
+
}
|
|
14848
|
+
let taskFound = false;
|
|
14849
|
+
const updatedPhases = plan.phases.map((phase) => {
|
|
14850
|
+
const updatedTasks = phase.tasks.map((task) => {
|
|
14851
|
+
if (task.id === taskId) {
|
|
14852
|
+
taskFound = true;
|
|
14853
|
+
return { ...task, status };
|
|
14854
|
+
}
|
|
14855
|
+
return task;
|
|
14856
|
+
});
|
|
14857
|
+
return { ...phase, tasks: updatedTasks };
|
|
14858
|
+
});
|
|
14859
|
+
if (!taskFound) {
|
|
14860
|
+
throw new Error(`Task not found: ${taskId}`);
|
|
14861
|
+
}
|
|
14862
|
+
const updatedPlan = { ...plan, phases: updatedPhases };
|
|
14863
|
+
await savePlan(directory, updatedPlan);
|
|
14864
|
+
return updatedPlan;
|
|
14865
|
+
}
|
|
14786
14866
|
function derivePlanMarkdown(plan) {
|
|
14787
14867
|
const statusMap = {
|
|
14788
14868
|
pending: "PENDING",
|
|
@@ -38002,7 +38082,7 @@ var init_runtime = __esm(() => {
|
|
|
38002
38082
|
});
|
|
38003
38083
|
|
|
38004
38084
|
// src/index.ts
|
|
38005
|
-
import * as
|
|
38085
|
+
import * as path44 from "path";
|
|
38006
38086
|
|
|
38007
38087
|
// src/tools/tool-names.ts
|
|
38008
38088
|
var TOOL_NAMES = [
|
|
@@ -38030,7 +38110,9 @@ var TOOL_NAMES = [
|
|
|
38030
38110
|
"retrieve_summary",
|
|
38031
38111
|
"extract_code_blocks",
|
|
38032
38112
|
"phase_complete",
|
|
38033
|
-
"save_plan"
|
|
38113
|
+
"save_plan",
|
|
38114
|
+
"update_task_status",
|
|
38115
|
+
"write_retro"
|
|
38034
38116
|
];
|
|
38035
38117
|
var TOOL_NAME_SET = new Set(TOOL_NAMES);
|
|
38036
38118
|
|
|
@@ -38068,7 +38150,9 @@ var AGENT_TOOL_MAP = {
|
|
|
38068
38150
|
"secretscan",
|
|
38069
38151
|
"symbols",
|
|
38070
38152
|
"test_runner",
|
|
38071
|
-
"todo_extract"
|
|
38153
|
+
"todo_extract",
|
|
38154
|
+
"update_task_status",
|
|
38155
|
+
"write_retro"
|
|
38072
38156
|
],
|
|
38073
38157
|
explorer: [
|
|
38074
38158
|
"complexity_hotspots",
|
|
@@ -39009,9 +39093,10 @@ writeCount > 0 on source files from the Architect is equivalent to GATE_DELEGATI
|
|
|
39009
39093
|
|
|
39010
39094
|
PLAN STATE PROTECTION
|
|
39011
39095
|
.swarm/plan.md and .swarm/plan.json are READABLE but NOT DIRECTLY WRITABLE for state transitions.
|
|
39012
|
-
Task status changes (
|
|
39096
|
+
Task-level status changes (marking individual tasks as "completed") must use update_task_status().
|
|
39097
|
+
Phase-level completion (marking an entire phase as done) must use phase_complete().
|
|
39013
39098
|
You may write to plan.md/plan.json for STRUCTURAL changes (adding tasks, updating descriptions).
|
|
39014
|
-
You may NOT write to plan.md/plan.json to change task completion status or phase status.
|
|
39099
|
+
You may NOT write to plan.md/plan.json to change task completion status or phase status directly.
|
|
39015
39100
|
"I'll just mark it done directly" is a bypass \u2014 equivalent to GATE_DELEGATION_BYPASS.
|
|
39016
39101
|
|
|
39017
39102
|
6i. **DELEGATION DISCIPLINE**
|
|
@@ -39047,7 +39132,7 @@ It is the same severity as skipping all gates. The QA gate is ALL steps or NONE.
|
|
|
39047
39132
|
- Target file is in: pages/, components/, views/, screens/, ui/, layouts/
|
|
39048
39133
|
If triggered: delegate to {{AGENT_PREFIX}}designer FIRST to produce a code scaffold. Then pass the scaffold to {{AGENT_PREFIX}}coder as INPUT alongside the task. The coder implements the TODOs in the scaffold without changing component structure or accessibility attributes.
|
|
39049
39134
|
If not triggered: delegate directly to {{AGENT_PREFIX}}coder as normal.
|
|
39050
|
-
10. **RETROSPECTIVE TRACKING**: At the end of every phase, record phase metrics in .swarm/context.md under "## Phase Metrics" and write a retrospective evidence entry via
|
|
39135
|
+
10. **RETROSPECTIVE TRACKING**: At the end of every phase, record phase metrics in .swarm/context.md under "## Phase Metrics" and write a retrospective evidence entry via write_retro. Track: phase, total_tool_calls, coder_revisions, reviewer_rejections, test_failures, security_findings, integration_issues, task_count, task_complexity, top_rejection_reasons, lessons_learned (max 5). Reset Phase Metrics to 0 after writing.
|
|
39051
39136
|
11. **CHECKPOINTS**: Before delegating multi-file refactor tasks (3+ files), create a checkpoint save. On critical failures when redo is faster than iterative fixes, restore from checkpoint. Use checkpoint tool: \`checkpoint save\` before risky operations, \`checkpoint restore\` on failure.
|
|
39052
39137
|
|
|
39053
39138
|
SECURITY_KEYWORDS: password, secret, token, credential, auth, login, encryption, hash, key, certificate, ssl, tls, jwt, oauth, session, csrf, xss, injection, sanitization, permission, access, vulnerable, exploit, privilege, authorization, roles, authentication, mfa, 2fa, totp, otp, salt, iv, nonce, hmac, aes, rsa, sha256, bcrypt, scrypt, argon2, api_key, apikey, private_key, public_key, rbac, admin, superuser, sqli, rce, ssrf, xxe, nosql, command_injection
|
|
@@ -39072,7 +39157,7 @@ Outside OpenCode, invoke any plugin command via: \`bunx opencode-swarm run <comm
|
|
|
39072
39157
|
|
|
39073
39158
|
SMEs advise only. Reviewer and critic review only. None of them write code.
|
|
39074
39159
|
|
|
39075
|
-
Available Tools: symbols (code symbol search), checkpoint (state snapshots), diff (structured git diff with contract change detection), imports (dependency audit), lint (code quality), placeholder_scan (placeholder/todo detection), secretscan (secret detection), sast_scan (static analysis security scan), syntax_check (syntax validation), test_runner (auto-detect and run tests), pkg_audit (dependency vulnerability scan \u2014 npm/pip/cargo), complexity_hotspots (git churn \xD7 complexity risk map), schema_drift (OpenAPI spec vs route drift), todo_extract (structured TODO/FIXME extraction), evidence_check (verify task evidence completeness), sbom_generate (SBOM generation for dependency inventory), build_check (build verification), quality_budget (code quality budget check), pre_check_batch (parallel verification: lint:check + secretscan + sast_scan + quality_budget)
|
|
39160
|
+
Available Tools: symbols (code symbol search), checkpoint (state snapshots), diff (structured git diff with contract change detection), imports (dependency audit), lint (code quality), placeholder_scan (placeholder/todo detection), secretscan (secret detection), sast_scan (static analysis security scan), syntax_check (syntax validation), test_runner (auto-detect and run tests), pkg_audit (dependency vulnerability scan \u2014 npm/pip/cargo), complexity_hotspots (git churn \xD7 complexity risk map), schema_drift (OpenAPI spec vs route drift), todo_extract (structured TODO/FIXME extraction), evidence_check (verify task evidence completeness), sbom_generate (SBOM generation for dependency inventory), build_check (build verification), quality_budget (code quality budget check), pre_check_batch (parallel verification: lint:check + secretscan + sast_scan + quality_budget), update_task_status (mark tasks complete, track phase progress), write_retro (document phase retrospectives via phase_complete workflow, capture lessons learned)
|
|
39076
39161
|
|
|
39077
39162
|
## DELEGATION FORMAT
|
|
39078
39163
|
|
|
@@ -39455,6 +39540,9 @@ The ONLY exception: lint tool in fix mode (step 5g) auto-corrects by design.
|
|
|
39455
39540
|
All other gates: failure \u2192 return to coder. No self-fixes. No workarounds.
|
|
39456
39541
|
|
|
39457
39542
|
5a. **UI DESIGN GATE** (conditional \u2014 Rule 9): If task matches UI trigger \u2192 {{AGENT_PREFIX}}designer produces scaffold \u2192 pass scaffold to coder as INPUT. If no match \u2192 skip.
|
|
39543
|
+
|
|
39544
|
+
\u2192 After step 5a (or immediately if no UI task applies): Call update_task_status with status in_progress for the current task. Then proceed to step 5b.
|
|
39545
|
+
|
|
39458
39546
|
5b. {{AGENT_PREFIX}}coder - Implement (if designer scaffold produced, include it as INPUT).
|
|
39459
39547
|
5c. Run \`diff\` tool. If \`hasContractChanges\` \u2192 {{AGENT_PREFIX}}explorer integration analysis. BREAKING \u2192 coder retry.
|
|
39460
39548
|
\u2192 REQUIRED: Print "diff: [PASS | CONTRACT CHANGE \u2014 details]"
|
|
@@ -39533,7 +39621,7 @@ PRE-COMMIT RULE \u2014 Before ANY commit or push:
|
|
|
39533
39621
|
Any blank "value: ___" field = gate was not run = task is NOT complete.
|
|
39534
39622
|
Filling this checklist from memory ("I think I ran it") is INVALID. Each value must come from actual tool/agent output in this session.
|
|
39535
39623
|
|
|
39536
|
-
5o.
|
|
39624
|
+
5o. Call update_task_status with status "completed", proceed to next task.
|
|
39537
39625
|
|
|
39538
39626
|
## \u26D4 RETROSPECTIVE GATE
|
|
39539
39627
|
|
|
@@ -39541,31 +39629,26 @@ PRE-COMMIT RULE \u2014 Before ANY commit or push:
|
|
|
39541
39629
|
|
|
39542
39630
|
**How to write the retrospective:**
|
|
39543
39631
|
|
|
39544
|
-
|
|
39545
|
-
|
|
39546
|
-
|
|
39547
|
-
|
|
39548
|
-
|
|
39549
|
-
|
|
39550
|
-
|
|
39551
|
-
|
|
39552
|
-
|
|
39553
|
-
|
|
39554
|
-
|
|
39555
|
-
|
|
39556
|
-
|
|
39557
|
-
|
|
39558
|
-
|
|
39559
|
-
|
|
39560
|
-
"timestamp": "<ISO 8601>",
|
|
39561
|
-
"agent": "architect",
|
|
39562
|
-
"metadata": { "plan_id": "<current plan title from .swarm/plan.json>" }
|
|
39563
|
-
}
|
|
39564
|
-
\`\`\`
|
|
39632
|
+
Call the \`write_retro\` tool with the required fields:
|
|
39633
|
+
- \`phase\`: The phase number being completed (e.g., 1, 2, 3)
|
|
39634
|
+
- \`summary\`: Human-readable summary of the phase
|
|
39635
|
+
- \`task_count\`: Count of tasks completed in this phase
|
|
39636
|
+
- \`task_complexity\`: One of \`trivial\` | \`simple\` | \`moderate\` | \`complex\`
|
|
39637
|
+
- \`total_tool_calls\`: Total number of tool calls in this phase
|
|
39638
|
+
- \`coder_revisions\`: Number of coder revisions made
|
|
39639
|
+
- \`reviewer_rejections\`: Number of reviewer rejections received
|
|
39640
|
+
- \`test_failures\`: Number of test failures encountered
|
|
39641
|
+
- \`security_findings\`: Number of security findings
|
|
39642
|
+
- \`integration_issues\`: Number of integration issues
|
|
39643
|
+
- \`lessons_learned\`: (optional) Key lessons learned from this phase (max 5)
|
|
39644
|
+
- \`top_rejection_reasons\`: (optional) Top reasons for reviewer rejections
|
|
39645
|
+
- \`metadata\`: (optional) Additional metadata, e.g., \`{ "plan_id": "<current plan title from .swarm/plan.json>" }\`
|
|
39646
|
+
|
|
39647
|
+
The tool will automatically write the retrospective to \`.swarm/evidence/retro-{phase}/evidence.json\` with the correct schema wrapper.
|
|
39565
39648
|
|
|
39566
39649
|
**Required field rules:**
|
|
39567
|
-
- \`verdict\`
|
|
39568
|
-
- \`
|
|
39650
|
+
- \`verdict\` is auto-generated by write_retro with value \`"pass"\`. The resulting retrospective entry will have verdict \`"pass"\`; this is required for phase_complete to succeed.
|
|
39651
|
+
- \`phase\` MUST match the phase number you are completing
|
|
39569
39652
|
- \`lessons_learned\` should be 3-5 concrete, actionable items from this phase
|
|
39570
39653
|
- Write the bundle as task_id \`retro-{N}\` (e.g., \`retro-1\` for Phase 1, \`retro-2\` for Phase 2)
|
|
39571
39654
|
- \`metadata.plan_id\` should be set to the current project's plan title (from \`.swarm/plan.json\` header). This enables cross-project filtering in the retrospective injection system.
|
|
@@ -39590,7 +39673,7 @@ Use the evidence manager tool to write a bundle at \`retro-{N}\` (where N is the
|
|
|
39590
39673
|
- Summary of what was added/modified/removed
|
|
39591
39674
|
- List of doc files that may need updating (README.md, CONTRIBUTING.md, docs/)
|
|
39592
39675
|
3. Update context.md
|
|
39593
|
-
4. Write retrospective evidence: record
|
|
39676
|
+
4. Write retrospective evidence: record phase, total_tool_calls, coder_revisions, reviewer_rejections, test_failures, security_findings, integration_issues, task_count, task_complexity, top_rejection_reasons, lessons_learned to .swarm/evidence/ via write_retro. Reset Phase Metrics in context.md to 0.
|
|
39594
39677
|
4.5. Run \`evidence_check\` to verify all completed tasks have required evidence (review + test). If gaps found, note in retrospective lessons_learned. Optionally run \`pkg_audit\` if dependencies were modified during this phase. Optionally run \`schema_drift\` if API routes were modified during this phase.
|
|
39595
39678
|
5. Run \`sbom_generate\` with scope='changed' to capture post-implementation dependency snapshot (saved to \`.swarm/evidence/sbom/\`). This is a non-blocking step - always proceeds to summary.
|
|
39596
39679
|
5.5. If \`.swarm/spec.md\` exists: delegate {{AGENT_PREFIX}}critic with DRIFT-CHECK context \u2014 include phase number, list of completed task IDs and descriptions, and evidence path (\`.swarm/evidence/\`). If SIGNIFICANT DRIFT is returned: surface as a warning to the user before proceeding. If spec.md does not exist: skip silently.
|
|
@@ -40757,6 +40840,9 @@ function getAgentConfigs(config2) {
|
|
|
40757
40840
|
} else {
|
|
40758
40841
|
sdkConfig.mode = "subagent";
|
|
40759
40842
|
}
|
|
40843
|
+
if (sdkConfig.mode === "primary") {
|
|
40844
|
+
delete sdkConfig.model;
|
|
40845
|
+
}
|
|
40760
40846
|
const baseAgentName = stripKnownSwarmPrefix(agent.name);
|
|
40761
40847
|
if (!toolFilterEnabled) {
|
|
40762
40848
|
sdkConfig.tools = agent.config.tools ?? {};
|
|
@@ -51890,10 +51976,17 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
51890
51976
|
let retroFound = false;
|
|
51891
51977
|
let retroEntry = null;
|
|
51892
51978
|
let invalidSchemaErrors = [];
|
|
51979
|
+
let loadedRetroTaskId = null;
|
|
51980
|
+
let loadedRetroBundle = null;
|
|
51981
|
+
const primaryRetroTaskId = `retro-${phase}`;
|
|
51893
51982
|
if (retroResult.status === "found") {
|
|
51894
51983
|
const validEntry = retroResult.bundle.entries?.find((entry) => isValidRetroEntry(entry, phase));
|
|
51895
|
-
|
|
51896
|
-
|
|
51984
|
+
if (validEntry) {
|
|
51985
|
+
retroFound = true;
|
|
51986
|
+
retroEntry = validEntry;
|
|
51987
|
+
loadedRetroTaskId = primaryRetroTaskId;
|
|
51988
|
+
loadedRetroBundle = retroResult.bundle;
|
|
51989
|
+
}
|
|
51897
51990
|
} else if (retroResult.status === "invalid_schema") {
|
|
51898
51991
|
invalidSchemaErrors = retroResult.errors;
|
|
51899
51992
|
}
|
|
@@ -51909,9 +52002,11 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
51909
52002
|
continue;
|
|
51910
52003
|
}
|
|
51911
52004
|
const validEntry = bundleResult.bundle.entries?.find((entry) => isValidRetroEntry(entry, phase));
|
|
51912
|
-
|
|
51913
|
-
|
|
52005
|
+
if (validEntry) {
|
|
52006
|
+
retroFound = true;
|
|
51914
52007
|
retroEntry = validEntry;
|
|
52008
|
+
loadedRetroTaskId = taskId;
|
|
52009
|
+
loadedRetroBundle = bundleResult.bundle;
|
|
51915
52010
|
break;
|
|
51916
52011
|
}
|
|
51917
52012
|
}
|
|
@@ -51989,6 +52084,11 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
51989
52084
|
}
|
|
51990
52085
|
const agentsMissing = effectiveRequired.filter((req) => !crossSessionResult.agents.has(req));
|
|
51991
52086
|
const warnings = [];
|
|
52087
|
+
const VALID_TASK_COMPLEXITY = ["trivial", "simple", "moderate", "complex"];
|
|
52088
|
+
const firstEntry = loadedRetroBundle?.entries?.[0];
|
|
52089
|
+
if (loadedRetroTaskId?.startsWith("retro-") && loadedRetroBundle?.schema_version === "1.0.0" && firstEntry?.task_complexity && VALID_TASK_COMPLEXITY.includes(firstEntry.task_complexity)) {
|
|
52090
|
+
warnings.push(`Retrospective data for phase ${phase} may have been automatically migrated to current schema format.`);
|
|
52091
|
+
}
|
|
51992
52092
|
let success3 = true;
|
|
51993
52093
|
let status = "success";
|
|
51994
52094
|
const safeSummary = summary?.trim().slice(0, 500);
|
|
@@ -57672,11 +57772,133 @@ var MAX_FILE_SIZE2 = 5 * 1024 * 1024;
|
|
|
57672
57772
|
// src/tools/index.ts
|
|
57673
57773
|
init_test_runner();
|
|
57674
57774
|
|
|
57675
|
-
// src/tools/
|
|
57676
|
-
|
|
57775
|
+
// src/tools/update-task-status.ts
|
|
57776
|
+
init_tool();
|
|
57777
|
+
init_manager2();
|
|
57677
57778
|
init_create_tool();
|
|
57678
57779
|
import * as fs29 from "fs";
|
|
57679
57780
|
import * as path42 from "path";
|
|
57781
|
+
var VALID_STATUSES = [
|
|
57782
|
+
"pending",
|
|
57783
|
+
"in_progress",
|
|
57784
|
+
"completed",
|
|
57785
|
+
"blocked"
|
|
57786
|
+
];
|
|
57787
|
+
function validateStatus(status) {
|
|
57788
|
+
if (!VALID_STATUSES.includes(status)) {
|
|
57789
|
+
return `Invalid status "${status}". Must be one of: ${VALID_STATUSES.join(", ")}`;
|
|
57790
|
+
}
|
|
57791
|
+
return;
|
|
57792
|
+
}
|
|
57793
|
+
function validateTaskId(taskId) {
|
|
57794
|
+
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
57795
|
+
if (!taskIdPattern.test(taskId)) {
|
|
57796
|
+
return `Invalid task_id "${taskId}". Must match pattern N.M or N.M.P (e.g., "1.1", "1.2.3")`;
|
|
57797
|
+
}
|
|
57798
|
+
return;
|
|
57799
|
+
}
|
|
57800
|
+
async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
57801
|
+
const statusError = validateStatus(args2.status);
|
|
57802
|
+
if (statusError) {
|
|
57803
|
+
return {
|
|
57804
|
+
success: false,
|
|
57805
|
+
message: "Validation failed",
|
|
57806
|
+
errors: [statusError]
|
|
57807
|
+
};
|
|
57808
|
+
}
|
|
57809
|
+
const taskIdError = validateTaskId(args2.task_id);
|
|
57810
|
+
if (taskIdError) {
|
|
57811
|
+
return {
|
|
57812
|
+
success: false,
|
|
57813
|
+
message: "Validation failed",
|
|
57814
|
+
errors: [taskIdError]
|
|
57815
|
+
};
|
|
57816
|
+
}
|
|
57817
|
+
let normalizedDir;
|
|
57818
|
+
if (args2.working_directory != null) {
|
|
57819
|
+
if (args2.working_directory.includes("\x00")) {
|
|
57820
|
+
return {
|
|
57821
|
+
success: false,
|
|
57822
|
+
message: "Invalid working_directory: null bytes are not allowed"
|
|
57823
|
+
};
|
|
57824
|
+
}
|
|
57825
|
+
if (process.platform === "win32") {
|
|
57826
|
+
const devicePathPattern = /^\\\\|^(NUL|CON|AUX|COM[1-9]|LPT[1-9])(\..*)?$/i;
|
|
57827
|
+
if (devicePathPattern.test(args2.working_directory)) {
|
|
57828
|
+
return {
|
|
57829
|
+
success: false,
|
|
57830
|
+
message: "Invalid working_directory: Windows device paths are not allowed"
|
|
57831
|
+
};
|
|
57832
|
+
}
|
|
57833
|
+
}
|
|
57834
|
+
normalizedDir = path42.normalize(args2.working_directory);
|
|
57835
|
+
const pathParts = normalizedDir.split(path42.sep);
|
|
57836
|
+
if (pathParts.includes("..")) {
|
|
57837
|
+
return {
|
|
57838
|
+
success: false,
|
|
57839
|
+
message: "Invalid working_directory: path traversal sequences (..) are not allowed",
|
|
57840
|
+
errors: [
|
|
57841
|
+
"Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
57842
|
+
]
|
|
57843
|
+
};
|
|
57844
|
+
}
|
|
57845
|
+
const resolvedDir = path42.resolve(normalizedDir);
|
|
57846
|
+
try {
|
|
57847
|
+
const realPath = fs29.realpathSync(resolvedDir);
|
|
57848
|
+
const planPath = path42.join(realPath, ".swarm", "plan.json");
|
|
57849
|
+
if (!fs29.existsSync(planPath)) {
|
|
57850
|
+
return {
|
|
57851
|
+
success: false,
|
|
57852
|
+
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
57853
|
+
errors: [
|
|
57854
|
+
`Invalid working_directory: plan not found in "${realPath}"`
|
|
57855
|
+
]
|
|
57856
|
+
};
|
|
57857
|
+
}
|
|
57858
|
+
} catch {
|
|
57859
|
+
return {
|
|
57860
|
+
success: false,
|
|
57861
|
+
message: `Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`,
|
|
57862
|
+
errors: [
|
|
57863
|
+
`Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`
|
|
57864
|
+
]
|
|
57865
|
+
};
|
|
57866
|
+
}
|
|
57867
|
+
}
|
|
57868
|
+
const directory = normalizedDir ?? fallbackDir ?? process.cwd();
|
|
57869
|
+
try {
|
|
57870
|
+
const updatedPlan = await updateTaskStatus(directory, args2.task_id, args2.status);
|
|
57871
|
+
return {
|
|
57872
|
+
success: true,
|
|
57873
|
+
message: "Task status updated successfully",
|
|
57874
|
+
task_id: args2.task_id,
|
|
57875
|
+
new_status: args2.status,
|
|
57876
|
+
current_phase: updatedPlan.current_phase
|
|
57877
|
+
};
|
|
57878
|
+
} catch (error93) {
|
|
57879
|
+
return {
|
|
57880
|
+
success: false,
|
|
57881
|
+
message: "Failed to update task status",
|
|
57882
|
+
errors: [String(error93)]
|
|
57883
|
+
};
|
|
57884
|
+
}
|
|
57885
|
+
}
|
|
57886
|
+
var update_task_status = createSwarmTool({
|
|
57887
|
+
description: "Update the status of a specific task in the implementation plan. " + "Task status can be one of: pending, in_progress, completed, blocked.",
|
|
57888
|
+
args: {
|
|
57889
|
+
task_id: tool.schema.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/, "Task ID must be in N.M or N.M.P format").describe('Task ID in N.M format, e.g. "1.1", "1.2.3"'),
|
|
57890
|
+
status: tool.schema.enum(["pending", "in_progress", "completed", "blocked"]).describe("New status for the task: pending, in_progress, completed, or blocked"),
|
|
57891
|
+
working_directory: tool.schema.string().optional().describe("Working directory where the plan is located")
|
|
57892
|
+
},
|
|
57893
|
+
execute: async (args2, _directory) => {
|
|
57894
|
+
return JSON.stringify(await executeUpdateTaskStatus(args2, _directory), null, 2);
|
|
57895
|
+
}
|
|
57896
|
+
});
|
|
57897
|
+
// src/tools/todo-extract.ts
|
|
57898
|
+
init_dist();
|
|
57899
|
+
init_create_tool();
|
|
57900
|
+
import * as fs30 from "fs";
|
|
57901
|
+
import * as path43 from "path";
|
|
57680
57902
|
var MAX_TEXT_LENGTH = 200;
|
|
57681
57903
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
57682
57904
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -57747,9 +57969,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
57747
57969
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
57748
57970
|
}
|
|
57749
57971
|
try {
|
|
57750
|
-
const resolvedPath =
|
|
57751
|
-
const normalizedCwd =
|
|
57752
|
-
const normalizedResolved =
|
|
57972
|
+
const resolvedPath = path43.resolve(paths);
|
|
57973
|
+
const normalizedCwd = path43.resolve(cwd);
|
|
57974
|
+
const normalizedResolved = path43.resolve(resolvedPath);
|
|
57753
57975
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
57754
57976
|
return {
|
|
57755
57977
|
error: "paths must be within the current working directory",
|
|
@@ -57765,13 +57987,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
57765
57987
|
}
|
|
57766
57988
|
}
|
|
57767
57989
|
function isSupportedExtension(filePath) {
|
|
57768
|
-
const ext =
|
|
57990
|
+
const ext = path43.extname(filePath).toLowerCase();
|
|
57769
57991
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
57770
57992
|
}
|
|
57771
57993
|
function findSourceFiles3(dir, files = []) {
|
|
57772
57994
|
let entries;
|
|
57773
57995
|
try {
|
|
57774
|
-
entries =
|
|
57996
|
+
entries = fs30.readdirSync(dir);
|
|
57775
57997
|
} catch {
|
|
57776
57998
|
return files;
|
|
57777
57999
|
}
|
|
@@ -57780,10 +58002,10 @@ function findSourceFiles3(dir, files = []) {
|
|
|
57780
58002
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
57781
58003
|
continue;
|
|
57782
58004
|
}
|
|
57783
|
-
const fullPath =
|
|
58005
|
+
const fullPath = path43.join(dir, entry);
|
|
57784
58006
|
let stat2;
|
|
57785
58007
|
try {
|
|
57786
|
-
stat2 =
|
|
58008
|
+
stat2 = fs30.statSync(fullPath);
|
|
57787
58009
|
} catch {
|
|
57788
58010
|
continue;
|
|
57789
58011
|
}
|
|
@@ -57876,7 +58098,7 @@ var todo_extract = createSwarmTool({
|
|
|
57876
58098
|
return JSON.stringify(errorResult, null, 2);
|
|
57877
58099
|
}
|
|
57878
58100
|
const scanPath = resolvedPath;
|
|
57879
|
-
if (!
|
|
58101
|
+
if (!fs30.existsSync(scanPath)) {
|
|
57880
58102
|
const errorResult = {
|
|
57881
58103
|
error: `path not found: ${pathsInput}`,
|
|
57882
58104
|
total: 0,
|
|
@@ -57886,13 +58108,13 @@ var todo_extract = createSwarmTool({
|
|
|
57886
58108
|
return JSON.stringify(errorResult, null, 2);
|
|
57887
58109
|
}
|
|
57888
58110
|
const filesToScan = [];
|
|
57889
|
-
const stat2 =
|
|
58111
|
+
const stat2 = fs30.statSync(scanPath);
|
|
57890
58112
|
if (stat2.isFile()) {
|
|
57891
58113
|
if (isSupportedExtension(scanPath)) {
|
|
57892
58114
|
filesToScan.push(scanPath);
|
|
57893
58115
|
} else {
|
|
57894
58116
|
const errorResult = {
|
|
57895
|
-
error: `unsupported file extension: ${
|
|
58117
|
+
error: `unsupported file extension: ${path43.extname(scanPath)}`,
|
|
57896
58118
|
total: 0,
|
|
57897
58119
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
57898
58120
|
entries: []
|
|
@@ -57905,11 +58127,11 @@ var todo_extract = createSwarmTool({
|
|
|
57905
58127
|
const allEntries = [];
|
|
57906
58128
|
for (const filePath of filesToScan) {
|
|
57907
58129
|
try {
|
|
57908
|
-
const fileStat =
|
|
58130
|
+
const fileStat = fs30.statSync(filePath);
|
|
57909
58131
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
57910
58132
|
continue;
|
|
57911
58133
|
}
|
|
57912
|
-
const content =
|
|
58134
|
+
const content = fs30.readFileSync(filePath, "utf-8");
|
|
57913
58135
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
57914
58136
|
allEntries.push(...entries);
|
|
57915
58137
|
} catch {}
|
|
@@ -58017,7 +58239,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
58017
58239
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
58018
58240
|
preflightTriggerManager = new PTM(automationConfig);
|
|
58019
58241
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
58020
|
-
const swarmDir =
|
|
58242
|
+
const swarmDir = path44.resolve(ctx.directory, ".swarm");
|
|
58021
58243
|
statusArtifact = new ASA(swarmDir);
|
|
58022
58244
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
58023
58245
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -58129,7 +58351,9 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
58129
58351
|
secretscan,
|
|
58130
58352
|
symbols,
|
|
58131
58353
|
test_runner,
|
|
58132
|
-
todo_extract
|
|
58354
|
+
todo_extract,
|
|
58355
|
+
update_task_status,
|
|
58356
|
+
write_retro
|
|
58133
58357
|
},
|
|
58134
58358
|
config: async (opencodeConfig) => {
|
|
58135
58359
|
if (!opencodeConfig.agent) {
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -23,5 +23,6 @@ export { type SecretFinding, type SecretscanResult, secretscan, } from './secret
|
|
|
23
23
|
export { symbols } from './symbols';
|
|
24
24
|
export { type SyntaxCheckFileResult, type SyntaxCheckInput, type SyntaxCheckResult, syntaxCheck, } from './syntax-check';
|
|
25
25
|
export { test_runner } from './test-runner';
|
|
26
|
+
export { type UpdateTaskStatusArgs, type UpdateTaskStatusResult, executeUpdateTaskStatus, update_task_status, } from './update-task-status';
|
|
26
27
|
export { todo_extract } from './todo-extract';
|
|
27
28
|
export { executeWriteRetro, write_retro } from './write-retro';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Used for constants and agent setup references.
|
|
4
4
|
*/
|
|
5
5
|
/** Union type of all valid tool names */
|
|
6
|
-
export type ToolName = 'diff' | 'syntax_check' | 'placeholder_scan' | 'imports' | 'lint' | 'secretscan' | 'sast_scan' | 'build_check' | 'pre_check_batch' | 'quality_budget' | 'symbols' | 'complexity_hotspots' | 'schema_drift' | 'todo_extract' | 'evidence_check' | 'sbom_generate' | 'checkpoint' | 'pkg_audit' | 'test_runner' | 'detect_domains' | 'gitingest' | 'retrieve_summary' | 'extract_code_blocks' | 'phase_complete' | 'save_plan';
|
|
6
|
+
export type ToolName = 'diff' | 'syntax_check' | 'placeholder_scan' | 'imports' | 'lint' | 'secretscan' | 'sast_scan' | 'build_check' | 'pre_check_batch' | 'quality_budget' | 'symbols' | 'complexity_hotspots' | 'schema_drift' | 'todo_extract' | 'evidence_check' | 'sbom_generate' | 'checkpoint' | 'pkg_audit' | 'test_runner' | 'detect_domains' | 'gitingest' | 'retrieve_summary' | 'extract_code_blocks' | 'phase_complete' | 'save_plan' | 'update_task_status' | 'write_retro';
|
|
7
7
|
/** Readonly array of all tool names */
|
|
8
8
|
export declare const TOOL_NAMES: readonly ToolName[];
|
|
9
9
|
/** Set for O(1) tool name validation */
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update task status tool for changing the status of individual tasks in a plan.
|
|
3
|
+
* Allows agents to mark tasks as pending, in_progress, completed, or blocked.
|
|
4
|
+
*/
|
|
5
|
+
import { type ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
6
|
+
/**
|
|
7
|
+
* Arguments for the update_task_status tool
|
|
8
|
+
*/
|
|
9
|
+
export interface UpdateTaskStatusArgs {
|
|
10
|
+
task_id: string;
|
|
11
|
+
status: string;
|
|
12
|
+
working_directory?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Result from executing update_task_status
|
|
16
|
+
*/
|
|
17
|
+
export interface UpdateTaskStatusResult {
|
|
18
|
+
success: boolean;
|
|
19
|
+
message: string;
|
|
20
|
+
task_id?: string;
|
|
21
|
+
new_status?: string;
|
|
22
|
+
current_phase?: number;
|
|
23
|
+
errors?: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Validate that the status is one of the allowed values.
|
|
27
|
+
* @param status - The status to validate
|
|
28
|
+
* @returns Error message if invalid, undefined if valid
|
|
29
|
+
*/
|
|
30
|
+
export declare function validateStatus(status: string): string | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Validate that task_id matches the required format (N.M or N.M.P).
|
|
33
|
+
* @param taskId - The task ID to validate
|
|
34
|
+
* @returns Error message if invalid, undefined if valid
|
|
35
|
+
*/
|
|
36
|
+
export declare function validateTaskId(taskId: string): string | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Execute the update_task_status tool.
|
|
39
|
+
* Validates the task_id and status, then updates the task status in the plan.
|
|
40
|
+
* @param args - The update task status arguments
|
|
41
|
+
* @returns UpdateTaskStatusResult with success status and details
|
|
42
|
+
*/
|
|
43
|
+
export declare function executeUpdateTaskStatus(args: UpdateTaskStatusArgs, fallbackDir?: string): Promise<UpdateTaskStatusResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Tool definition for update_task_status
|
|
46
|
+
*/
|
|
47
|
+
export declare const update_task_status: ToolDefinition;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.19.
|
|
3
|
+
"version": "6.19.7",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|