@felixdotgo/aidlc-kit 0.1.0 → 0.2.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.
Files changed (150) hide show
  1. package/DEVELOPMENT.md +14 -0
  2. package/README.md +14 -6
  3. package/dist/assets/.agents/aidlc/docker/Dockerfile.claude +7 -0
  4. package/dist/assets/.agents/aidlc/docker/Dockerfile.codex +9 -0
  5. package/dist/assets/.agents/aidlc/docker/Dockerfile.opencode +8 -0
  6. package/dist/assets/.agents/aidlc/orchestrator.md +1 -1
  7. package/dist/assets/.agents/aidlc/phase-clarify.md +1 -1
  8. package/dist/assets/.agents/aidlc/phase-plan.md +2 -2
  9. package/dist/assets/.agents/aidlc/schemas/config.schema.json +2 -1
  10. package/dist/assets/.agents/aidlc/schemas/manifest.schema.json +1 -1
  11. package/dist/assets/.agents/aidlc/scripts/lib/context-runtime.mjs +5 -0
  12. package/dist/assets/.agents/aidlc/scripts/lib/loop-authority.mjs +245 -0
  13. package/dist/assets/.agents/aidlc/scripts/lib/loop-commit-message.mjs +45 -0
  14. package/dist/assets/.agents/aidlc/scripts/lib/loop-daemon.mjs +232 -0
  15. package/dist/assets/.agents/aidlc/scripts/lib/loop-drivers.mjs +21 -4
  16. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-cli.mjs +86 -28
  17. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-remote.mjs +7 -0
  18. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-supervisor.mjs +22 -6
  19. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet.mjs +46 -15
  20. package/dist/assets/.agents/aidlc/scripts/lib/loop-git.mjs +22 -9
  21. package/dist/assets/.agents/aidlc/scripts/lib/loop-intake.mjs +23 -5
  22. package/dist/assets/.agents/aidlc/scripts/lib/loop-local-workers.mjs +43 -15
  23. package/dist/assets/.agents/aidlc/scripts/lib/loop-runtime.mjs +82 -6
  24. package/dist/assets/.agents/aidlc/scripts/lib/loop-stream.mjs +60 -0
  25. package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor-run-local.mjs +142 -5
  26. package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor.mjs +9 -1
  27. package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-docker.mjs +31 -5
  28. package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-image.mjs +64 -0
  29. package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-snapshot.mjs +3 -2
  30. package/dist/assets/.agents/aidlc/scripts/lib/store.mjs +59 -4
  31. package/dist/assets/.agents/aidlc/scripts/loop-entry.mjs +85 -73
  32. package/dist/assets/.agents/aidlc/scripts/loop-gate.mjs +19 -7
  33. package/dist/assets/.agents/aidlc/scripts/loop.mjs +2 -1
  34. package/dist/assets/.agents/aidlc/scripts/remote-state.mjs +2 -0
  35. package/dist/assets/.agents/aidlc/scripts/state.mjs +4 -0
  36. package/dist/assets/.agents/aidlc/templates/design.md +9 -0
  37. package/dist/assets/.agents/aidlc/templates/intent.md +4 -0
  38. package/dist/assets/.agents/aidlc/templates/workplan.md +1 -1
  39. package/dist/assets/.agents/skills/aidlc-plan/SKILL.md +1 -1
  40. package/dist/assets/ui/bulma.min.css +3 -0
  41. package/dist/assets/ui/dashboard.css +414 -0
  42. package/dist/services/aidlc-coordination/Dockerfile +11 -3
  43. package/dist/services/aidlc-coordination/compose.yaml +12 -0
  44. package/dist/services/aidlc-coordination/package-lock.json +3 -1
  45. package/dist/services/aidlc-coordination/package.json +9 -4
  46. package/dist/services/aidlc-coordination/src/lifecycle-core.mjs +59 -4
  47. package/dist/services/aidlc-coordination/src/repository.mjs +66 -0
  48. package/dist/services/aidlc-coordination/src/server.mjs +9 -3
  49. package/dist/services/aidlc-coordination/test/fleet.test.mjs +21 -0
  50. package/dist/services/aidlc-coordination/test/server-health-auth.test.mjs +67 -0
  51. package/dist/src/adapters.d.ts +0 -3
  52. package/dist/src/adapters.js +11 -6
  53. package/dist/src/cli/argv.d.ts +12 -0
  54. package/dist/src/cli/argv.js +62 -0
  55. package/dist/src/cli/commands.d.ts +8 -0
  56. package/dist/src/cli/commands.js +129 -0
  57. package/dist/src/cli/options.d.ts +25 -0
  58. package/dist/src/cli/options.js +32 -0
  59. package/dist/src/cli/prompt.d.ts +9 -0
  60. package/dist/src/cli/prompt.js +66 -0
  61. package/dist/src/cli.js +67 -217
  62. package/dist/src/context.js +2 -0
  63. package/dist/src/gate.d.ts +1 -0
  64. package/dist/src/gate.js +51 -37
  65. package/dist/src/installer.d.ts +19 -7
  66. package/dist/src/installer.js +111 -178
  67. package/dist/src/legacy.js +1 -0
  68. package/dist/src/managed-content.d.ts +7 -0
  69. package/dist/src/managed-content.js +15 -4
  70. package/dist/src/managed-planning.d.ts +65 -0
  71. package/dist/src/managed-planning.js +219 -0
  72. package/dist/src/mcp-setup.js +3 -1
  73. package/dist/src/model/config-contracts.d.ts +65 -0
  74. package/dist/src/model/config-contracts.js +1 -0
  75. package/dist/src/model/install-contracts.d.ts +29 -0
  76. package/dist/src/model/install-contracts.js +1 -0
  77. package/dist/src/model/lifecycle-enums.d.ts +13 -0
  78. package/dist/src/model/lifecycle-enums.js +1 -0
  79. package/dist/src/model/loop.d.ts +20 -0
  80. package/dist/src/model/loop.js +1 -0
  81. package/dist/src/model/manifest.d.ts +16 -0
  82. package/dist/src/model/manifest.js +1 -0
  83. package/dist/src/model/records.d.ts +138 -0
  84. package/dist/src/model/records.js +1 -0
  85. package/dist/src/model.d.ts +11 -264
  86. package/dist/src/model.js +1 -1
  87. package/dist/src/profiles.d.ts +8 -0
  88. package/dist/src/profiles.js +63 -8
  89. package/dist/src/project-migration.d.ts +1 -0
  90. package/dist/src/project-migration.js +7 -0
  91. package/dist/src/state/archive-record.d.ts +9 -0
  92. package/dist/src/state/archive-record.js +26 -0
  93. package/dist/src/state/commands.d.ts +18 -0
  94. package/dist/src/state/commands.js +27 -0
  95. package/dist/src/state/domain.d.ts +9 -0
  96. package/dist/src/state/domain.js +9 -0
  97. package/dist/src/state/guards.d.ts +7 -0
  98. package/dist/src/state/guards.js +17 -0
  99. package/dist/src/state/io.d.ts +10 -0
  100. package/dist/src/state/io.js +35 -0
  101. package/dist/src/state/items.d.ts +24 -0
  102. package/dist/src/state/items.js +147 -0
  103. package/dist/src/state/lessons.d.ts +7 -0
  104. package/dist/src/state/lessons.js +74 -0
  105. package/dist/src/state/lifecycle.d.ts +5 -0
  106. package/dist/src/state/lifecycle.js +78 -0
  107. package/dist/src/state/lock.d.ts +7 -0
  108. package/dist/src/state/lock.js +125 -0
  109. package/dist/src/state/memory.d.ts +8 -0
  110. package/dist/src/state/memory.js +100 -0
  111. package/dist/src/state/migrate.d.ts +17 -0
  112. package/dist/src/state/migrate.js +60 -0
  113. package/dist/src/state/partition.d.ts +15 -0
  114. package/dist/src/state/partition.js +90 -0
  115. package/dist/src/state/paths.d.ts +11 -0
  116. package/dist/src/state/paths.js +12 -0
  117. package/dist/src/state/render.d.ts +26 -0
  118. package/dist/src/state/render.js +32 -0
  119. package/dist/src/state/store.d.ts +4 -0
  120. package/dist/src/state/store.js +75 -0
  121. package/dist/src/state/transitions.d.ts +21 -0
  122. package/dist/src/state/transitions.js +95 -0
  123. package/dist/src/state/validate.d.ts +4 -0
  124. package/dist/src/state/validate.js +143 -0
  125. package/dist/src/state.d.ts +20 -117
  126. package/dist/src/state.js +20 -815
  127. package/dist/src/task-ui.d.ts +54 -0
  128. package/dist/src/task-ui.js +1570 -0
  129. package/dist/src/upgrade-board.d.ts +5 -0
  130. package/dist/src/upgrade-board.js +89 -0
  131. package/dist/src/upgrade.d.ts +3 -5
  132. package/dist/src/upgrade.js +174 -255
  133. package/dist/src/workflow.js +4 -4
  134. package/docs/README.md +6 -2
  135. package/docs/architecture.md +12 -8
  136. package/docs/command-reference.md +83 -19
  137. package/docs/configuration.md +30 -7
  138. package/docs/coordination-service.md +20 -5
  139. package/docs/design-decisions.md +83 -0
  140. package/docs/development.md +41 -2
  141. package/docs/loop-local-run.md +495 -0
  142. package/docs/loop-runbook.md +235 -0
  143. package/docs/operating-workflow.md +5 -2
  144. package/docs/testing-and-release.md +11 -7
  145. package/docs/troubleshooting.md +125 -0
  146. package/package.json +5 -2
  147. package/dist/src/ledger.d.ts +0 -22
  148. package/dist/src/ledger.js +0 -119
  149. package/dist/src/tracker.d.ts +0 -29
  150. package/dist/src/tracker.js +0 -41
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Managed-planning core shared by init and upgrade: the manifest-reader family,
3
+ * inventory-key handling, managed-content hash proofs, and the single
4
+ * create/skip/update/conflict ladder for managed files, driven by explicit
5
+ * per-flow policies so installation and upgrade keep their exact semantics.
6
+ */
7
+ import { existsSync, readFileSync } from "node:fs";
8
+ import { join, resolve } from "node:path";
9
+ import { legacyManagedMarker, managedBlock, mergeManagedBlock } from "./managed-content.js";
10
+ import { validateLoopConfig } from "./profiles.js";
11
+ import { contentHash } from "./workflow.js";
12
+ /** Constructs manifest inventory keys (`path#owner` for shared managed blocks). The definition should live here; it stays in workflow.ts pending a cross-owner move. */
13
+ export { manifestKey } from "./workflow.js";
14
+ /** The single read+parse of .agents/aidlc/manifest.json that every manifest question goes through. */
15
+ export const readManifestFile = (root) => {
16
+ const path = join(resolve(root), ".agents/aidlc/manifest.json");
17
+ if (!existsSync(path))
18
+ return { status: "missing" };
19
+ try {
20
+ return { status: "parsed", value: JSON.parse(readFileSync(path, "utf8")) };
21
+ }
22
+ catch {
23
+ return { status: "invalid" };
24
+ } /* intentional: an unreadable manifest is missing/invalid, never a crash */
25
+ };
26
+ /** Strict schema-v2 ownership manifest; malformed or non-conforming content reads as "not installed". */
27
+ export const readManifest = (root) => {
28
+ const read = readManifestFile(root);
29
+ if (read.status !== "parsed")
30
+ return undefined;
31
+ try {
32
+ const value = read.value;
33
+ const validFiles = value.files && typeof value.files === "object" && !Array.isArray(value.files) && Object.values(value.files).every((item) => item && typeof item.hash === "string" && typeof item.owner === "string" && ["replace", "managed-block"].includes(item.strategy));
34
+ return value.schemaVersion === 2 && typeof value.packageVersion === "string" && value.workflow === "AI-DLC" && value.source === "local-package-assets" && value.remoteUpdates === false && (value.managedBy === "aidlc-kit" || value.managedBy === "aidlc-workflow") && Array.isArray(value.adapters) && validFiles ? value : undefined;
35
+ }
36
+ catch {
37
+ return undefined;
38
+ } /* intentional: a malformed manifest is treated as "not installed" */
39
+ };
40
+ /** Whether the on-disk manifest is owned by this package (any schema version). */
41
+ export const hasOwnedManifest = (root) => {
42
+ const read = readManifestFile(root);
43
+ if (read.status !== "parsed")
44
+ return false;
45
+ try {
46
+ return read.value.managedBy === "aidlc-kit" || read.value.managedBy === "aidlc-workflow";
47
+ }
48
+ catch {
49
+ return false;
50
+ } /* intentional: a malformed/missing manifest is not owned */
51
+ };
52
+ /** Whether the on-disk manifest is a legacy aidlc-workflow v0.x install (schema 0 or 1). */
53
+ export const legacyManifest = (root) => {
54
+ const read = readManifestFile(root);
55
+ if (read.status !== "parsed")
56
+ return false;
57
+ try {
58
+ return read.value.managedBy === "aidlc-workflow" && (read.value.schemaVersion === 0 || read.value.schemaVersion === 1);
59
+ }
60
+ catch {
61
+ return false;
62
+ } /* intentional: a malformed/missing manifest is not a legacy v0.x install */
63
+ };
64
+ /* --- Inventory keys and hash proofs --------------------------------------------- */
65
+ /** Splits a manifest inventory key into its path and, when present, its `#owner` suffix. */
66
+ export const splitInventoryKey = (key) => {
67
+ const separator = key.lastIndexOf("#");
68
+ return separator > 0 ? { path: key.slice(0, separator), owner: key.slice(separator + 1) } : { path: key };
69
+ };
70
+ /** Managed prompt blocks share a path across owners, so inventory keys carry the owner. */
71
+ export const installedHashFor = (files, spec) => {
72
+ if (!files)
73
+ return undefined;
74
+ const keyed = files[`${spec.path}#${spec.owner}`];
75
+ if (keyed)
76
+ return keyed.hash;
77
+ const legacy = files[spec.path];
78
+ return legacy && (spec.strategy !== "managed-block" || legacy.owner === spec.owner) ? legacy.hash : undefined;
79
+ };
80
+ /** Hash of the managed slice of a file: the owned block for managed-block strategies, the whole file otherwise. */
81
+ export const managedContentHash = (spec, content) => {
82
+ const managed = managedBlock(spec, content);
83
+ return managed === undefined ? undefined : contentHash(managed);
84
+ };
85
+ /* --- Owned-file preservation ------------------------------------------------------ */
86
+ /** Plans one project/state-owned file: preserved verbatim when present, seeded from the package when absent. */
87
+ export const preserveOwnedFile = (target, spec) => existsSync(target)
88
+ ? { ...spec, content: readFileSync(target, "utf8"), action: "preserve", reason: `${spec.ownershipClass}-owned file` }
89
+ : { ...spec, action: "create", reason: `new ${spec.ownershipClass}-owned file` };
90
+ /* --- The one managed-file planning ladder -------------------------------------------- */
91
+ /**
92
+ * The single managed-file planning ladder shared by init and upgrade. The flows
93
+ * share the head rungs and then diverge; every difference is pinned below so
94
+ * each caller behaves exactly as it did before the extraction:
95
+ * - project/state specs: init plans preserve/create here; upgrade never passes
96
+ * them (its project files go through its own preserveProjectFiles pass).
97
+ * - fresh managed-block file: init merges into the empty file and says "new
98
+ * managed prompt"; upgrade copies spec.content verbatim and says "new managed
99
+ * file".
100
+ * - current content: init skips on whole-file equality ("already current");
101
+ * upgrade compares managed-content hashes ("managed content already current")
102
+ * and can still plan an update when only the surrounding layout changed.
103
+ * - manifest refresh and --force: init-only rungs (upgrade rewrites the
104
+ * manifest unconditionally through its own manifestSpec entry).
105
+ * - installed-hash proof: init compares the whole-file hash (only replace files
106
+ * reach this rung); upgrade compares the managed-content hash (block-scoped
107
+ * for shared blocks).
108
+ * - v0.2.1 baselines and the legacy single-marker conflict: upgrade-only rungs.
109
+ * - terminal conflict: init reports unprovable ownership; upgrade names the
110
+ * legacy-baseline or installed-hash mismatch.
111
+ */
112
+ const planManagedFile = (root, spec, policy) => {
113
+ const target = policy.resolvePath(root, spec.path);
114
+ if (policy.flow === "init" && (spec.ownershipClass === "project" || spec.ownershipClass === "state"))
115
+ return preserveOwnedFile(target, spec);
116
+ if (policy.flow === "init" && spec.strategy === "managed-block") {
117
+ const current = existsSync(target) ? readFileSync(target, "utf8") : "";
118
+ const next = mergeManagedBlock(spec, current);
119
+ return { ...spec, content: next, action: existsSync(target) ? (next === current ? "skip" : "update") : "create", reason: existsSync(target) ? "managed prompt block" : "new managed prompt" };
120
+ }
121
+ if (!existsSync(target))
122
+ return { ...spec, action: "create", reason: "new managed file" };
123
+ const current = readFileSync(target, "utf8");
124
+ if (policy.flow === "init") {
125
+ if (current === spec.content)
126
+ return { ...spec, action: "skip", reason: "already current" };
127
+ if (spec.path === ".agents/aidlc/manifest.json" && policy.installed)
128
+ return { ...spec, action: "update", reason: "refresh manifest inventory" };
129
+ const installedHash = installedHashFor(policy.installed?.files, spec);
130
+ if (installedHash && contentHash(current) === installedHash)
131
+ return { ...spec, action: "update", reason: "unchanged managed file" };
132
+ if (policy.force)
133
+ return { ...spec, action: "update", reason: "--force permits replacement of an unmanaged file" };
134
+ return { ...spec, action: "conflict", reason: "managed ownership cannot be proven; use upgrade or review --force" };
135
+ }
136
+ const next = spec.strategy === "managed-block" ? mergeManagedBlock(spec, current) : spec.content;
137
+ const currentHash = managedContentHash(spec, current);
138
+ const nextHash = contentHash(spec.strategy === "managed-block" ? spec.content.trimEnd() : spec.content);
139
+ if (currentHash === nextHash)
140
+ return { ...spec, content: next, action: next === current ? "skip" : "update", reason: "managed content already current" };
141
+ const installedHash = installedHashFor(policy.installed?.files, spec);
142
+ if (installedHash && currentHash === installedHash)
143
+ return { ...spec, content: next, action: "update", reason: "unchanged managed file" };
144
+ if (policy.legacy && policy.legacyBaseline?.(spec, currentHash))
145
+ return { ...spec, content: next, action: "update", reason: "recognized v0.2.1 baseline" };
146
+ if (spec.strategy === "managed-block" && current.includes(legacyManagedMarker(spec.owner)))
147
+ return { ...spec, content: next, action: "conflict", reason: "managed prompt block was modified" };
148
+ return { ...spec, content: next, action: "conflict", reason: policy.legacy ? "legacy core differs from known baseline" : "managed file differs from installed hash" };
149
+ };
150
+ /**
151
+ * Merges a later owner of a shared managed-block path into the already-planned
152
+ * entry. Upgrade proof-checks the later owner's installed block hash first so a
153
+ * user edit to a later adapter's block is reported instead of being silently
154
+ * overwritten; init has nothing to prove against and merges unconditionally,
155
+ * saying "new managed prompt" for a file that did not exist yet.
156
+ */
157
+ const mergeSharedBlockOwner = (root, previous, spec, policy) => {
158
+ if (!["create", "update", "skip"].includes(previous.action))
159
+ return;
160
+ const target = policy.resolvePath(root, spec.path);
161
+ const current = existsSync(target) ? readFileSync(target, "utf8") : "";
162
+ if (policy.flow === "upgrade") {
163
+ const installedBlockHash = installedHashFor(policy.installed?.files, spec);
164
+ const currentBlockHash = managedContentHash(spec, current);
165
+ if (installedBlockHash !== undefined && currentBlockHash !== undefined && installedBlockHash !== currentBlockHash) {
166
+ previous.action = "conflict";
167
+ previous.reason = "managed prompt block was modified";
168
+ return;
169
+ }
170
+ }
171
+ previous.content = mergeManagedBlock(spec, previous.content);
172
+ previous.action = existsSync(target) ? (previous.content === current ? "skip" : "update") : "create";
173
+ previous.reason = policy.flow === "init" && !existsSync(target) ? "new managed prompt" : "managed prompt block";
174
+ };
175
+ /**
176
+ * Plans managed files (and, for init, the manifest and project/state files) in
177
+ * order; later owners of a shared managed-block path merge into the earlier
178
+ * entry. Init finds the earlier entry by scanning the plan; upgrade tracks the
179
+ * first block entry per path so a conflicted first owner stays the single
180
+ * reportable entry for that path.
181
+ */
182
+ export const planManagedWrites = (root, files, policy) => {
183
+ const plan = [];
184
+ const firstBlocks = new Map();
185
+ for (const spec of files) {
186
+ const previous = spec.strategy === "managed-block"
187
+ ? policy.flow === "init" ? plan.find((item) => item.path === spec.path && ["create", "update", "skip"].includes(item.action)) : firstBlocks.get(spec.path)
188
+ : undefined;
189
+ if (!previous) {
190
+ const write = planManagedFile(root, spec, policy);
191
+ plan.push(write);
192
+ if (policy.flow === "upgrade" && spec.strategy === "managed-block")
193
+ firstBlocks.set(spec.path, write);
194
+ }
195
+ else
196
+ mergeSharedBlockOwner(root, previous, spec, policy);
197
+ }
198
+ return plan;
199
+ };
200
+ /** Include an explicitly selected loop config in the same preview/transaction as setup. */
201
+ export const planLoopSelection = (plan, selection) => {
202
+ if (selection === undefined)
203
+ return;
204
+ const loop = validateLoopConfig(selection);
205
+ const config = plan.find((item) => item.path === ".agents/config.json");
206
+ if (!config || !["create", "preserve", "skip", "migrate"].includes(config.action))
207
+ throw new Error("Cannot change loop configuration while the project config has another planned change");
208
+ const parsed = JSON.parse(config.content);
209
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
210
+ throw new Error("Invalid project config");
211
+ const current = parsed;
212
+ if (JSON.stringify(current.loop) === JSON.stringify(loop))
213
+ return;
214
+ const previousAction = config.action;
215
+ current.loop = loop;
216
+ config.content = `${JSON.stringify(current, null, 2)}\n`;
217
+ config.action = previousAction === "create" || previousAction === "migrate" ? previousAction : "update";
218
+ config.reason = "explicit loop mode selection";
219
+ };
@@ -1,5 +1,6 @@
1
1
  import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { join, resolve } from "node:path";
