@aiwg/cli 2026.10.5 → 2026.10.6

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 (212) hide show
  1. package/agentic/code/addons/composition-engine/lib/runtime.mjs +1401 -0
  2. package/agentic/code/addons/composition-engine/lib/validator.mjs +513 -0
  3. package/agentic/code/addons/composition-engine/schemas/flow-graph.schema.json +372 -0
  4. package/agentic/code/providers/model-capabilities.v1.json +74 -50
  5. package/bin/aiwg.mjs +3 -1
  6. package/dist/src/artifacts/browser-export.js +1 -0
  7. package/dist/src/artifacts/citation-parser.js +8 -1
  8. package/dist/src/artifacts/cli.js +57 -6
  9. package/dist/src/artifacts/fortemi-core-query-adapter.js +2 -0
  10. package/dist/src/artifacts/fortemi-core-sync.js +26 -8
  11. package/dist/src/artifacts/graph-query.js +18 -8
  12. package/dist/src/artifacts/index-adapters.js +339 -0
  13. package/dist/src/artifacts/index-builder.js +143 -14
  14. package/dist/src/artifacts/index-files.js +15 -4
  15. package/dist/src/artifacts/index-reader.js +44 -0
  16. package/dist/src/artifacts/index-refresh.js +114 -55
  17. package/dist/src/artifacts/index-status.js +20 -5
  18. package/dist/src/artifacts/memory-maintenance.js +503 -0
  19. package/dist/src/artifacts/prebuilt-relations.js +3 -1
  20. package/dist/src/artifacts/query-engine.js +263 -108
  21. package/dist/src/artifacts/relations-builder.js +2 -2
  22. package/dist/src/artifacts/source-graph.js +2 -2
  23. package/dist/src/artifacts/types.js +9 -1
  24. package/dist/src/cli/handlers/decision.js +19 -1
  25. package/dist/src/cli/handlers/guided-setup.js +470 -0
  26. package/dist/src/cli/handlers/help.js +2 -2
  27. package/dist/src/cli/handlers/housekeeper.js +1110 -0
  28. package/dist/src/cli/handlers/index.js +4 -2
  29. package/dist/src/cli/handlers/init.js +41 -6
  30. package/dist/src/cli/handlers/local-executor.js +5 -3
  31. package/dist/src/cli/handlers/mc.js +509 -53
  32. package/dist/src/cli/handlers/models.js +32 -2
  33. package/dist/src/cli/handlers/ralph-launcher.js +76 -4
  34. package/dist/src/cli/handlers/rules.js +1 -1
  35. package/dist/src/cli/handlers/script-runner.js +73 -2
  36. package/dist/src/cli/handlers/serve.js +5 -3
  37. package/dist/src/cli/handlers/sessions.js +1 -0
  38. package/dist/src/cli/handlers/setup.js +428 -1
  39. package/dist/src/cli/handlers/skill-lint.js +1 -1
  40. package/dist/src/cli/handlers/subcommands.js +118 -8
  41. package/dist/src/cli/handlers/use.js +279 -93
  42. package/dist/src/cli/handlers/workspace.js +3 -1
  43. package/dist/src/cli/prompt-utils.js +8 -0
  44. package/dist/src/cli/router.js +16 -1
  45. package/dist/src/config/aiwg-config.js +42 -0
  46. package/dist/src/config/cli.js +7 -3
  47. package/dist/src/config/decision-config.js +14 -1
  48. package/dist/src/config/native-sandbox-warnings.js +25 -0
  49. package/dist/src/contributors/validation.js +6 -5
  50. package/dist/src/decision/admission.js +7 -3
  51. package/dist/src/decision/benchmark.js +469 -0
  52. package/dist/src/decision/ledger.js +22 -3
  53. package/dist/src/decision/pricing.js +147 -0
  54. package/dist/src/decision/qualification/gate-evidence.js +18 -15
  55. package/dist/src/decision/qualification/load-staged.js +539 -0
  56. package/dist/src/decision/qualification/load.js +109 -33
  57. package/dist/src/decision/qualification/runner.js +5 -2
  58. package/dist/src/decision/review/service.js +6 -4
  59. package/dist/src/decision/review/validate.js +23 -2
  60. package/dist/src/decision/savings.js +8 -3
  61. package/dist/src/discovery/index.js +492 -0
  62. package/dist/src/discovery/interview.js +233 -0
  63. package/dist/src/discovery/plan-apply.js +571 -0
  64. package/dist/src/discovery/plan-store.js +171 -0
  65. package/dist/src/discovery/plan-types.js +2 -0
  66. package/dist/src/discovery/plan-validation.js +139 -0
  67. package/dist/src/discovery/types.js +2 -0
  68. package/dist/src/extensions/commands/definitions.js +49 -9
  69. package/dist/src/extensions/manifest.js +71 -44
  70. package/dist/src/extensions/project-local-discovery.js +1 -1
  71. package/dist/src/extensions/project-quickref.js +18 -17
  72. package/dist/src/extensions/validation.js +32 -29
  73. package/dist/src/housekeeper/daemon-config.js +148 -0
  74. package/dist/src/housekeeper/ipc.js +84 -0
  75. package/dist/src/housekeeper/lifecycle.js +148 -0
  76. package/dist/src/housekeeper/platform.js +35 -0
  77. package/dist/src/housekeeper/status.js +70 -0
  78. package/dist/src/housekeeper/units.js +114 -0
  79. package/dist/src/jobs/flow.js +22 -21
  80. package/dist/src/lint/rule-activation.js +20 -5
  81. package/dist/src/lint/runner.js +1 -1
  82. package/dist/src/mcp/cli.mjs +5 -6
  83. package/dist/src/mcp/config-file.mjs +6 -2
  84. package/dist/src/mcp/config-layers.mjs +23 -7
  85. package/dist/src/mcp/profiles.js +18 -31
  86. package/dist/src/mcp/profiles.mjs +18 -32
  87. package/dist/src/mcp/registry.js +7 -27
  88. package/dist/src/mcp/registry.mjs +7 -28
  89. package/dist/src/mcp/server.mjs +34 -1
  90. package/dist/src/mcp/tools/agentic-sandbox.mjs +8 -7
  91. package/dist/src/mcp/tools/command-run.mjs +3 -2
  92. package/dist/src/mcp/tools/decision.mjs +49 -48
  93. package/dist/src/mcp/tools/discovery.mjs +46 -21
  94. package/dist/src/mcp/tools/orchestration.mjs +22 -22
  95. package/dist/src/mcp/tools/subsystems.mjs +9 -8
  96. package/dist/src/mcp/tools/worker-invoke.mjs +17 -4
  97. package/dist/src/mcp/tools/writer-profiles.mjs +1 -1
  98. package/dist/src/memory/audit.js +719 -0
  99. package/dist/src/memory/canonical-context.js +392 -13
  100. package/dist/src/memory/canonical-maintenance.js +95 -0
  101. package/dist/src/memory/cli-result.js +22 -0
  102. package/dist/src/memory/cli.js +176 -0
  103. package/dist/src/memory/context-pack.js +57 -6
  104. package/dist/src/memory/cost.js +512 -0
  105. package/dist/src/memory/firewall-classification.d.mts +7 -0
  106. package/dist/src/memory/firewall-classification.mjs +32 -0
  107. package/dist/src/memory/index.js +8 -0
  108. package/dist/src/memory/line-maintenance.js +68 -0
  109. package/dist/src/memory/maintenance-cli.js +286 -0
  110. package/dist/src/memory/maintenance-contract.js +136 -0
  111. package/dist/src/memory/maintenance-index.js +18 -0
  112. package/dist/src/memory/maintenance-owner.js +2 -0
  113. package/dist/src/memory/maintenance-record.js +138 -0
  114. package/dist/src/memory/maintenance.js +254 -0
  115. package/dist/src/memory/provider-memory-adapter.js +154 -0
  116. package/dist/src/memory/recommend-cli.js +83 -0
  117. package/dist/src/memory/recommend.js +269 -0
  118. package/dist/src/memory/scheduled.js +81 -0
  119. package/dist/src/memory/taxonomy.js +44 -0
  120. package/dist/src/mission-protocol/codecs.js +19 -9
  121. package/dist/src/models/config-loader.js +11 -1
  122. package/dist/src/models/model-capabilities.v1.json +74 -50
  123. package/dist/src/models/provider-policy.js +125 -62
  124. package/dist/src/models/resolver.js +45 -8
  125. package/dist/src/models/worker-installation.d.mts +7 -0
  126. package/dist/src/models/worker-installation.mjs +169 -37
  127. package/dist/src/models/wrapper-route.js +1 -1
  128. package/dist/src/output-modes/registry.js +8 -7
  129. package/dist/src/plugin/metadata-validator.js +1 -1
  130. package/dist/src/providers/deploy-version.d.mts +1 -0
  131. package/dist/src/providers/deploy-version.mjs +17 -0
  132. package/dist/src/providers/provider-definitions.js +19 -16
  133. package/dist/src/providers/skill-ownership.d.mts +11 -2
  134. package/dist/src/providers/skill-ownership.mjs +35 -17
  135. package/dist/src/rules/activation.d.mts +11 -2
  136. package/dist/src/rules/activation.mjs +82 -6
  137. package/dist/src/rules/inventory.js +1 -1
  138. package/dist/src/rules/rule-frontmatter.schema.json +2 -0
  139. package/dist/src/schema/zod-validation.d.mts +6 -0
  140. package/dist/src/schema/zod-validation.mjs +50 -0
  141. package/dist/src/serve/executor-registry.js +297 -20
  142. package/dist/src/serve/executor-token.d.mts +1 -0
  143. package/dist/src/serve/executor-token.mjs +8 -0
  144. package/dist/src/serve/shared-host-scheduler.js +1102 -31
  145. package/dist/src/serve/worker-invocation.js +114 -15
  146. package/dist/src/sessions/adapters/claude.js +19 -18
  147. package/dist/src/sessions/adapters/codex.js +10 -9
  148. package/dist/src/sessions/adapters/copilot.js +14 -13
  149. package/dist/src/sessions/adapters/cursor.js +19 -18
  150. package/dist/src/sessions/adapters/deepseek-harness.js +9 -8
  151. package/dist/src/sessions/adapters/factory.js +11 -10
  152. package/dist/src/sessions/adapters/generic.js +32 -23
  153. package/dist/src/sessions/adapters/grokbot.js +35 -35
  154. package/dist/src/sessions/adapters/hermes.js +20 -19
  155. package/dist/src/sessions/adapters/muse.js +50 -49
  156. package/dist/src/sessions/adapters/omp.js +5 -4
  157. package/dist/src/sessions/adapters/openclaw.js +30 -29
  158. package/dist/src/sessions/adapters/opencode.js +26 -26
  159. package/dist/src/sessions/adapters/openhuman.js +24 -23
  160. package/dist/src/sessions/adapters/pi.js +5 -4
  161. package/dist/src/sessions/adapters/windsurf.js +8 -8
  162. package/dist/src/sessions/analytics.js +10 -9
  163. package/dist/src/sessions/candidates.js +7 -6
  164. package/dist/src/sessions/contracts.js +63 -53
  165. package/dist/src/sessions/output-registration.js +11 -10
  166. package/dist/src/sessions/workspace-discovery.js +3 -4
  167. package/dist/src/smiths/context-pipeline/aiwg-md.js +18 -1
  168. package/dist/src/smiths/context-pipeline/claude-hook.js +42 -6
  169. package/dist/src/smiths/context-pipeline/parallelism-section.js +72 -5
  170. package/dist/src/smiths/context-pipeline/workspace-context.js +106 -10
  171. package/dist/src/update/checker.d.mts +4 -0
  172. package/dist/src/update/checker.mjs +14 -0
  173. package/dist/src/writing/exemplar-selection.js +6 -6
  174. package/dist/src/writing/voice-evaluation.js +24 -23
  175. package/dist/src/writing/writer-migration.js +14 -13
  176. package/dist/src/writing/writer-profile.js +19 -18
  177. package/dist/src/writing/writing-brief.js +18 -17
  178. package/dist/src/writing/writing-receipt.js +47 -46
  179. package/package.json +5 -2
  180. package/schemas/decision/DecisionReview.schema.json +78 -1
  181. package/schemas/mission-v1.schema.json +3 -0
  182. package/tools/agents/deploy-agents.mjs +67 -39
  183. package/tools/agents/providers/antigravity.mjs +6 -1
  184. package/tools/agents/providers/base.mjs +19 -13
  185. package/tools/agents/providers/claude.mjs +1 -1
  186. package/tools/agents/providers/codex.mjs +50 -56
  187. package/tools/agents/providers/copilot.mjs +8 -2
  188. package/tools/agents/providers/cursor.mjs +1 -1
  189. package/tools/agents/providers/deepseek-harness.mjs +1 -1
  190. package/tools/agents/providers/factory.mjs +7 -1
  191. package/tools/agents/providers/grok-build.mjs +18 -2
  192. package/tools/agents/providers/grokbot.mjs +1 -1
  193. package/tools/agents/providers/hermes.mjs +7 -13
  194. package/tools/agents/providers/muse-hooks.mjs +21 -14
  195. package/tools/agents/providers/muse.mjs +7 -2
  196. package/tools/agents/providers/omp.mjs +28 -4
  197. package/tools/agents/providers/opencode.mjs +14 -5
  198. package/tools/agents/providers/openhuman.mjs +1 -1
  199. package/tools/agents/providers/pi.mjs +1 -1
  200. package/tools/agents/providers/provider-prepare-coordinator.mjs +29 -9
  201. package/tools/agents/providers/rule-delivery.mjs +263 -71
  202. package/tools/agents/providers/windsurf.mjs +7 -0
  203. package/tools/cli/workspace-status.mjs +5 -0
  204. package/tools/commands/deploy-prompts-codex.mjs +11 -8
  205. package/tools/ralph-external/lib/codex-adapter.mjs +6 -2
  206. package/tools/ralph-external/lib/muse-adapter.mjs +12 -2
  207. package/tools/ralph-external/lib/worker-health.mjs +1 -1
  208. package/tools/ralph-external/lib/worker-isolation.mjs +65 -9
  209. package/tools/ralph-external/process-monitor.mjs +7 -4
  210. package/tools/ralph-external/session-launcher.mjs +280 -32
  211. package/tools/skills/deploy-skills-codex.mjs +11 -7
  212. package/vscode-extension/schemas/aiwg.config.v1.json +11 -1
