@felixdotgo/aidlc-kit 0.1.1 → 0.3.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/DEVELOPMENT.md +14 -13
- package/README.md +37 -43
- package/dist/assets/.agents/aidlc/docker/Dockerfile.claude +7 -0
- package/dist/assets/.agents/aidlc/docker/Dockerfile.codex +9 -0
- package/dist/assets/.agents/aidlc/docker/Dockerfile.opencode +8 -0
- package/dist/assets/.agents/aidlc/orchestrator.md +2 -2
- package/dist/assets/.agents/aidlc/phase-clarify.md +1 -1
- package/dist/assets/.agents/aidlc/phase-plan.md +2 -2
- package/dist/assets/.agents/aidlc/schemas/config.schema.json +2 -1
- package/dist/assets/.agents/aidlc/schemas/state.schema.json +2 -0
- package/dist/assets/.agents/aidlc/scripts/lib/assignment-store.mjs +94 -48
- package/dist/assets/.agents/aidlc/scripts/lib/context-runtime.mjs +5 -4
- package/dist/assets/.agents/aidlc/scripts/lib/loop-authority.mjs +261 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-commit-message.mjs +45 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-daemon.mjs +206 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-drivers.mjs +100 -14
- package/dist/assets/.agents/aidlc/scripts/lib/loop-env.mjs +279 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-cli.mjs +105 -32
- package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-remote.mjs +17 -1
- package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-supervisor.mjs +24 -7
- package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet.mjs +42 -16
- package/dist/assets/.agents/aidlc/scripts/lib/loop-git.mjs +20 -6
- package/dist/assets/.agents/aidlc/scripts/lib/loop-holder.mjs +376 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-intake.mjs +33 -7
- package/dist/assets/.agents/aidlc/scripts/lib/loop-lease.mjs +67 -61
- package/dist/assets/.agents/aidlc/scripts/lib/loop-leases.mjs +268 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-local-workers.mjs +116 -28
- package/dist/assets/.agents/aidlc/scripts/lib/loop-runtime.mjs +114 -12
- package/dist/assets/.agents/aidlc/scripts/lib/loop-stream.mjs +117 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor-local.mjs +16 -56
- package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor-run-local.mjs +149 -6
- package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor.mjs +9 -1
- package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-docker.mjs +44 -6
- package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-image.mjs +64 -0
- package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-log.mjs +158 -0
- package/dist/assets/.agents/aidlc/scripts/lib/repo-head.mjs +22 -0
- package/dist/assets/.agents/aidlc/scripts/lib/store.mjs +68 -2
- package/dist/assets/.agents/aidlc/scripts/lib/task-runtime-migrate.mjs +75 -0
- package/dist/assets/.agents/aidlc/scripts/lib/task-runtime.mjs +97 -0
- package/dist/assets/.agents/aidlc/scripts/loop-entry.mjs +168 -73
- package/dist/assets/.agents/aidlc/scripts/loop-gate.mjs +19 -7
- package/dist/assets/.agents/aidlc/scripts/loop.cmd +101 -0
- package/dist/assets/.agents/aidlc/scripts/loop.mjs +2 -1
- package/dist/assets/.agents/aidlc/scripts/loop.sh +71 -0
- package/dist/assets/.agents/aidlc/scripts/remote-state.mjs +10 -4
- package/dist/assets/.agents/aidlc/scripts/state.mjs +16 -8
- package/dist/assets/.agents/aidlc/templates/design.md +9 -0
- package/dist/assets/.agents/aidlc/templates/intent.md +4 -0
- package/dist/assets/.agents/aidlc/templates/workplan.md +1 -1
- package/dist/assets/.agents/skills/aidlc-plan/SKILL.md +1 -1
- package/dist/assets/ui/bulma.min.css +3 -0
- package/dist/assets/ui/changes.js +83 -0
- package/dist/assets/ui/common.js +664 -0
- package/dist/assets/ui/dashboard.css +636 -0
- package/dist/assets/ui/dashboard.js +77 -0
- package/dist/assets/ui/detail.js +159 -0
- package/dist/assets/ui/live-log.js +332 -0
- package/dist/services/aidlc-coordination/Dockerfile +11 -3
- package/dist/services/aidlc-coordination/compose.yaml +12 -0
- package/dist/services/aidlc-coordination/package-lock.json +3 -1
- package/dist/services/aidlc-coordination/package.json +9 -4
- package/dist/services/aidlc-coordination/src/lifecycle-core.mjs +68 -2
- package/dist/services/aidlc-coordination/src/repository.mjs +66 -0
- package/dist/services/aidlc-coordination/src/server.mjs +9 -3
- package/dist/services/aidlc-coordination/test/fleet.test.mjs +21 -0
- package/dist/services/aidlc-coordination/test/server-health-auth.test.mjs +67 -0
- package/dist/src/adapters.d.ts +0 -3
- package/dist/src/adapters.js +3 -5
- package/dist/src/cli/argv.d.ts +12 -0
- package/dist/src/cli/argv.js +68 -0
- package/dist/src/cli/commands.d.ts +8 -0
- package/dist/src/cli/commands.js +159 -0
- package/dist/src/cli/loop-launcher.d.ts +47 -0
- package/dist/src/cli/loop-launcher.js +322 -0
- package/dist/src/cli/options.d.ts +25 -0
- package/dist/src/cli/options.js +32 -0
- package/dist/src/cli/prompt.d.ts +9 -0
- package/dist/src/cli/prompt.js +66 -0
- package/dist/src/cli.js +28 -191
- package/dist/src/gate.js +3 -2
- package/dist/src/installer.d.ts +14 -7
- package/dist/src/installer.js +42 -143
- package/dist/src/legacy.js +1 -0
- package/dist/src/managed-content.d.ts +7 -0
- package/dist/src/managed-content.js +15 -4
- package/dist/src/managed-planning.d.ts +65 -0
- package/dist/src/managed-planning.js +219 -0
- package/dist/src/mcp-setup.js +3 -1
- package/dist/src/model/config-contracts.d.ts +65 -0
- package/dist/src/model/config-contracts.js +1 -0
- package/dist/src/model/install-contracts.d.ts +29 -0
- package/dist/src/model/install-contracts.js +1 -0
- package/dist/src/model/lifecycle-enums.d.ts +13 -0
- package/dist/src/model/lifecycle-enums.js +1 -0
- package/dist/src/model/loop.d.ts +20 -0
- package/dist/src/model/loop.js +1 -0
- package/dist/src/model/manifest.d.ts +16 -0
- package/dist/src/model/manifest.js +1 -0
- package/dist/src/model/records.d.ts +142 -0
- package/dist/src/model/records.js +1 -0
- package/dist/src/model.d.ts +11 -264
- package/dist/src/model.js +1 -1
- package/dist/src/profiles.d.ts +2 -0
- package/dist/src/profiles.js +53 -9
- package/dist/src/state/archive-record.d.ts +9 -0
- package/dist/src/state/archive-record.js +26 -0
- package/dist/src/state/commands.d.ts +18 -0
- package/dist/src/state/commands.js +27 -0
- package/dist/src/state/domain.d.ts +9 -0
- package/dist/src/state/domain.js +9 -0
- package/dist/src/state/guards.d.ts +7 -0
- package/dist/src/state/guards.js +17 -0
- package/dist/src/state/io.d.ts +10 -0
- package/dist/src/state/io.js +35 -0
- package/dist/src/state/items.d.ts +3 -4
- package/dist/src/state/items.js +58 -57
- package/dist/src/state/lessons.js +14 -7
- package/dist/src/state/lifecycle.js +2 -2
- package/dist/src/state/lock.js +7 -6
- package/dist/src/state/memory.js +24 -12
- package/dist/src/state/{archive.js → migrate.js} +7 -7
- package/dist/src/state/partition.d.ts +15 -0
- package/dist/src/state/partition.js +90 -0
- package/dist/src/state/paths.d.ts +11 -0
- package/dist/src/state/paths.js +12 -0
- package/dist/src/state/render.js +9 -6
- package/dist/src/state/store.js +9 -15
- package/dist/src/state/transitions.js +9 -7
- package/dist/src/state/validate.js +55 -7
- package/dist/src/state.d.ts +16 -11
- package/dist/src/state.js +16 -11
- package/dist/src/task-ui.d.ts +33 -0
- package/dist/src/task-ui.js +33 -0
- package/dist/src/ui/assets.d.ts +14 -0
- package/dist/src/ui/assets.js +45 -0
- package/dist/src/ui/changes.d.ts +83 -0
- package/dist/src/ui/changes.js +498 -0
- package/dist/src/ui/containers.d.ts +71 -0
- package/dist/src/ui/containers.js +214 -0
- package/dist/src/ui/daemon.d.ts +75 -0
- package/dist/src/ui/daemon.js +232 -0
- package/dist/src/ui/data.d.ts +42 -0
- package/dist/src/ui/data.js +89 -0
- package/dist/src/ui/docs.d.ts +13 -0
- package/dist/src/ui/docs.js +39 -0
- package/dist/src/ui/files.d.ts +3 -0
- package/dist/src/ui/files.js +20 -0
- package/dist/src/ui/http.d.ts +14 -0
- package/dist/src/ui/http.js +80 -0
- package/dist/src/ui/live.d.ts +5 -0
- package/dist/src/ui/live.js +43 -0
- package/dist/src/ui/markdown.d.ts +2 -0
- package/dist/src/ui/markdown.js +127 -0
- package/dist/src/ui/options.d.ts +48 -0
- package/dist/src/ui/options.js +81 -0
- package/dist/src/ui/security.d.ts +34 -0
- package/dist/src/ui/security.js +38 -0
- package/dist/src/ui/server.d.ts +39 -0
- package/dist/src/ui/server.js +347 -0
- package/dist/src/ui/sse.d.ts +14 -0
- package/dist/src/ui/sse.js +281 -0
- package/dist/src/ui/views/board.d.ts +7 -0
- package/dist/src/ui/views/board.js +131 -0
- package/dist/src/ui/views/changes.d.ts +19 -0
- package/dist/src/ui/views/changes.js +154 -0
- package/dist/src/ui/views/components.d.ts +56 -0
- package/dist/src/ui/views/components.js +113 -0
- package/dist/src/ui/views/docs.d.ts +15 -0
- package/dist/src/ui/views/docs.js +64 -0
- package/dist/src/ui/views/layout.d.ts +44 -0
- package/dist/src/ui/views/layout.js +233 -0
- package/dist/src/ui/views/task.d.ts +25 -0
- package/dist/src/ui/views/task.js +320 -0
- package/dist/src/upgrade-board.js +10 -10
- package/dist/src/upgrade.d.ts +0 -1
- package/dist/src/upgrade.js +24 -85
- package/dist/src/workflow.d.ts +4 -0
- package/dist/src/workflow.js +36 -4
- package/docs/README.md +41 -22
- package/docs/architecture.md +101 -37
- package/docs/command-reference.md +289 -52
- package/docs/configuration.md +70 -30
- package/docs/coordination-service.md +91 -30
- package/docs/design-decisions.md +87 -0
- package/docs/development.md +124 -49
- package/docs/loop-local-run.md +228 -0
- package/docs/loop-runbook.md +214 -0
- package/docs/operating-workflow.md +55 -42
- package/docs/testing-and-release.md +72 -49
- package/docs/troubleshooting.md +221 -0
- package/package.json +4 -1
- package/dist/src/ledger.d.ts +0 -22
- package/dist/src/ledger.js +0 -119
- package/dist/src/state/shared.d.ts +0 -29
- package/dist/src/state/shared.js +0 -71
- package/dist/src/tracker.d.ts +0 -36
- package/dist/src/tracker.js +0 -44
- /package/dist/src/state/{archive.d.ts → migrate.d.ts} +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive layer: TTY detection, dynamic @inquirer/prompts loading, and the
|
|
3
|
+
* prompting flows (loop configuration, MCP setup selections, confirmations).
|
|
4
|
+
* Parsing of argv into options happens in ./argv.ts and ./options.ts.
|
|
5
|
+
*/
|
|
6
|
+
import { stdin, stdout } from "node:process";
|
|
7
|
+
import { LOOP_PROVIDERS } from "../model.js";
|
|
8
|
+
import { validateLoopConfig } from "../profiles.js";
|
|
9
|
+
import { loopSelection, mcpArgSelections, parseWorkerMapping } from "./options.js";
|
|
10
|
+
export const interactive = () => Boolean(stdin.isTTY && stdout.isTTY);
|
|
11
|
+
const prompts = async () => import("@inquirer/prompts");
|
|
12
|
+
export const chooseLoop = async (args, upgrade) => {
|
|
13
|
+
let { mode, lead: leadArg, workers: workersArg } = loopSelection(args);
|
|
14
|
+
if (!mode && (leadArg || workersArg))
|
|
15
|
+
throw new Error("--loop-lead and --loop-workers require --loop-mode");
|
|
16
|
+
if (!mode && interactive()) {
|
|
17
|
+
const { select } = await prompts();
|
|
18
|
+
mode = await select({ message: "Loop execution mode", choices: [
|
|
19
|
+
...(upgrade ? [{ name: "Keep existing loop configuration", value: "keep" }] : []),
|
|
20
|
+
{ name: "Off", value: "off" }, { name: "Local", value: "local" }, { name: "Fleet", value: "fleet" }
|
|
21
|
+
] });
|
|
22
|
+
}
|
|
23
|
+
if (!mode || mode === "keep")
|
|
24
|
+
return undefined;
|
|
25
|
+
if (mode === "off") {
|
|
26
|
+
if (leadArg || workersArg)
|
|
27
|
+
throw new Error("Disabled loop cannot specify agents");
|
|
28
|
+
return validateLoopConfig({ mode });
|
|
29
|
+
}
|
|
30
|
+
let lead = leadArg, rawWorkers = workersArg;
|
|
31
|
+
if (interactive() && (!lead || !rawWorkers)) {
|
|
32
|
+
const { select, input } = await prompts();
|
|
33
|
+
lead ??= await select({ message: "Lead agent", choices: LOOP_PROVIDERS.map((name) => ({ name, value: name })) });
|
|
34
|
+
rawWorkers ??= await input({ message: "Workers (id=provider, comma separated)", default: "codex-worker=codex,claude-worker=claude" });
|
|
35
|
+
}
|
|
36
|
+
if (!lead || !rawWorkers)
|
|
37
|
+
throw new Error("An enabled loop requires --loop-lead and --loop-workers");
|
|
38
|
+
return validateLoopConfig({ mode, agents: { lead, workers: parseWorkerMapping(rawWorkers) } });
|
|
39
|
+
};
|
|
40
|
+
export const mcpSetupSelections = async (args) => {
|
|
41
|
+
const selected = mcpArgSelections(args);
|
|
42
|
+
if ((!selected.deployment || !selected.storage || !selected.bind || !selected.workspace) && !interactive())
|
|
43
|
+
throw new Error("mcp setup outside a TTY requires --deployment, --storage, --bind and --workspace");
|
|
44
|
+
if (interactive()) {
|
|
45
|
+
const { input, select, checkbox } = await prompts();
|
|
46
|
+
selected.deployment ??= await select({ message: "State service deployment", choices: [{ name: "Docker on this machine", value: "docker" }, { name: "Remote service (configure endpoint later)", value: "remote" }] });
|
|
47
|
+
selected.storage ??= await select({ message: "Database", choices: [{ name: "SQLite (local Docker volume)", value: "sqlite" }, { name: "PostgreSQL (multi-host production)", value: "postgres" }] });
|
|
48
|
+
selected.bind ??= await select({ message: "Network binding", choices: [{ name: "localhost only", value: "localhost" }, { name: "network (requires token/TLS)", value: "network" }] });
|
|
49
|
+
selected.workspace ??= await input({ message: "Workspace ID", default: "default", required: true });
|
|
50
|
+
if (!selected.providers.length)
|
|
51
|
+
selected.providers = await checkbox({ message: "Project-management connectors to configure", choices: ["jira", "trello", "github-issues"].map((value) => ({ name: value, value })) });
|
|
52
|
+
}
|
|
53
|
+
if (!Number.isInteger(selected.pollMs) || selected.pollMs < 1_000 || selected.pollMs > 3_600_000)
|
|
54
|
+
throw new Error("--poll-ms must be an integer from 1000 to 3600000");
|
|
55
|
+
return selected;
|
|
56
|
+
};
|
|
57
|
+
export const confirmGeneral = async (options, operation) => {
|
|
58
|
+
if (options.dryRun)
|
|
59
|
+
return false;
|
|
60
|
+
if (options.yes)
|
|
61
|
+
return true;
|
|
62
|
+
if (!interactive())
|
|
63
|
+
return false;
|
|
64
|
+
const { confirm } = await prompts();
|
|
65
|
+
return confirm({ message: `${operation} this plan?`, default: false });
|
|
66
|
+
};
|
package/dist/src/cli.js
CHANGED
|
@@ -1,96 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { loadProjectConfig, resolveProfiles, validateLoopConfig } from "./profiles.js";
|
|
2
|
+
import { resolvedAdapters } from "./adapters.js";
|
|
3
|
+
import { assertKnownOptions, flags, INIT_FLAGS, rootArg, UNINSTALL_FLAGS, UPGRADE_FLAGS, usage } from "./cli/argv.js";
|
|
4
|
+
import { runDoctor, runLoopCommand, runMcp, runProfile, runStatus, runUi } from "./cli/commands.js";
|
|
5
|
+
import { recordInstallerCli } from "./cli/loop-launcher.js";
|
|
6
|
+
import { initOptions } from "./cli/options.js";
|
|
7
|
+
import { chooseLoop, confirmGeneral, interactive } from "./cli/prompt.js";
|
|
8
|
+
import { applyPlan, detectedAgents, formatPlan, planInit, planUninstall, selectAgents } from "./installer.js";
|
|
10
9
|
import { applyUpgrade, planUpgrade } from "./upgrade.js";
|
|
11
10
|
import { packageVersion } from "./workflow.js";
|
|
12
|
-
|
|
13
|
-
const usage = `Usage:
|
|
14
|
-
npx @felixdotgo/aidlc-kit init [path] [--agent <name[,name]> | --all] [--loop-mode off|local|fleet] [--loop-lead ${LOOP_PROVIDERS.join("|")}] [--loop-workers <id=provider,...>] [--yes] [--dry-run] [--force]
|
|
15
|
-
npx @felixdotgo/aidlc-kit upgrade [path] [--loop-mode off|local|fleet] [--loop-lead ${LOOP_PROVIDERS.join("|")}] [--loop-workers <id=provider,...>] [--dry-run]
|
|
16
|
-
npx @felixdotgo/aidlc-kit uninstall [path] [--yes] [--dry-run]
|
|
17
|
-
npx @felixdotgo/aidlc-kit status [path]
|
|
18
|
-
npx @felixdotgo/aidlc-kit doctor [path] [--strict]
|
|
19
|
-
npx @felixdotgo/aidlc-kit profile validate [path]
|
|
20
|
-
npx @felixdotgo/aidlc-kit loop start|status|resume [--task-id ID] [--root PATH] [--mode local|fleet]
|
|
21
|
-
npx @felixdotgo/aidlc-kit mcp setup [path] [--dry-run] [--yes] [--storage sqlite|postgres] [--deployment docker|remote] [--bind localhost|network] [--workspace <id>] [--poll-ms <n>] [--enable]`;
|
|
22
|
-
const interactive = () => Boolean(stdin.isTTY && stdout.isTTY);
|
|
11
|
+
/* Kept in this file: test/unit/cli.test.ts pins these prompt sources (and the upgrade boundary strings below) to src/cli.ts; the shared interactive flows live in ./cli/prompt.ts. */
|
|
23
12
|
const prompts = async () => import("@inquirer/prompts");
|
|
24
|
-
/* ---
|
|
25
|
-
const value = (args, name) => {
|
|
26
|
-
const index = args.indexOf(name);
|
|
27
|
-
return index < 0 ? undefined : args[index + 1];
|
|
28
|
-
};
|
|
29
|
-
const flags = (args) => new Set(args.filter((item) => item.startsWith("--")));
|
|
30
|
-
const valueFlags = new Set(["--agent", "--storage", "--deployment", "--bind", "--workspace", "--poll-ms", "--token-env", "--providers", "--loop-mode", "--loop-lead", "--loop-workers"]);
|
|
31
|
-
const COMMAND_KEYWORDS = ["init", "upgrade", "uninstall", "status", "doctor", "validate", "run", "list"];
|
|
32
|
-
const positional = (args) => {
|
|
33
|
-
const result = [];
|
|
34
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
35
|
-
if (valueFlags.has(args[index])) {
|
|
36
|
-
index += 1;
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
if (!args[index].startsWith("--"))
|
|
40
|
-
result.push(args[index]);
|
|
41
|
-
}
|
|
42
|
-
return result;
|
|
43
|
-
};
|
|
44
|
-
const rootArg = (args, fallback = ".") => positional(args).find((item) => !COMMAND_KEYWORDS.includes(item)) ?? fallback;
|
|
45
|
-
/* --- Loop configuration --------------------------------------------------- */
|
|
46
|
-
const parseWorkerMapping = (rawWorkers) => {
|
|
47
|
-
const workers = Object.create(null);
|
|
48
|
-
for (const entry of rawWorkers.split(",")) {
|
|
49
|
-
const parts = entry.split("=");
|
|
50
|
-
if (parts.length !== 2 || !parts[0] || !parts[1] || Object.hasOwn(workers, parts[0]))
|
|
51
|
-
throw new Error("Invalid or duplicate loop worker mapping");
|
|
52
|
-
workers[parts[0]] = parts[1];
|
|
53
|
-
}
|
|
54
|
-
return workers;
|
|
55
|
-
};
|
|
56
|
-
const chooseLoop = async (args, upgrade) => {
|
|
57
|
-
let mode = value(args, "--loop-mode");
|
|
58
|
-
const leadArg = value(args, "--loop-lead"), workersArg = value(args, "--loop-workers");
|
|
59
|
-
if (!mode && (leadArg || workersArg))
|
|
60
|
-
throw new Error("--loop-lead and --loop-workers require --loop-mode");
|
|
61
|
-
if (!mode && interactive()) {
|
|
62
|
-
const { select } = await prompts();
|
|
63
|
-
mode = await select({ message: "Loop execution mode", choices: [
|
|
64
|
-
...(upgrade ? [{ name: "Keep existing loop configuration", value: "keep" }] : []),
|
|
65
|
-
{ name: "Off", value: "off" }, { name: "Local", value: "local" }, { name: "Fleet", value: "fleet" }
|
|
66
|
-
] });
|
|
67
|
-
}
|
|
68
|
-
if (!mode || mode === "keep")
|
|
69
|
-
return undefined;
|
|
70
|
-
if (mode === "off") {
|
|
71
|
-
if (leadArg || workersArg)
|
|
72
|
-
throw new Error("Disabled loop cannot specify agents");
|
|
73
|
-
return validateLoopConfig({ mode });
|
|
74
|
-
}
|
|
75
|
-
let lead = leadArg, rawWorkers = workersArg;
|
|
76
|
-
if (interactive() && (!lead || !rawWorkers)) {
|
|
77
|
-
const { select, input } = await prompts();
|
|
78
|
-
lead ??= await select({ message: "Lead agent", choices: LOOP_PROVIDERS.map((name) => ({ name, value: name })) });
|
|
79
|
-
rawWorkers ??= await input({ message: "Workers (id=provider, comma separated)", default: "codex-worker=codex,claude-worker=claude" });
|
|
80
|
-
}
|
|
81
|
-
if (!lead || !rawWorkers)
|
|
82
|
-
throw new Error("An enabled loop requires --loop-lead and --loop-workers");
|
|
83
|
-
return validateLoopConfig({ mode, agents: { lead, workers: parseWorkerMapping(rawWorkers) } });
|
|
84
|
-
};
|
|
85
|
-
/* --- Option builders and shared flows -------------------------------------- */
|
|
86
|
-
const initOptions = (args) => ({
|
|
87
|
-
root: rootArg(args),
|
|
88
|
-
agents: (value(args, "--agent") ?? "").split(",").filter(Boolean),
|
|
89
|
-
all: flags(args).has("--all"),
|
|
90
|
-
dryRun: flags(args).has("--dry-run"),
|
|
91
|
-
yes: flags(args).has("--yes"),
|
|
92
|
-
force: flags(args).has("--force")
|
|
93
|
-
});
|
|
13
|
+
/* --- Agent selection and plan preview -------------------------------------- */
|
|
94
14
|
const chooseAgents = async (options) => {
|
|
95
15
|
const selected = selectAgents(options);
|
|
96
16
|
if (selected.length)
|
|
@@ -101,7 +21,7 @@ const chooseAgents = async (options) => {
|
|
|
101
21
|
if (!interactive())
|
|
102
22
|
throw new Error(`Unable to select an agent automatically. Use --agent <name> or --all. Detected: ${detected.join(", ") || "none"}`);
|
|
103
23
|
const { checkbox } = await prompts();
|
|
104
|
-
const choices =
|
|
24
|
+
const choices = resolvedAdapters();
|
|
105
25
|
const agents = await checkbox({
|
|
106
26
|
message: "Select one or more agents",
|
|
107
27
|
choices: choices.map((adapter) => ({
|
|
@@ -116,67 +36,9 @@ const preview = (operation, plan) => {
|
|
|
116
36
|
console.log(`◆ ${operation} preview — changes have NOT been applied`);
|
|
117
37
|
console.log(formatPlan(plan));
|
|
118
38
|
};
|
|
119
|
-
|
|
120
|
-
if (options.dryRun)
|
|
121
|
-
return false;
|
|
122
|
-
if (options.yes)
|
|
123
|
-
return true;
|
|
124
|
-
if (!interactive())
|
|
125
|
-
return false;
|
|
126
|
-
const { confirm } = await prompts();
|
|
127
|
-
return confirm({ message: `${operation} this plan?`, default: false });
|
|
128
|
-
};
|
|
129
|
-
/* --- MCP setup options ----------------------------------------------------- */
|
|
130
|
-
const mcpSetupSelections = async (args) => {
|
|
131
|
-
const selected = {
|
|
132
|
-
deployment: value(args, "--deployment"),
|
|
133
|
-
storage: value(args, "--storage"),
|
|
134
|
-
bind: value(args, "--bind"),
|
|
135
|
-
workspace: value(args, "--workspace"),
|
|
136
|
-
pollMs: Number(value(args, "--poll-ms") ?? 30_000),
|
|
137
|
-
tokenEnv: value(args, "--token-env") ?? "AIDLC_MCP_TOKEN",
|
|
138
|
-
providers: (value(args, "--providers") ?? "").split(",").filter(Boolean)
|
|
139
|
-
};
|
|
140
|
-
if ((!selected.deployment || !selected.storage || !selected.bind || !selected.workspace) && !interactive())
|
|
141
|
-
throw new Error("mcp setup outside a TTY requires --deployment, --storage, --bind and --workspace");
|
|
142
|
-
if (interactive()) {
|
|
143
|
-
const { input, select, checkbox } = await prompts();
|
|
144
|
-
selected.deployment ??= await select({ message: "State service deployment", choices: [{ name: "Docker on this machine", value: "docker" }, { name: "Remote service (configure endpoint later)", value: "remote" }] });
|
|
145
|
-
selected.storage ??= await select({ message: "Database", choices: [{ name: "SQLite (local Docker volume)", value: "sqlite" }, { name: "PostgreSQL (multi-host production)", value: "postgres" }] });
|
|
146
|
-
selected.bind ??= await select({ message: "Network binding", choices: [{ name: "localhost only", value: "localhost" }, { name: "network (requires token/TLS)", value: "network" }] });
|
|
147
|
-
selected.workspace ??= await input({ message: "Workspace ID", default: "default", required: true });
|
|
148
|
-
if (!selected.providers.length)
|
|
149
|
-
selected.providers = await checkbox({ message: "Project-management connectors to configure", choices: ["jira", "trello", "github-issues"].map((value) => ({ name: value, value })) });
|
|
150
|
-
}
|
|
151
|
-
if (!Number.isInteger(selected.pollMs) || selected.pollMs < 1_000 || selected.pollMs > 3_600_000)
|
|
152
|
-
throw new Error("--poll-ms must be an integer from 1000 to 3600000");
|
|
153
|
-
return selected;
|
|
154
|
-
};
|
|
155
|
-
const mcpSetupOptions = async (args) => {
|
|
156
|
-
const selected = await mcpSetupSelections(args);
|
|
157
|
-
return { root: rootArg(args), template: join(fileURLToPath(new URL("../services/aidlc-coordination", import.meta.url))), dryRun: flags(args).has("--dry-run"), deployment: selected.deployment, storage: selected.storage, bind: selected.bind, workspace: selected.workspace, pollMs: selected.pollMs, tokenEnv: selected.tokenEnv, providers: selected.providers, enable: flags(args).has("--enable") };
|
|
158
|
-
};
|
|
159
|
-
/* --- Command handlers ------------------------------------------------------ */
|
|
160
|
-
const runLoopCommand = (args) => {
|
|
161
|
-
const action = args[0];
|
|
162
|
-
if (!["start", "status", "resume"].includes(action))
|
|
163
|
-
throw new Error("Expected loop start, status, or resume");
|
|
164
|
-
const parsed = new Map();
|
|
165
|
-
for (let index = 1; index < args.length; index += 2) {
|
|
166
|
-
const key = args[index], entry = args[index + 1];
|
|
167
|
-
if (!["--task-id", "--root", "--mode"].includes(key) || !entry || entry.startsWith("--") || parsed.has(key))
|
|
168
|
-
throw new Error("Invalid or duplicate loop option");
|
|
169
|
-
parsed.set(key, entry);
|
|
170
|
-
}
|
|
171
|
-
const root = resolve(parsed.get("--root") ?? ".");
|
|
172
|
-
const script = join(root, ".agents", "aidlc", "scripts", "loop-entry.mjs");
|
|
173
|
-
const child = spawnSync(process.execPath, [script, action, parsed.get("--task-id") ?? "", root, parsed.get("--mode") ?? ""], { stdio: "inherit" });
|
|
174
|
-
if (child.error)
|
|
175
|
-
throw child.error;
|
|
176
|
-
if (child.status !== 0)
|
|
177
|
-
process.exitCode = child.status ?? 1;
|
|
178
|
-
};
|
|
39
|
+
/* --- Command handlers that consume the pinned prompts above ----------------- */
|
|
179
40
|
const runInit = async (args) => {
|
|
41
|
+
assertKnownOptions(args, INIT_FLAGS);
|
|
180
42
|
const options = { ...await chooseAgents(initOptions(args)), loop: await chooseLoop(args, false) };
|
|
181
43
|
const plan = planInit(options);
|
|
182
44
|
preview("INIT", plan);
|
|
@@ -192,8 +54,10 @@ const runInit = async (args) => {
|
|
|
192
54
|
applyPlan(options.root, plan);
|
|
193
55
|
console.log("Installed local AI-DLC workflow assets.");
|
|
194
56
|
}
|
|
57
|
+
recordInstallerCli(options.root);
|
|
195
58
|
};
|
|
196
59
|
const runUninstall = async (args) => {
|
|
60
|
+
assertKnownOptions(args, UNINSTALL_FLAGS);
|
|
197
61
|
const options = initOptions(args);
|
|
198
62
|
const plan = planUninstall(options.root);
|
|
199
63
|
preview("UNINSTALL", plan);
|
|
@@ -203,6 +67,7 @@ const runUninstall = async (args) => {
|
|
|
203
67
|
console.log("Removed eligible managed assets; project config and state were preserved.");
|
|
204
68
|
};
|
|
205
69
|
const runUpgrade = async (args) => {
|
|
70
|
+
assertKnownOptions(args, UPGRADE_FLAGS);
|
|
206
71
|
if (flags(args).has("--yes") || flags(args).has("--force"))
|
|
207
72
|
throw new Error("upgrade does not support --yes or --force; apply requires a human interactive TTY confirmation");
|
|
208
73
|
const root = rootArg(args);
|
|
@@ -220,49 +85,21 @@ const runUpgrade = async (args) => {
|
|
|
220
85
|
throw new Error("Upgrade confirmation did not match the target version");
|
|
221
86
|
const result = applyUpgrade(root, plan);
|
|
222
87
|
console.log(`Upgrade complete. Backup: ${result.backup}; changed: ${result.changed}`);
|
|
88
|
+
recordInstallerCli(root);
|
|
223
89
|
};
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
console.log(`◆ MCP SETUP preview — ${options.dryRun ? "no files will be written" : "review before applying"}`);
|
|
228
|
-
console.log(JSON.stringify(plan, null, 2));
|
|
229
|
-
if (options.dryRun)
|
|
230
|
-
return;
|
|
231
|
-
if (!await confirmGeneral({ ...initOptions(args), root: options.root }, "Apply MCP setup"))
|
|
232
|
-
return;
|
|
233
|
-
applyMcpSetup(options);
|
|
234
|
-
console.log(`MCP setup written to ${plan.target}. MCP remains ${options.enable ? "enabled" : "disabled"}; start Docker explicitly with docker compose --env-file .env -f ${join(plan.target, "compose.yaml")} up -d.`);
|
|
235
|
-
};
|
|
90
|
+
const runHelp = () => console.log(usage);
|
|
91
|
+
const runVersion = () => console.log(packageVersion());
|
|
92
|
+
const REGISTRY = { init: runInit, upgrade: runUpgrade, uninstall: runUninstall, status: runStatus, doctor: runDoctor, loop: runLoopCommand, ui: runUi, mcp: runMcp, profile: runProfile, version: runVersion, help: runHelp };
|
|
236
93
|
const main = async () => {
|
|
237
|
-
const
|
|
238
|
-
if (
|
|
94
|
+
const argv = process.argv.slice(2);
|
|
95
|
+
if (argv.includes("--version") || argv.includes("-v"))
|
|
96
|
+
return void console.log(packageVersion());
|
|
97
|
+
if (argv.includes("--help"))
|
|
239
98
|
return void console.log(usage);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const result = doctor(rootArg(args), flags(args).has("--strict"));
|
|
246
|
-
console.log(result);
|
|
247
|
-
if (result.startsWith("ERROR:"))
|
|
248
|
-
process.exitCode = 1;
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
if (command === "init")
|
|
252
|
-
return void await runInit(args);
|
|
253
|
-
if (command === "uninstall")
|
|
254
|
-
return void await runUninstall(args);
|
|
255
|
-
if (command === "upgrade")
|
|
256
|
-
return void await runUpgrade(args);
|
|
257
|
-
if (command === "mcp" && args[0] === "setup")
|
|
258
|
-
return void await runMcpSetup(args);
|
|
259
|
-
if (command === "profile" && args[0] === "validate") {
|
|
260
|
-
const root = rootArg(args.slice(1));
|
|
261
|
-
const config = loadProjectConfig(root);
|
|
262
|
-
const profiles = resolveProfiles(root, config.extends);
|
|
263
|
-
console.log(`OK: ${profiles.map((item) => item.id).join(" → ")}`);
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
throw new Error(`Unknown command: ${command}`);
|
|
99
|
+
const [command = "help", ...args] = argv;
|
|
100
|
+
const handler = Object.hasOwn(REGISTRY, command) ? REGISTRY[command] : undefined;
|
|
101
|
+
if (!handler)
|
|
102
|
+
throw new Error(`Unknown command: ${command}`);
|
|
103
|
+
return void await handler(args);
|
|
267
104
|
};
|
|
268
105
|
main().catch((error) => { console.error(`aidlc-kit: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; });
|
package/dist/src/gate.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { resolveProjectPathWithoutSymlinks } from "./project-path.js";
|
|
3
|
-
import { hasAreaVerification, hasReview, isLegacyG2Wait, nextAction, repairBounds, transitionDiagnostics, transitionTask } from "./state.js";
|
|
3
|
+
import { hasAreaVerification, hasReview, isLegacyG2Wait, loopPartitionStrict, nextAction, partitionDiagnostics, repairBounds, transitionDiagnostics, transitionTask } from "./state.js";
|
|
4
4
|
const safeArtifactTarget = (root, path) => resolveProjectPathWithoutSymlinks(root, path, "Unsafe artifact path", "Artifact path crosses a symlink");
|
|
5
5
|
const artifactContent = (root, path) => {
|
|
6
6
|
if (!path)
|
|
@@ -40,6 +40,7 @@ const reviewGateDiagnostics = (root, task) => {
|
|
|
40
40
|
if (content !== undefined)
|
|
41
41
|
for (const heading of missingHeadings(content, ["## 🧩 Solution per affected area", "## 📌 Spec traceability", "## 🔗 Cross-service contracts", "## ⚠️ Risks / edge cases"]))
|
|
42
42
|
diagnostics.push({ level: "ERROR", code: "DESIGN_HEADING", message: `Design is missing ${heading}` });
|
|
43
|
+
diagnostics.push(...partitionDiagnostics(task, { strict: loopPartitionStrict(root) }));
|
|
43
44
|
return diagnostics;
|
|
44
45
|
};
|
|
45
46
|
const codeReviewGateDiagnostics = (root, task) => {
|
|
@@ -82,7 +83,7 @@ export const checkGate = (root, state, taskId, gate) => {
|
|
|
82
83
|
diagnostics.push(...reviewGateDiagnostics(root, task));
|
|
83
84
|
if (gate === "G2_codereview")
|
|
84
85
|
diagnostics.push(...codeReviewGateDiagnostics(root, task));
|
|
85
|
-
if (!diagnostics.
|
|
86
|
+
if (!diagnostics.some((item) => item.level === "ERROR"))
|
|
86
87
|
diagnostics.push({ level: "INFO", code: "GATE_OK", message: `${gate} checks passed for ${taskId}` });
|
|
87
88
|
return diagnostics;
|
|
88
89
|
};
|
package/dist/src/installer.d.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import type { AgentId,
|
|
2
|
-
/**
|
|
3
|
-
export
|
|
4
|
-
export declare const managedContentHash: (spec: Pick<FileSpec, "owner" | "strategy">, content: string) => string | undefined;
|
|
5
|
-
export declare const readManifest: (root: string) => WorkflowManifest | undefined;
|
|
1
|
+
import type { AgentId, InitOptions, PlannedWrite } from "./model.js";
|
|
2
|
+
/** Manifest reading lives in the managed-planning core; this export path stays stable for existing importers. */
|
|
3
|
+
export { readManifest } from "./managed-planning.js";
|
|
6
4
|
export declare const detectedAgents: (root: string) => AgentId[];
|
|
7
5
|
export declare const selectAgents: (options: Pick<InitOptions, "root" | "agents" | "all">) => AgentId[];
|
|
8
|
-
/** Include an explicitly selected loop config in the same preview/transaction as setup. */
|
|
9
|
-
export declare const planLoopSelection: (plan: PlannedWrite[], selection?: LoopConfig) => void;
|
|
10
6
|
/** Plans an init transaction: managed workflow files, manifest, and project-owned files. */
|
|
11
7
|
export declare const planInit: (options: InitOptions) => PlannedWrite[];
|
|
12
8
|
/** Applies a planned init/uninstall transaction to disk. */
|
|
@@ -14,7 +10,18 @@ export declare const applyPlan: (root: string, plan: PlannedWrite[]) => void;
|
|
|
14
10
|
export declare const formatPlan: (plan: PlannedWrite[]) => string;
|
|
15
11
|
/** Plans an uninstall transaction that removes only unchanged managed assets. */
|
|
16
12
|
export declare const planUninstall: (root: string) => PlannedWrite[];
|
|
13
|
+
export declare const statusData: (root: string) => {
|
|
14
|
+
workflow: string;
|
|
15
|
+
installedVersion: string;
|
|
16
|
+
schema: string;
|
|
17
|
+
detectedAgents: string[];
|
|
18
|
+
};
|
|
17
19
|
/** Reports installed workflow version, schema, and detected agents. */
|
|
18
20
|
export declare const status: (root: string) => string;
|
|
19
21
|
/** Validates the installed workflow manifest and local config/state. */
|
|
20
22
|
export declare const doctor: (root: string, strict?: boolean) => string;
|
|
23
|
+
export declare const doctorData: (root: string, strict?: boolean) => {
|
|
24
|
+
level: "ok" | "warn" | "error";
|
|
25
|
+
message: string;
|
|
26
|
+
strict: boolean;
|
|
27
|
+
};
|