@sabaiway/agent-workflow-kit 5.11.2 → 7.0.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/CHANGELOG.md +117 -0
- package/README.md +3 -2
- package/SKILL.md +5 -1
- package/bridges/antigravity-cli-bridge/bin/agy-review-await-guard.test.mjs +176 -0
- package/bridges/antigravity-cli-bridge/bin/agy-review.sh +61 -14
- package/bridges/antigravity-cli-bridge/bin/agy-review.test.mjs +606 -467
- package/bridges/antigravity-cli-bridge/references/review-prompt.md +42 -4
- package/bridges/codex-cli-bridge/SKILL.md +18 -5
- package/bridges/codex-cli-bridge/bin/codex-await-guard.test.mjs +161 -0
- package/bridges/codex-cli-bridge/bin/codex-exec.sh +22 -17
- package/bridges/codex-cli-bridge/bin/codex-exec.test.mjs +356 -363
- package/bridges/codex-cli-bridge/bin/codex-review.sh +6 -6
- package/bridges/codex-cli-bridge/bin/codex-review.test.mjs +275 -286
- package/bridges/codex-cli-bridge/capability.json +1 -1
- package/bridges/codex-cli-bridge/references/driving-codex.md +4 -2
- package/bridges/codex-cli-bridge/references/sandbox-and-flags.md +3 -2
- package/bridges/codex-cli-bridge/setup/README.md +3 -1
- package/capability.json +1 -1
- package/package.json +1 -1
- package/references/hooks/gate-approve.mjs +1 -1
- package/references/modes/grounding.md +1 -1
- package/references/modes/mcp.md +37 -0
- package/references/modes/procedures.md +3 -3
- package/references/modes/recommendations.md +1 -0
- package/references/modes/uninstall.md +2 -1
- package/references/templates/agent_rules.md +4 -5
- package/tools/commands.mjs +7 -0
- package/tools/direct-run.mjs +3 -0
- package/tools/doc-parity.mjs +18 -2
- package/tools/grounding.mjs +10 -20
- package/tools/inject-methodology.mjs +2 -0
- package/tools/mcp-registration.mjs +283 -0
- package/tools/mcp-server.mjs +314 -0
- package/tools/mcp-stdio.mjs +229 -0
- package/tools/mcp.mjs +299 -0
- package/tools/procedures.mjs +7 -8
- package/tools/recommendations.mjs +90 -1
- package/tools/uninstall.mjs +356 -45
|
@@ -59,6 +59,13 @@ import { shellQuoteArg } from './review-state.mjs';
|
|
|
59
59
|
import { isFinalCapableDeclaration } from './run-gates.mjs';
|
|
60
60
|
import { loadDeclaration, canonicalCheckerGates, coverageProducerPrecedes, isKitOwnedCheckerGate, GATES_REL, LCOV_PRODUCER_KEY } from './gates-declaration.mjs';
|
|
61
61
|
import { readRegularFileNoFollow } from './fs-read-nofollow.mjs';
|
|
62
|
+
// The typed channel's READ-ONLY leaf only — never tools/mcp.mjs, which reaches the write core.
|
|
63
|
+
import {
|
|
64
|
+
MCP_JSON_REL,
|
|
65
|
+
SERVER_NAME as MCP_SERVER_NAME,
|
|
66
|
+
STATE as MCP_STATE,
|
|
67
|
+
readRegistration,
|
|
68
|
+
} from './mcp-registration.mjs';
|
|
62
69
|
import { matchesCoverageProducer, isCoverageProducerGate } from './coverage-producer.mjs';
|
|
63
70
|
// How much of the TRACKED tree the changed-line coverage domain can assess at all — the fact that
|
|
64
71
|
// turns "the checker certifies" into "the checker certifies the assessable minority".
|
|
@@ -143,6 +150,13 @@ export const SEVERITIES = Object.freeze({
|
|
|
143
150
|
'read-lane.stale': SEVERITY_ATTENTION,
|
|
144
151
|
'read-lane.missing': SEVERITY_ATTENTION,
|
|
145
152
|
'state-block': SEVERITY_OPTIONAL,
|
|
153
|
+
// The typed channel. The base arm is an ordinary offer; `.masked` stays an offer too (nothing is
|
|
154
|
+
// broken — the kit simply cannot write through a device node, so the remedy is handed over);
|
|
155
|
+
// `.differing` reports a CONFIGURED declaration that would launch something else, which is the
|
|
156
|
+
// one state here a maintainer must actually look at.
|
|
157
|
+
'mcp-channel': SEVERITY_OPTIONAL,
|
|
158
|
+
'mcp-channel.masked': SEVERITY_OPTIONAL,
|
|
159
|
+
'mcp-channel.differing': SEVERITY_ATTENTION,
|
|
146
160
|
agents: SEVERITY_OPTIONAL,
|
|
147
161
|
'family-freshness': SEVERITY_ATTENTION,
|
|
148
162
|
'adr-store-migration': SEVERITY_ATTENTION,
|
|
@@ -210,6 +224,9 @@ export const WHATS = Object.freeze({
|
|
|
210
224
|
'read-lane.stale': 'the read-lane is ON but the placed gate hook is stale — an old hook never reads lanes.json, so the lane is silently dark; reseed it',
|
|
211
225
|
'read-lane.missing': 'the gate hook is wired but its placed file is missing — every Bash call errors and the read-lane is dark; re-place it',
|
|
212
226
|
'state-block': 'nothing checks the closing state block — a turn that ends on «nothing needed from you», or on a promise it never started, passes unseen',
|
|
227
|
+
'mcp-channel': "the kit's read-only MCP server is not registered here — path questions and literal searches stay shell strings",
|
|
228
|
+
'mcp-channel.masked': '{rel} is a {className} here (a sandbox device mask is the usual cause), so the entry to merge is printed instead',
|
|
229
|
+
'mcp-channel.differing': 'an "{server}" MCP entry is already declared here and DIFFERS from the registration this kit copy would write',
|
|
213
230
|
agents: '{n} read-only subagent(s) not placed (Claude Code) — no shell-free vehicle for that work; the apply PREVIEWS first',
|
|
214
231
|
'family-freshness': '{parts}',
|
|
215
232
|
'adr-store-migration': 'still on the retired 3-tier ADR layout — {shape}',
|
|
@@ -266,6 +283,7 @@ export const BENEFITS = Object.freeze({
|
|
|
266
283
|
'commit-guard': 'integrity — commits require the ONE green --final receipt at the exact staged fingerprint (consented pre-commit arm)',
|
|
267
284
|
'read-lane': 'velocity — pipes/chains of your seeded read-only commands auto-approve instead of prompting (opt-in, conservatively classified)',
|
|
268
285
|
'state-block': 'no silent stalls — a turn ending on «you are not needed», or on work it never started, warns at once instead of waiting to be spotted',
|
|
286
|
+
'mcp-channel': 'velocity — path facts and literal searches arrive as typed tool calls whose arguments are JSON fields, never a shell string',
|
|
269
287
|
agents: 'cost and quiet — mechanical work runs on a cheap model, and no vehicle has a shell, so a read-only fan-out cannot flood you with prompts',
|
|
270
288
|
'family-freshness': 'currency — placed family members carry the latest shipped fixes and features',
|
|
271
289
|
'adr-store-migration': 'durability — every decision becomes its own file with a generated navigator, instead of one hand-rotated pile',
|
|
@@ -311,6 +329,7 @@ export const OPT_IN_CAPABILITIES = Object.freeze([
|
|
|
311
329
|
{ id: 'commit-guard', mode: 'commit-guard', advisorKey: 'commit-guard' },
|
|
312
330
|
{ id: 'state-block', mode: 'state-block-guard', advisorKey: 'state-block' },
|
|
313
331
|
{ id: 'sandbox-masks', mode: 'sandbox-masks', advisorKey: 'sandbox-masks' },
|
|
332
|
+
{ id: 'mcp-channel', mode: 'mcp', advisorKey: 'mcp-channel' },
|
|
314
333
|
{ id: 'worktrees-dir', mode: 'worktrees', advisorKey: 'worktrees-dir' },
|
|
315
334
|
{ id: 'family-freshness', mode: 'upgrade', advisorKey: 'family-freshness' },
|
|
316
335
|
{ id: 'adr-store-migration', mode: 'migrate-adr-store', advisorKey: 'adr-store-migration' },
|
|
@@ -1189,7 +1208,7 @@ const readReadLaneToggle = (root, deps) => {
|
|
|
1189
1208
|
// D3: the risk-marked keys — every key here has a per-item posture note in the mode doc, surfaced
|
|
1190
1209
|
// at the consent moment; the static contract test asserts EXACT bidirectional coverage
|
|
1191
1210
|
// (risk-marked keys == mode-doc note keys — a dropped note goes red, not silent).
|
|
1192
|
-
export const RISK_NOTED_KEYS = Object.freeze(['sandbox-lane', 'read-lane', 'worktrees-dir', 'adr-store-migration', 'gates-inert', 'source-size', 'gate-hook']);
|
|
1211
|
+
export const RISK_NOTED_KEYS = Object.freeze(['sandbox-lane', 'read-lane', 'worktrees-dir', 'adr-store-migration', 'gates-inert', 'source-size', 'gate-hook', 'mcp-channel']);
|
|
1193
1212
|
|
|
1194
1213
|
const probeSandboxLane = ({ root, deps, add, skip }) => {
|
|
1195
1214
|
try {
|
|
@@ -1384,6 +1403,75 @@ export const probeAdrStore = ({ root, deps, add, skip }) => {
|
|
|
1384
1403
|
}
|
|
1385
1404
|
};
|
|
1386
1405
|
|
|
1406
|
+
// The typed-channel item. It asks the READ-ONLY registration leaf and nothing else — importing the
|
|
1407
|
+
// writer would pull the atomic-write core into the advisor's graph (read-graph-purity.test.mjs).
|
|
1408
|
+
// The rendered apply is the mode's FLAGLESS preview on purpose: registering an MCP server means the
|
|
1409
|
+
// client will RUN that command, so the entry is read before it is declared and the `--apply` stays
|
|
1410
|
+
// the maintainer's separate step.
|
|
1411
|
+
const probeMcpChannel = ({ root, deps, add, skip }) => {
|
|
1412
|
+
try {
|
|
1413
|
+
const registration = readRegistration(root, deps);
|
|
1414
|
+
// A target we could not read is never turned into a verdict about what it contains.
|
|
1415
|
+
const assertReadable = (target) => {
|
|
1416
|
+
if (target.state === MCP_STATE.FOREIGN) throw new Error(`${target.rel} is a ${target.className} — refusing to read through it`);
|
|
1417
|
+
if (target.state === MCP_STATE.MALFORMED) throw new Error(`${target.rel} is ${target.reason}`);
|
|
1418
|
+
if (target.state === MCP_STATE.UNREADABLE) throw new Error(`${target.rel} cannot be read (${target.reason})`);
|
|
1419
|
+
};
|
|
1420
|
+
const preview = `node ${q(toolPath('mcp.mjs'))} --cwd ${q(root)}`;
|
|
1421
|
+
// ORDER: the `.mcp.json` half is judged and REPORTED on its own before anything about the
|
|
1422
|
+
// settings half can end the probe. A differing entry is fully observable, and an unreadable
|
|
1423
|
+
// settings file says nothing about it — returning on the settings mask first hid it.
|
|
1424
|
+
assertReadable(registration.mcpJson);
|
|
1425
|
+
const settingsUsable = registration.settings.state !== MCP_STATE.MASKED
|
|
1426
|
+
&& registration.settings.state !== MCP_STATE.FOREIGN
|
|
1427
|
+
&& registration.settings.state !== MCP_STATE.UNREADABLE
|
|
1428
|
+
&& registration.settings.state !== MCP_STATE.MALFORMED;
|
|
1429
|
+
if (registration.mcpJson.differs) {
|
|
1430
|
+
// The remedy is the maintainer's edit either way; the "then run" tail is dropped where that
|
|
1431
|
+
// command could not succeed, so the item never hands over a line that exits 1.
|
|
1432
|
+
const tail = settingsUsable ? `, then run ${preview}` : '';
|
|
1433
|
+
add(
|
|
1434
|
+
'mcp-channel',
|
|
1435
|
+
fillTemplate(WHATS['mcp-channel.differing'], { server: MCP_SERVER_NAME }),
|
|
1436
|
+
`HAND-APPLY: edit ${q(join(root, MCP_JSON_REL))} → remove or rename the "${MCP_SERVER_NAME}" entry${tail}`,
|
|
1437
|
+
'mcp-channel.differing',
|
|
1438
|
+
);
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
assertReadable(registration.settings);
|
|
1442
|
+
// The HAND-APPLY arm renders the MODE's own preview, so it may fire only where that command can
|
|
1443
|
+
// actually run — and the writer refuses a masked settings.json outright (it can neither write it
|
|
1444
|
+
// nor merge into what it cannot read). A masked settings half is therefore a stated SKIP: the
|
|
1445
|
+
// completeness this item decides on is unknowable, and offering a command that exits 1 is worse
|
|
1446
|
+
// than saying nothing.
|
|
1447
|
+
if (registration.settings.state === MCP_STATE.MASKED) {
|
|
1448
|
+
skip('mcp-channel', new Error(`${registration.settings.rel} is a ${registration.settings.className} here (a sandbox device mask is the usual cause) — the registration cannot be judged or written from in here; verify it outside the sandbox`));
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
if (registration.mcpJson.state === MCP_STATE.MASKED) {
|
|
1452
|
+
// The kit cannot write through the mask either, so the remedy is HAND-APPLY. But when the
|
|
1453
|
+
// settings half is already complete, the registration was almost certainly made from outside
|
|
1454
|
+
// the sandbox: what cannot be observed becomes a stated SKIP (optimality withheld), never the
|
|
1455
|
+
// same offer again on every single upgrade.
|
|
1456
|
+
if (registration.settings.complete) {
|
|
1457
|
+
skip('mcp-channel', new Error(`${registration.mcpJson.rel} is a ${registration.mcpJson.className} here (a sandbox device mask is the usual cause) and the settings half is already complete — verify the entry outside the sandbox`));
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
add(
|
|
1461
|
+
'mcp-channel',
|
|
1462
|
+
fillTemplate(WHATS['mcp-channel.masked'], { rel: registration.mcpJson.rel, className: registration.mcpJson.className }),
|
|
1463
|
+
`HAND-APPLY: ${preview}`,
|
|
1464
|
+
'mcp-channel.masked',
|
|
1465
|
+
);
|
|
1466
|
+
return;
|
|
1467
|
+
}
|
|
1468
|
+
if (registration.registered) return;
|
|
1469
|
+
add('mcp-channel', fillTemplate(WHATS['mcp-channel'], {}), preview);
|
|
1470
|
+
} catch (err) {
|
|
1471
|
+
skip('mcp-channel', err);
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
|
|
1387
1475
|
// ── assembly (frozen presentation order) ─────────────────────────────────────────────────────────
|
|
1388
1476
|
const PROBES = Object.freeze([
|
|
1389
1477
|
probeVelocityItems,
|
|
@@ -1402,6 +1490,7 @@ const PROBES = Object.freeze([
|
|
|
1402
1490
|
probeMasksItem,
|
|
1403
1491
|
probeSandboxLane,
|
|
1404
1492
|
probeWorktreesDir,
|
|
1493
|
+
probeMcpChannel,
|
|
1405
1494
|
]);
|
|
1406
1495
|
|
|
1407
1496
|
export const buildRecommendations = ({ cwd, deps = {} } = {}) => {
|