@@ -0,0 +1,171 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { mkdir, open, readFile, rename, rm, stat } from 'node:fs/promises';
3
+ import { dirname, join } from 'node:path';
4
+ import { isDeepStrictEqual } from 'node:util';
5
+ import { resolveProjectAiwgDir, resolveProjectAiwgDirForWrite } from '../config/project-artifacts-runtime.mjs';
6
+ import { SETUP_PLAN_SCHEMA_VERSION } from './plan-types.js';
7
+ import { assertPlanRedacted, planIdSchema, validateSetupPlan } from './plan-validation.js';
8
+ function checkedId(id) {
9
+ assertPlanRedacted(id);
10
+ if (!planIdSchema.safeParse(id).success)
11
+ throw new Error('Setup plan ID must be 1-120 letters, digits, underscores, or hyphens, starting with a letter or digit.');
12
+ return id;
13
+ }
14
+ /** Explicit compatibility seam: pre-release v0 lacked receipts and updatedAt. Never migrate on disk during read. */
15
+ export function migrateSetupPlan(input) {
16
+ if (!input || typeof input !== 'object' || Array.isArray(input))
17
+ throw new Error('Setup plan must be a versioned JSON object.');
18
+ const value = input;
19
+ const version = value.schemaVersion;
20
+ if (typeof version !== 'number' || !Number.isSafeInteger(version) || version < 0) {
21
+ throw new Error('Setup plan schemaVersion must be a non-negative integer.');
22
+ }
23
+ if (version > SETUP_PLAN_SCHEMA_VERSION) {
24
+ throw new Error(`Setup plan schemaVersion ${version} is newer than supported version ${SETUP_PLAN_SCHEMA_VERSION}; upgrade AIWG before resuming.`);
25
+ }
26
+ switch (version) {
27
+ case 0:
28
+ return validateSetupPlan({ ...value, schemaVersion: SETUP_PLAN_SCHEMA_VERSION,
29
+ updatedAt: value.updatedAt === undefined ? value.createdAt : value.updatedAt,
30
+ receipts: value.receipts === undefined ? [] : value.receipts });
31
+ case SETUP_PLAN_SCHEMA_VERSION:
32
+ return validateSetupPlan(value);
33
+ default:
34
+ throw new Error('No migration exists for this setup plan schemaVersion.');
35
+ }
36
+ }
37
+ /** One resolved artifact root owns the entire plan, including receipts for other workspaces. */
38
+ export async function writeSetupPlan(projectDir, input, env) {
39
+ // Scan the serialized snapshot too: toJSON/getters cannot introduce an unscanned write.
40
+ assertPlanRedacted(input);
41
+ let snapshot;
42
+ try {
43
+ snapshot = JSON.parse(JSON.stringify(input));
44
+ }
45
+ catch {
46
+ throw new Error('Setup plan must contain serializable JSON values.');
47
+ }
48
+ const plan = validateSetupPlan(snapshot);
49
+ const id = checkedId(plan.id);
50
+ const root = resolveProjectAiwgDirForWrite(projectDir, env);
51
+ const destination = join(root, 'setup', 'plans', `${id}.json`);
52
+ const temporary = join(dirname(destination), `.${id}.${randomUUID()}.tmp`);
53
+ try {
54
+ await mkdir(dirname(destination), { recursive: true, mode: 0o700 });
55
+ const file = await open(temporary, 'wx', 0o600);
56
+ try {
57
+ await file.writeFile(JSON.stringify(plan, null, 2) + '\n', 'utf8');
58
+ await file.sync();
59
+ }
60
+ finally {
61
+ await file.close();
62
+ }
63
+ await rename(temporary, destination);
64
+ }
65
+ catch (error) {
66
+ // The error code names the cause (EACCES, ENOSPC, ENOENT) without echoing plan data.
67
+ const code = error?.code;
68
+ throw new Error(`Cannot write setup plan under the resolved artifact root${code ? ` (${code})` : ''}. Check that the corpus is attached and writable; no fallback was used.`);
69
+ }
70
+ finally {
71
+ await rm(temporary, { force: true }).catch(() => { });
72
+ }
73
+ return destination;
74
+ }
75
+ export async function readSetupPlan(projectDir, id, env) {
76
+ checkedId(id);
77
+ const root = resolveProjectAiwgDir(projectDir, env);
78
+ try {
79
+ if (!(await stat(root)).isDirectory())
80
+ throw new Error();
81
+ }
82
+ catch {
83
+ throw new Error('Resolved AIWG artifact root is unavailable. Reconnect or attach the corpus before reading setup plans; no fallback was used.');
84
+ }
85
+ let content;
86
+ try {
87
+ content = await readFile(join(root, 'setup', 'plans', `${id}.json`), 'utf8');
88
+ }
89
+ catch {
90
+ throw new Error('Cannot read setup plan from the resolved artifact root. Check the plan ID and file permissions; no fallback was used.');
91
+ }
92
+ let parsed;
93
+ try {
94
+ parsed = JSON.parse(content);
95
+ }
96
+ catch {
97
+ throw new Error('Setup plan is not valid JSON. Restore the plan from a valid copy.');
98
+ }
99
+ const plan = migrateSetupPlan(parsed);
100
+ if (plan.id !== id)
101
+ throw new Error('Setup plan ID does not match its filename.');
102
+ return plan;
103
+ }
104
+ /** Failed and skipped actions remain eligible. The apply slice decides retry/skip policy. */
105
+ export function remainingPlanActions(plan) {
106
+ return plan.actions.filter(action => !plan.receipts.some(receipt => receipt.workspace === action.workspace &&
107
+ Object.hasOwn(receipt.actions, action.id) && receipt.actions[action.id].status === 'applied'));
108
+ }
109
+ /** Presence counts, including false, null, and default/discovered answers. Never fill/overwrite answers here. */
110
+ export function unansweredPlanChoices(plan) {
111
+ return plan.unresolvedChoices.filter(choice => !Object.hasOwn(plan.answers, choice.questionId));
112
+ }
113
+ function observedPaths(project) {
114
+ return [project.root, project.packageManifest, ...project.packageRoots,
115
+ project.aiwg.directory ? join(project.root, '.aiwg') : null, project.aiwg.configFile,
116
+ project.aiwg.contextFile, ...project.providerFiles.map(file => file.path)].filter((path) => path !== null);
117
+ }
118
+ function factValue(inventory, fact) {
119
+ if (fact.kind === 'tool')
120
+ return inventory.tools.find(tool => tool.executable === fact.executable)?.[fact.field];
121
+ const root = fact.kind === 'project' ? fact.root : fact.workspace;
122
+ const project = inventory.projects.find(entry => entry.root === root);
123
+ if (fact.kind === 'project')
124
+ return project?.[fact.field];
125
+ if (project && observedPaths(project).includes(fact.path))
126
+ return true;
127
+ // Missing observations in a partial inventory cannot establish absence.
128
+ if (inventory.stats.truncated || inventory.diagnostics.some(d => ['inaccessible', 'symlink-skipped', 'outside-root'].includes(d.code)))
129
+ return undefined;
130
+ return false;
131
+ }
132
+ /** Successful config owners establish these paths as present for subsequent actions. */
133
+ function createdByAppliedConfig(plan, fact) {
134
+ if (fact.kind !== 'path' || ![join(fact.workspace, '.aiwg'), join(fact.workspace, '.aiwg', 'aiwg.config')].includes(fact.path))
135
+ return false;
136
+ return plan.actions.some(action => action.workspace === fact.workspace &&
137
+ ['write-project-config', 'configure-worker-dispatch', 'record-decline'].includes(action.kind) &&
138
+ plan.receipts.some(receipt => receipt.workspace === action.workspace && receipt.actions[action.id]?.status === 'applied'));
139
+ }
140
+ /** Pure comparison of local observations. Does not inspect paths, execute tools, or authorize apply. */
141
+ export function revalidateSetupPlan(plan, fresh) {
142
+ return plan.actions.flatMap(action => {
143
+ const changes = action.dependsOn.flatMap(fact => {
144
+ const before = createdByAppliedConfig(plan, fact) ? true : factValue(plan.inventory, fact);
145
+ const after = factValue(fresh, fact);
146
+ let reason;
147
+ if (before === undefined || after === undefined || before === 'unknown' || after === 'unknown')
148
+ reason = 'unobserved';
149
+ if (fact.kind === 'tool') {
150
+ const tool = fresh.tools.find(entry => entry.executable === fact.executable);
151
+ if (!tool || tool.installed === 'unknown')
152
+ reason = 'unobserved';
153
+ else if (tool.installed === 'no')
154
+ reason = 'tool-not-installed';
155
+ else if (fact.field === 'version' && (before === null || after === null))
156
+ reason = 'unobserved';
157
+ else if (fact.field === 'version' && !isDeepStrictEqual(before, after))
158
+ reason = 'version-changed';
159
+ }
160
+ if (fact.kind === 'project' && before !== undefined && after === undefined && !fresh.stats.truncated &&
161
+ !fresh.diagnostics.some(d => d.path === fact.root && d.code === 'inaccessible'))
162
+ reason = 'path-missing';
163
+ if (!reason && !isDeepStrictEqual(before, after)) {
164
+ reason = fact.kind === 'path' && after === false ? 'path-missing' : 'fact-changed';
165
+ }
166
+ return reason ? [{ fact, reason, before: before, after: after }] : [];
167
+ });
168
+ return changes.length ? [{ actionId: action.id, workspace: action.workspace, changes }] : [];
169
+ });
170
+ }
171
+ //# sourceMappingURL=plan-store.js.map
@@ -0,0 +1,2 @@
1
+ export const SETUP_PLAN_SCHEMA_VERSION = 1;
2
+ //# sourceMappingURL=plan-types.js.map
@@ -0,0 +1,139 @@
1
+ import { z } from 'zod';
2
+ import { dateTime, number } from '../schema/zod-validation.mjs';
3
+ import { redactText } from '../governance/redaction.js';
4
+ import { SETUP_PLAN_SCHEMA_VERSION } from './plan-types.js';
5
+ const text = z.string().min(1);
6
+ const timestamp = dateTime({ offset: true });
7
+ const observation = z.enum(['yes', 'no', 'unknown']);
8
+ export const planIdSchema = text.max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/);
9
+ const referenceSchema = z.strictObject({
10
+ kind: z.literal('credential-ref'), source: z.enum(['env', 'file', 'stdin-at-apply']), name: text,
11
+ });
12
+ const valueSchema = z.lazy(() => z.union([
13
+ z.string(), z.number().finite(), z.boolean(), z.null(), z.array(valueSchema), z.record(z.string(), valueSchema),
14
+ ]));
15
+ const projectSchema = z.strictObject({
16
+ root: text, sources: z.array(z.enum(['workspace', 'registry', 'selected'])),
17
+ vcs: z.enum(['git', 'worktree', 'none', 'unknown']), layout: z.enum(['project', 'package', 'monorepo', 'ambiguous']),
18
+ packageManifest: text.nullable(), workspacePatterns: z.array(z.string()), packageRoots: z.array(text),
19
+ aiwg: z.strictObject({ directory: z.boolean(), configFile: text.nullable(), contextFile: text.nullable() }),
20
+ providerFiles: z.array(z.strictObject({ provider: text, path: text, kind: z.enum(['config', 'context', 'artifacts']) })),
21
+ });
22
+ const toolSchema = z.strictObject({
23
+ executable: text, path: text.nullable(), installed: observation, configured: observation,
24
+ authenticated: observation, qualified: observation, version: text.nullable(), evidence: z.array(z.string()),
25
+ });
26
+ const inventorySchema = z.strictObject({
27
+ projects: z.array(projectSchema), tools: z.array(toolSchema),
28
+ diagnostics: z.array(z.strictObject({
29
+ code: z.enum(['depth-limit', 'entry-limit', 'time-limit', 'file-limit', 'inaccessible', 'invalid-metadata',
30
+ 'symlink-skipped', 'outside-root', 'ambiguous', 'excluded', 'home-scan-refused']),
31
+ path: z.string(), message: z.string(),
32
+ })),
33
+ limits: z.strictObject({ maxDepth: number().check(z.gte(0)).meta({ type: 'number', minimum: 0 }), maxEntries: number().check(z.gte(0)).meta({ type: 'number', minimum: 0 }),
34
+ timeBudgetMs: number().check(z.gte(0)).meta({ type: 'number', minimum: 0 }), maxFileBytes: number().check(z.gte(0)).meta({ type: 'number', minimum: 0 }) }),
35
+ stats: z.strictObject({ entriesInspected: number().check(z.gte(0)).meta({ type: 'number', minimum: 0 }), elapsedMs: number().check(z.gte(0)).meta({ type: 'number', minimum: 0 }), truncated: z.boolean() }),
36
+ });
37
+ const factSchema = z.discriminatedUnion('kind', [
38
+ z.strictObject({ kind: z.literal('project'), root: text, field: projectSchema.keyof() }),
39
+ z.strictObject({ kind: z.literal('tool'), executable: text, field: toolSchema.keyof() }),
40
+ z.strictObject({ kind: z.literal('path'), workspace: text, path: text }),
41
+ ]);
42
+ const planSchema = z.strictObject({
43
+ schemaVersion: z.literal(SETUP_PLAN_SCHEMA_VERSION), id: planIdSchema, inventoryId: text,
44
+ createdAt: timestamp, updatedAt: timestamp,
45
+ answers: z.record(z.string(), z.strictObject({ value: valueSchema,
46
+ source: z.enum(['explicit-flag', 'existing-setting', 'interview', 'default', 'discovered']), answeredAt: timestamp })),
47
+ recommendations: z.array(z.strictObject({ questionId: text, value: valueSchema, reason: text })),
48
+ unresolvedChoices: z.array(z.strictObject({ questionId: text,
49
+ options: z.array(z.strictObject({ label: text, value: valueSchema })).min(1),
50
+ default: valueSchema, whyItMatters: text, deferredAt: timestamp.optional() })),
51
+ actions: z.array(z.strictObject({ id: text, workspace: text, provider: text, scope: z.enum(['project', 'user']),
52
+ kind: text, dependsOn: z.array(factSchema) })),
53
+ receipts: z.array(z.strictObject({ workspace: text, actions: z.record(z.string(), z.strictObject({
54
+ status: z.enum(['applied', 'failed', 'skipped']), startedAt: timestamp, completedAt: timestamp,
55
+ message: z.string().optional(),
56
+ })) })),
57
+ inventory: inventorySchema,
58
+ });
59
+ const sensitiveKey = /(?:password|passwd|token|secret|api[_-]?key|credential|authorization|cookie|private[_-]?key|connection[_-]?string)/i;
60
+ const secretError = () => new Error('Setup plan contains secret-looking material; use a credential-ref (env, file, or stdin-at-apply).');
61
+ /** Scan the exact JSON snapshot, including keys and free-form evidence/messages. Never echo rejected values. */
62
+ export function assertPlanRedacted(input) {
63
+ let nodes = 0;
64
+ const scanText = (value) => {
65
+ const result = redactText(value, { organizationPatterns: [
66
+ { id: 'jwt', pattern: '\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]{8,}\\b' },
67
+ { id: 'extra-token', pattern: '\\b(?:aiwg_(?:at|rt)_|npm_|hf_|xai-|AIza)[A-Za-z0-9_-]{8,}\\b' },
68
+ ] });
69
+ if (result.sensitivity !== 'none')
70
+ throw secretError();
71
+ // Scan disjoint runs rather than retrying lookaheads at every word boundary.
72
+ for (const candidate of value.match(/[A-Za-z0-9_+=-]{32,}/g) ?? []) {
73
+ if (/[a-z]/.test(candidate) && /[A-Z]/.test(candidate) && /[0-9]/.test(candidate))
74
+ throw secretError();
75
+ }
76
+ };
77
+ const isReference = (value) => referenceSchema.safeParse(value).success;
78
+ const visit = (value, depth, answerMap = false) => {
79
+ if (++nodes > 100_000 || depth > 64)
80
+ throw new Error('Setup plan exceeds redaction structure limits.');
81
+ if (typeof value === 'string')
82
+ scanText(value);
83
+ if (!value || typeof value !== 'object')
84
+ return;
85
+ if (Array.isArray(value)) {
86
+ for (const item of value)
87
+ visit(item, depth + 1);
88
+ return;
89
+ }
90
+ const object = value;
91
+ if (object.kind === 'credential-ref' && !isReference(object))
92
+ throw secretError();
93
+ // Answers and recommendations can carry sensitive question IDs as data.
94
+ if (typeof object.questionId === 'string' && sensitiveKey.test(object.questionId)) {
95
+ const values = [object.value, object.default,
96
+ ...(Array.isArray(object.options) ? object.options.map(option => option?.value) : [])];
97
+ if (values.some(candidate => candidate !== undefined && candidate !== null && !isReference(candidate)))
98
+ throw secretError();
99
+ }
100
+ for (const [key, child] of Object.entries(object)) {
101
+ scanText(key);
102
+ if (sensitiveKey.test(key) && child !== null && child !== undefined && !isReference(child)) {
103
+ // A sensitive answer ID may wrap a reference with source/timestamp metadata.
104
+ const answer = child && typeof child === 'object' ? child : null;
105
+ if (!answerMap || !answer || !Object.hasOwn(answer, 'value') ||
106
+ (answer.value !== null && !isReference(answer.value)))
107
+ throw secretError();
108
+ }
109
+ visit(child, depth + 1, depth === 0 && key === 'answers');
110
+ }
111
+ };
112
+ visit(input, 0);
113
+ }
114
+ export function validateSetupPlan(input) {
115
+ assertPlanRedacted(input);
116
+ const parsed = planSchema.safeParse(input);
117
+ // Zod errors can include credential-bearing keys/values: keep diagnostics structural.
118
+ if (!parsed.success)
119
+ throw new Error('Invalid setup plan v1 shape; check required fields, timestamps, and action dependencies.');
120
+ const plan = parsed.data;
121
+ const ids = new Set(plan.actions.map(action => action.id));
122
+ if (ids.size !== plan.actions.length)
123
+ throw new Error('Setup plan action IDs must be unique.');
124
+ if (new Set(plan.receipts.map(receipt => receipt.workspace)).size !== plan.receipts.length) {
125
+ throw new Error('Setup plan workspace receipts must be unique.');
126
+ }
127
+ for (const receipt of plan.receipts)
128
+ for (const [id, result] of Object.entries(receipt.actions)) {
129
+ if (!plan.actions.some(action => action.id === id && action.workspace === receipt.workspace)) {
130
+ throw new Error('Setup plan receipt must refer to an action in the same workspace.');
131
+ }
132
+ if (Date.parse(result.completedAt) < Date.parse(result.startedAt))
133
+ throw new Error('Setup plan receipt timestamps are out of order.');
134
+ }
135
+ if (Date.parse(plan.updatedAt) < Date.parse(plan.createdAt))
136
+ throw new Error('Setup plan timestamps are out of order.');
137
+ return plan;
138
+ }
139
+ //# sourceMappingURL=plan-validation.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -687,6 +687,7 @@ export const initCommand = {
687
687
  triggerPhrases: ['init project', 'setup project config', 'configure providers'],