3
+ import { defaultConfig, validateProjectConfig } from "./profiles.js";
3
4
  export const planMcpSetup = (options) => {
4
5
  const target = join(resolve(options.root), ".agents/aidlc-coordination");
5
6
  const endpoint = options.deployment === "docker" ? "http://127.0.0.1:8787/mcp" : "https://replace-with-service.example/mcp";
@@ -24,8 +25,9 @@ export const applyMcpSetup = (options) => {
24
25
  ].join("\n");
25
26
  writeFileSync(join(plan.target, ".env.example"), `${env}\n`, "utf8");
26
27
  const configPath = join(resolve(options.root), ".agents/config.json");
27
- const current = existsSync(configPath) ? JSON.parse(readFileSync(configPath, "utf8")) : { schemaVersion: 3, extends: ["topology/single"], specs: { roots: [] }, commands: {}, rules: { include: [] }, risk: { default: "normal" }, context: { maxChars: 16000 }, agentState: {} };
28
+ const current = existsSync(configPath) ? JSON.parse(readFileSync(configPath, "utf8")) : { ...defaultConfig() };
28
29
  current.mcp = plan.config;
30
+ validateProjectConfig(current);
29
31
  writeFileSync(configPath, `${JSON.stringify(current, null, 2)}\n`, "utf8");
30
32
  return plan;
31
33
  };
