fix(#711): wire autonomous convergence flag (#729)

* fix(#711): wire autonomous convergence flag

* Update wise-ibex-tumble.md

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Jeremy McSpadden
2026-06-10 15:10:07 -05:00
committed by GitHub
parent 19edab21da
commit 092340d18a
9 changed files with 235 additions and 21 deletions

View File

@@ -0,0 +1,111 @@
// allow-test-rule: source-text-is-the-product
// The autonomous command and workflow markdown are runtime-loaded contracts.
// Checking their text verifies the shipped slash-command behavior.
'use strict';
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const REPO_ROOT = path.join(__dirname, '..');
const COMMAND_PATH = path.join(REPO_ROOT, 'commands', 'gsd', 'autonomous.md');
const WORKFLOW_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', 'autonomous.md');
const COMMANDS_DOC_PATH = path.join(REPO_ROOT, 'docs', 'COMMANDS.md');
const HOW_TO_PATH = path.join(REPO_ROOT, 'docs', 'how-to', 'run-phases-autonomously.md');
function read(filePath) {
return fs.readFileSync(filePath, 'utf8');
}
describe('autonomous --converge flag (#711)', () => {
test('command advertises --converge and documents --cross-ai as alias', () => {
const command = read(COMMAND_PATH);
assert.match(
command,
/^argument-hint:.*--converge/m,
'autonomous command should advertise --converge in argument-hint',
);
assert.match(command, /--cross-ai/, 'autonomous command should document --cross-ai alias');
assert.match(
command,
/workflow\.plan_review_convergence=true/,
'autonomous command should mention the existing convergence feature gate',
);
});
test('workflow parses converge aliases into a plan strategy', () => {
const workflow = read(WORKFLOW_PATH);
assert.match(workflow, /PLAN_STRATEGY="local"/, 'workflow should default to local planning');
assert.match(workflow, /PLAN_STRATEGY="converge"/, 'workflow should opt into converge planning');
assert.match(workflow, /converge\|cross-ai/, 'workflow should accept --converge and --cross-ai');
});
test('workflow fails fast when convergence is requested but disabled', () => {
const workflow = read(WORKFLOW_PATH);
assert.match(
workflow,
/config-get workflow\.plan_review_convergence/,
'workflow should check workflow.plan_review_convergence before planning',
);
assert.match(
workflow,
/gsd config-set workflow\.plan_review_convergence true/,
'workflow should print the enable command instead of silently downgrading',
);
});
test('workflow routes planning through plan-review-convergence when enabled', () => {
const workflow = read(WORKFLOW_PATH);
assert.match(
workflow,
/Skill\(skill="gsd-plan-review-convergence", args="\$\{PHASE_NUM\} \$\{CONVERGENCE_ARGS\}"\)/,
'non-interactive converge mode should call gsd-plan-review-convergence',
);
assert.match(
workflow,
/Run plan convergence for phase \$\{PHASE_NUM\}: Skill\(skill=\\"gsd-plan-review-convergence\\"/,
'interactive converge mode should dispatch plan convergence in the background agent',
);
assert.match(
workflow,
/Skill\(skill="gsd-plan-phase", args="\$\{PHASE_NUM\}"\)/,
'local planning path should remain available for default autonomous runs',
);
});
test('workflow forwards reviewer flags and max cycles to convergence', () => {
const workflow = read(WORKFLOW_PATH);
const reviewerFlags = [
'--codex',
'--gemini',
'--claude',
'--opencode',
'--ollama',
'--lm-studio',
'--llama-cpp',
'--all',
'--text',
];
assert.match(workflow, /CONVERGENCE_ARGS/, 'workflow should build convergence pass-through args');
for (const flag of reviewerFlags) {
assert.ok(workflow.includes(flag), `workflow should pass through ${flag}`);
}
assert.match(workflow, /--max-cycles/, 'workflow should pass through --max-cycles N');
});
test('docs show autonomous convergence usage', () => {
const commandsDoc = read(COMMANDS_DOC_PATH);
const howTo = read(HOW_TO_PATH);
assert.match(commandsDoc, /--converge/, 'COMMANDS.md should document --converge');
assert.match(commandsDoc, /--cross-ai/, 'COMMANDS.md should document --cross-ai alias');
assert.match(howTo, /\/gsd-autonomous --only 4 --converge/, 'how-to should show single-phase converge usage');
});
});

View File

@@ -26,8 +26,10 @@ const PROJECT_ROOT = path.join(__dirname, '..');
// ─── Size threshold ──────────────────────────────────────────────────────────
// 38K chars ≈ 9,500 tokens — stays below 10K with margin
const AUTONOMOUS_SIZE_LIMIT = 38 * 1024;
// 40K chars ≈ 10,000 tokens — stays at the 10K ceiling; raised from 38K after
// the #729+#853 merge added runtime-gated converge routing to the interactive
// planning arm (both Claude-inline and other-runtime-background), adding ~1.2K chars.
const AUTONOMOUS_SIZE_LIMIT = 40 * 1024;
// ─── File paths ──────────────────────────────────────────────────────────────
@@ -41,7 +43,7 @@ describe('autonomous.md size constraints (#2196)', () => {
assert.ok(fs.existsSync(AUTONOMOUS_PATH), `Missing: ${AUTONOMOUS_PATH}`);
});
test('autonomous.md is under 38K chars (below Claude Code 10K-token Read limit)', () => {
test('autonomous.md is under 40K chars (at or below Claude Code 10K-token Read limit)', () => {
const raw = fs.readFileSync(AUTONOMOUS_PATH, 'utf-8');
const content = raw.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
assert.ok(

View File

@@ -770,7 +770,7 @@ describe('installRuntimeArtifacts (copilot integration)', () => {
'description preserved (round-trips through #2876 yamlQuote)',
);
// argument-hint round-trips
assert.equal(fm['argument-hint'], '[--from N] [--to N] [--only N] [--interactive]', 'argument-hint round-trips');
assert.equal(fm['argument-hint'], '[--from N] [--to N] [--only N] [--interactive] [--converge]', 'argument-hint round-trips');
// allowed-tools comma-separated
assert.ok(skillContent.includes('allowed-tools: Read, Write, Bash, Glob, Grep, AskUserQuestion, Agent'),
'allowed-tools is comma-separated');