688
688
  commandHint: {
689
689
  template: 'utility',
690
+ argumentHint: '[--scope project|user] [--intent code|docs|ops|mixed] [--credential <provider>=env:NAME|file:PATH|stdin] [--jev enable|decline|defer]',
690
691
  allowedTools: ['Read', 'Write'],
691
692
  },
692
693
  },
@@ -718,7 +719,7 @@ export const setupCommand = {
718
719
  ],
719
720
  commandHint: {
720
721
  template: 'utility',
721
- argumentHint: 'project [--yes] [--dry-run] [--target <dir>]',
722
+ argumentHint: 'project [--yes] [--dry-run] [--review] [--apply] [--plan <id>] [--target <dir>] [--scope project|user] [--workspace <root>] [--monorepo root|package] [--package <root>] [--scan-roots <dir>] [--intent code|docs|ops|mixed] [--credential <provider>=env:NAME|file:PATH|stdin] [--jev enable|decline|defer]',
722
723
  allowedTools: ['Read', 'Write', 'Bash'],
723
724
  },
724
725
  },
@@ -1647,14 +1648,14 @@ export const discoverCommand = {
1647
1648
  },
1648
1649
  };
1649
1650
  // Show: companion to `discover`. Where `discover` ranks candidates,
1650
- // `show` fetches the full body of one specific artifact (#1218). This
1651
+ // `show` returns a metadata card with explicit section/body drill-ins. This
1651
1652
  // closes the loop so consumers never need to navigate AIWG's storage