@@ -0,0 +1,65 @@
1
+ import type { AgentId, RiskLevel, StateMutationMode } from "./lifecycle-enums.js";
2
+ import type { LoopConfig } from "./loop.js";
3
+ export interface CommandSpec {
4
+ command: string;
5
+ args: string[];
6
+ }
7
+ export interface Profile {
8
+ schemaVersion: 1;
9
+ id: string;
10
+ extends?: string[];
11
+ topology: string;
12
+ discovery?: {
13
+ roots?: string[];
14
+ workspaceMarkers?: string[];
15
+ };
16
+ specs?: {
17
+ roots?: string[];
18
+ };
19
+ commands?: Record<string, CommandSpec>;
20
+ rules?: {
21
+ include?: string[];
22
+ };
23
+ }
24
+ export interface ProjectConfig {
25
+ $schema?: string;
26
+ schemaVersion: 1 | 2 | 3;
27
+ extends: string[];
28
+ specs: {
29
+ roots: string[];
30
+ };
31
+ commands: Record<string, CommandSpec>;
32
+ rules: {
33
+ include: string[];
34
+ };
35
+ risk: {
36
+ default: RiskLevel;
37
+ };
38
+ context: {
39
+ maxChars: number;
40
+ };
41
+ agentState: Partial<Record<AgentId, StateMutationMode>>;
42
+ tracker?: TrackerConfig;
43
+ mcp: McpConfig;
44
+ loop?: LoopConfig;
45
+ }
46
+ export interface McpConfig {
47
+ enabled: boolean;
48
+ endpoint?: string;
49
+ workspace?: string;
50
+ tokenEnv?: string;
51
+ pollMs?: number;
52
+ providers?: Array<"jira" | "trello" | "github-issues">;
53
+ }
54
+ export interface TrackerConfig {
55
+ enabled: boolean;
56
+ provider: "backlog";
57
+ spaceUrl: string;
58
+ project: string;
59
+ tokenEnv: string;
60
+ workflow: "waterfall" | "scrum";
61
+ mapping: {
62
+ statuses?: Partial<Record<"clarify" | "plan" | "build" | "wrap" | "done", number>>;
63
+ gateFieldId?: number;
64
+ };
65
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,29 @@
1
+ import type { AgentId } from "./lifecycle-enums.js";
2
+ import type { LoopConfig } from "./loop.js";
3
+ export interface FileSpec {
4
+ path: string;
5
+ content: string;
6
+ owner: string;
7
+ strategy?: "replace" | "managed-block";
8
+ ownershipClass?: "managed" | "project" | "state";
9
+ }
10
+ export interface Adapter {
11
+ id: AgentId;
12
+ displayName: string;
13
+ detect(root: string): boolean;
14
+ files(): FileSpec[];
15
+ }
16
+ export interface PlannedWrite extends FileSpec {
17
+ action: "create" | "update" | "delete" | "skip" | "conflict" | "migrate" | "preserve";
18
+ reason: string;
19
+ contentEncoding?: "base64";
20
+ }
21
+ export interface InitOptions {
22
+ root: string;
23
+ agents: AgentId[];
24
+ all: boolean;
25
+ dryRun: boolean;
26
+ yes: boolean;
27
+ force: boolean;
28
+ loop?: LoopConfig;
29
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ export type AgentId = string;
2
+ export type StateMutationMode = "native" | "scripted";
3
+ export type Phase = "clarify" | "plan" | "build" | "wrap" | "done";
4
+ export type Gate = "none" | "G0_confirm" | "G1_review" | "G2_codereview";
5
+ export type TaskStatus = "active" | "blocked_on_user" | "paused" | "done" | "closed" | "superseded";
6
+ export type RiskLevel = "low" | "normal" | "high" | "regulated";
7
+ export type DecisionStatus = "unresolved" | "approved" | "changed" | "dropped";
8
+ export type HandoffKind = "repair_exhausted" | "review_exhausted" | "g2_failed" | "release_failed" | "structural_change" | "other";
9
+ export interface Diagnostic {
10
+ level: "ERROR" | "WARN" | "INFO";
11
+ code: string;
12
+ message: string;
13
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ export type LoopMode = "off" | "local" | "fleet";
2
+ export declare const LOOP_PROVIDERS: readonly ["codex", "claude", "opencode"];
3
+ export type LoopAgent = (typeof LOOP_PROVIDERS)[number];
4
+ export interface LoopConfig {
5
+ mode: LoopMode;
6
+ agents?: {
7
+ lead: LoopAgent;
8
+ workers: Record<string, LoopAgent>;
9
+ };
10
+ workerImage?: Partial<Record<LoopAgent, string>>;
11
+ /** Local daemon canonical-state poll interval (1000–300000 ms). */
12
+ pollMs?: number;
13
+ /** Per-run lead loop limits; bounds mirror `validateLimits` in loop-runtime.mjs. */
14
+ limits?: LoopLimits;
15
+ }
16
+ export interface LoopLimits {
17
+ maxTurns?: number;
18
+ turnTimeoutMs?: number;
19
+ maxStallTurns?: number;
20
+ }
@@ -0,0 +1 @@
1
+ export const LOOP_PROVIDERS = Object.freeze(["codex", "claude", "opencode"]);
@@ -0,0 +1,16 @@
1
+ import type { AgentId } from "./lifecycle-enums.js";
2
+ export interface ManifestInventoryItem {
3
+ hash: string;
4
+ owner: string;
5
+ strategy: "replace" | "managed-block";
6
+ }
7
+ export interface WorkflowManifest {
8
+ schemaVersion: 2;
9
+ packageVersion: string;
10
+ workflow: "AI-DLC";
11
+ source: "local-package-assets";
12
+ remoteUpdates: false;
13
+ managedBy: "aidlc-kit" | "aidlc-workflow";
14
+ adapters: AgentId[];
15
+ files: Record<string, ManifestInventoryItem>;
16
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,138 @@
1
+ import type { DecisionStatus, Gate, HandoffKind, Phase, RiskLevel, TaskStatus } from "./lifecycle-enums.js";
2
+ export interface TaskDecision {
3
+ id: string;
4
+ label: string;
5
+ status: DecisionStatus;
6
+ resolution?: string;
7
+ }
8
+ export interface Evidence {
9
+ kind: "approval" | "spec" | "test" | "lint" | "review" | "diagnostic";
10
+ gate?: Gate;
11
+ area?: string;
12
+ source: string;
13
+ result: "pass" | "fail" | "skip";
14
+ detail?: string;
15
+ recordedAt: string;
16
+ }
17
+ export interface LessonRecord {
18
+ id: string;
19
+ taskId: string;
20
+ areas: string[];
21
+ summary: string;
22
+ prevention: string;
23
+ example: string;
24
+ promotion: string;
25
+ source: string;
26
+ recordedAt: string;
27
+ }
28
+ export interface LessonDisposition {
29
+ status: "captured" | "none";
30
+ reason?: string;
31
+ source: string;
32
+ recordedAt: string;
33
+ }
34
+ export interface TaskState {
35
+ id: string;
36
+ featureId?: string;
37
+ title: string;
38
+ type: "feature" | "bug" | "refactor" | "infra";
39
+ phase: Phase;
40
+ gate: Gate;
41
+ status: TaskStatus;
42
+ language: "vi" | "en";
43
+ risk: RiskLevel;
44
+ areas: string[];
45
+ branch: string;
46
+ artifacts: {
47
+ intent?: string;
48
+ design?: string;
49
+ workplan?: string;
50
+ };
51
+ decisions: TaskDecision[];
52
+ tasks: Array<{
53
+ id: string;
54
+ label: string;
55
+ status: "todo" | "in_progress" | "done" | "deferred";
56
+ dependsOn?: string[];
57
+ ownedPaths?: string[];
58
+ }>;
59
+ evidence: Evidence[];
60
+ lessons?: LessonRecord[];
61
+ lessonDisposition?: LessonDisposition;
62
+ handoff?: {
63
+ kind: HandoffKind;
64
+ reason: string;
65
+ source: string;
66
+ recordedAt: string;
67
+ };
68
+ closure?: {
69
+ reason: string;
70
+ source: string;
71
+ recordedAt: string;
72
+ };
73
+ legacyG2Wait?: {
74
+ migratedAt: string;
75
+ source: string;
76
+ };
77
+ predecessorTaskId?: string;
78
+ successorTaskId?: string;
79
+ createdAt: string;
80
+ updatedAt: string;
81
+ }
82
+ export interface WorkflowState {
83
+ schemaVersion: 1 | 2 | 3 | 4;
84
+ tasks: Record<string, TaskState>;
85
+ archive?: Record<string, ArchivedTaskSummary>;
86
+ }
87
+ export interface ArchivedTaskSummary {
88
+ id: string;
89
+ title: string;
90
+ type: TaskState["type"];
91
+ phase: Phase;
92
+ gate: Gate;
93
+ status: "done" | "closed" | "superseded";
94
+ risk: RiskLevel;
95
+ areas: string[];
96
+ record: string;
97
+ digest: string;
98
+ lessonCount: number;
99
+ predecessorTaskId?: string;
100
+ successorTaskId?: string;
101
+ createdAt: string;
102
+ updatedAt: string;
103
+ }
104
+ export interface LessonIndexEntry {
105
+ id: string;
106
+ taskId: string;
107
+ areas: string[];
108
+ summary: string;
109
+ prevention: string;
110
+ source: string;
111
+ recordedAt: string;
112
+ }
113
+ export interface LessonIndex {
114
+ schemaVersion: 1;
115
+ sourceDigest: string;
116
+ lessons: LessonIndexEntry[];
117
+ }
118
+ export interface AgenticMemoryEntry {
119
+ id: string;
120
+ summary: string;
121
+ guidance: string;
122
+ areas: string[];
123
+ phases: Array<Exclude<Phase, "done"> | "*">;
124
+ priority: number;
125
+ sourceTaskId: string;
126
+ sourceLessonId: string;
127
+ approvedBy: string;
128
+ approvedAt: string;
129
+ }
130
+ export interface AgenticMemoryRegistry {
131
+ schemaVersion: 1;
132
+ entries: AgenticMemoryEntry[];
133
+ retired: Array<AgenticMemoryEntry & {
134
+ retiredBy: string;
135
+ retiredAt: string;
136
+ reason: string;
137
+ }>;
138
+ }
@@ -0,0 +1 @@
1
+ export {};