1652
1653
  // paths themselves — the CLI is the access point.
1653
1654
  export const showCommand = {
1654
1655
  id: 'show',
1655
1656
  type: 'skill',
1656
1657
  name: 'Show',
1657
- description: 'Print the full text of a specific AIWG skill, agent, command, or rule by name',
1658
+ description: 'Show an AIWG artifact metadata card; use --section or --body for content',
1658
1659
  version: '1.0.0',
1659
1660
  capabilities: ['cli', 'discovery', 'read', 'capability', 'skills'],
1660
1661
  keywords: ['show', 'cat', 'read skill', 'print skill', 'get skill content', 'aiwg show'],
@@ -1678,7 +1679,7 @@ export const showCommand = {
1678
1679
  ],
1679
1680
  commandHint: {
1680
1681
  template: 'utility',
1681
- argumentHint: '<type> <name> [--json] [--first] [--resource-source local|web|auto] [--aiwg-version <version|range|digest|channel>] [--offline] # type: skill | agent | command | rule',
1682
+ argumentHint: '<type> <name> [--body] [--section <heading>] [--rules] [--resources] [--json] [--first] [--resource-source local|web|auto] [--aiwg-version <version|range|digest|channel>] [--offline] # type: skill | agent | command | rule',
1682
1683
  allowedTools: ['Read'],
1683
1684
  },
1684
1685
  },
@@ -3177,6 +3178,39 @@ export const daemonInitCommand = {
3177
3178
  },
3178
3179
  },
3179
3180
  };
3181
+ export const housekeeperCommand = {
3182
+ id: 'housekeeper',
3183
+ type: 'skill',
3184
+ name: 'Housekeeper',
3185
+ description: 'Deterministic maintenance daemon: start/stop/status/run-once, jobs, watch roots, autostart units',
3186
+ version: '1.0.0',
3187
+ capabilities: ['cli', 'daemon', 'maintenance', 'scheduler'],
3188
+ keywords: ['housekeeper', 'daemon', 'maintenance', 'schedule', 'run-once', 'autostart'],
3189
+ category: 'daemon',
3190
+ platforms: {
3191
+ claude: 'full',
3192
+ generic: 'full',
3193
+ },
3194
+ deployment: {
3195
+ pathTemplate: '.{platform}/commands/{id}.md',
3196
+ core: false,
3197
+ },
3198
+ metadata: {
3199
+ type: 'skill',
3200
+ triggerPhrases: ['housekeeper', 'housekeeper status', 'housekeeper start', 'maintenance daemon'],
3201
+ commandHint: {
3202
+ template: 'utility',
3203
+ argumentHint: '<start|stop|status|run-once|job|watch|install|uninstall> [options]',
3204
+ allowedTools: ['Bash', 'Read', 'Write'],
3205
+ executionSteps: [
3206
+ 'Parse subcommand and flags',
3207
+ 'Start/stop/query the housekeeper-profile daemon or edit its config',
3208
+ 'Run one job without a daemon (run-once) or write autostart units (install)',
3209
+ 'Display result',
3210
+ ],
3211
+ },
3212
+ },
3213
+ };
3180
3214
  // Config Commands
3181
3215
  export const configCommand = {
3182
3216
  id: 'config',
@@ -3341,7 +3375,7 @@ export const memoryCommand = {
3341
3375
  id: 'memory',
3342
3376
  type: 'skill',
3343
3377
  name: 'Memory',
3344
- description: 'Storage operations on the AIWG memory subsystem, plus user-level project memory registry commands under ~/.aiwg/projects',
3378
+ description: 'Read-only memory audit/cost/recommend/verify, reviewed plan/apply/restore, storage and project memory registry commands',
3345
3379
  version: '1.0.0',
3346
3380
  capabilities: ['cli', 'memory', 'semantic-memory', 'storage', 'pkm', 'project-memory', 'user-registry'],
3347
3381
  keywords: ['memory', 'semantic-memory', 'project-memory', 'registry', 'reflections', 'pages'],
@@ -3359,11 +3393,16 @@ export const memoryCommand = {
3359
3393
  triggerPhrases: ['where is memory', 'memory path', 'list memory', 'project memory', 'aiwg memory'],
3360
3394
  commandHint: {
3361
3395
  template: 'utility',
3362
- argumentHint: '<path|list|get|put|delete|append-log|project> [options]',
3396
+ argumentHint: '<audit|cost|recommend|plan|apply|verify|restore|path|list|get|put|delete|append-log|project> [options]',
3363
3397
  allowedTools: ['Bash', 'Read'],
3364
3398
  executionSteps: [
3365
3399
  'Parse subcommand and arguments',
3366
- 'Resolve storage adapter for memory subsystem',
3400
+ 'For audit, parse --scope global|project|provider, --provider <id>, --json, --cost strictly; default to workspace and perform a bounded read-only inventory',
3401
+ 'For cost, run the same read-only inventory through the resident-cost view (--demote, --startup-measurement, --usage only read; nothing is written)',
3402
+ 'For recommend and verify, run read-only reports; verify --plan checks existing owner receipts, retained history and published end states without refresh',
3403
+ 'For plan/apply/restore, show project targeting, diff, owner review and next-session limits; mutation requires exact reviewed owner plans',
3404
+ 'Use maintenance exit codes 0 success, 1 findings, 2 usage, 3 stale or failed',
3405
+ 'Resolve storage adapter for storage operations only',
3367
3406
  'Read/write/list/delete/append-log via the adapter or manage project-memory mappings',
3368
3407
  'Print result',
3369
3408
  ],
@@ -3755,7 +3794,7 @@ export const rlmCacheCommand = {
3755
3794
  * - SDLC Orchestration (1): sdlc-accelerate
3756
3795
  * - Index (1): index
3757
3796
  * - Reproducibility (4): execution-mode, snapshot, checkpoint, reproducibility-validate
3758
- * - Daemon (2): behavior, daemon-init
3797
+ * - Daemon (3): behavior, daemon-init, housekeeper
3759
3798
  * - Config (1): config
3760
3799
  * - Ops (1): ops
3761
3800
  * - Agentic Tools (5): chunk, fanout, rlm-prep, rlm-search, rlm-status
@@ -3886,9 +3925,10 @@ export const commandDefinitions = [
3886
3925
  snapshotCommand,
3887
3926
  checkpointCommand,
3888
3927
  reproducibilityValidateCommand,
3889
- // Daemon (2)
3928
+ // Daemon (3)
3890
3929
  behaviorCommand,
3891
3930
  daemonInitCommand,
3931
+ housekeeperCommand,
3892
3932
  // Config (1)
3893
3933
  configCommand,
3894
3934
  // Ops (1)