agentic-orchestrator 0.1.4 → 0.1.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 (108) hide show
  1. package/.claude/settings.local.json +6 -1
  2. package/README.md +81 -54
  3. package/agentic/orchestrator/defaults/policy.defaults.yaml +212 -0
  4. package/agentic/orchestrator/schemas/adapters.schema.json +17 -4
  5. package/agentic/orchestrator/schemas/agents.schema.json +58 -13
  6. package/agentic/orchestrator/schemas/gates.schema.json +88 -17
  7. package/agentic/orchestrator/schemas/index.schema.json +172 -37
  8. package/agentic/orchestrator/schemas/multi-project.schema.json +85 -17
  9. package/agentic/orchestrator/schemas/plan.schema.json +135 -30
  10. package/agentic/orchestrator/schemas/policy.schema.json +198 -69
  11. package/agentic/orchestrator/schemas/policy.user.schema.json +165 -0
  12. package/agentic/orchestrator/schemas/qa_test_index.schema.json +71 -14
  13. package/agentic/orchestrator/schemas/state.schema.json +196 -39
  14. package/apps/control-plane/scripts/validate-architecture-rules.mjs +5 -3
  15. package/apps/control-plane/scripts/validate-docker-mcp-contract.mjs +0 -3
  16. package/apps/control-plane/scripts/validate-mcp-contracts.ts +2 -6
  17. package/apps/control-plane/src/application/services/policy-loader-service.ts +115 -0
  18. package/apps/control-plane/src/cli/aop.ts +35 -1
  19. package/apps/control-plane/src/cli/cli-argument-parser.ts +4 -0
  20. package/apps/control-plane/src/cli/help-command-handler.ts +2 -1
  21. package/apps/control-plane/src/cli/init-command-handler.ts +136 -27
  22. package/apps/control-plane/src/cli/retry-command-handler.ts +3 -6
  23. package/apps/control-plane/src/cli/types.ts +1 -0
  24. package/apps/control-plane/src/core/git.ts +1 -3
  25. package/apps/control-plane/src/core/kernel.ts +3 -6
  26. package/apps/control-plane/src/core/schemas.ts +36 -1
  27. package/apps/control-plane/src/interfaces/cli/bootstrap.ts +1 -1
  28. package/apps/control-plane/src/mcp/tool-registry-loader.ts +37 -1
  29. package/apps/control-plane/src/supervisor/qa-wave-executor.ts +1 -1
  30. package/apps/control-plane/test/aop.spec.ts +37 -0
  31. package/apps/control-plane/test/batch-operations.spec.ts +5 -3
  32. package/apps/control-plane/test/bootstrap-attach.spec.ts +28 -18
  33. package/apps/control-plane/test/bootstrap-edge-cases.spec.ts +25 -15
  34. package/apps/control-plane/test/bootstrap.spec.ts +30 -22
  35. package/apps/control-plane/test/cli.unit.spec.ts +55 -10
  36. package/apps/control-plane/test/core-utils.spec.ts +12 -3
  37. package/apps/control-plane/test/feature-deletion-service.spec.ts +2 -1
  38. package/apps/control-plane/test/feature-lifecycle.spec.ts +1 -1
  39. package/apps/control-plane/test/helpers.ts +22 -2
  40. package/apps/control-plane/test/init-wizard.spec.ts +160 -7
  41. package/apps/control-plane/test/issue-tracker.spec.ts +3 -3
  42. package/apps/control-plane/test/kernel.spec.ts +62 -0
  43. package/apps/control-plane/test/lock-service.spec.ts +4 -4
  44. package/apps/control-plane/test/policy-loader-service.spec.ts +346 -0
  45. package/apps/control-plane/test/reactions.spec.ts +8 -6
  46. package/apps/control-plane/test/resume-command.spec.ts +31 -15
  47. package/apps/control-plane/test/supervisor.unit.spec.ts +2 -2
  48. package/apps/control-plane/test/tool-registry-loader.spec.ts +12 -0
  49. package/apps/control-plane/vitest.config.ts +1 -1
  50. package/dist/apps/control-plane/application/services/policy-loader-service.d.ts +24 -0
  51. package/dist/apps/control-plane/application/services/policy-loader-service.js +90 -0
  52. package/dist/apps/control-plane/application/services/policy-loader-service.js.map +1 -0
  53. package/dist/apps/control-plane/application/tools/tool-metadata.js +1 -0
  54. package/dist/apps/control-plane/application/tools/tool-metadata.js.map +1 -1
  55. package/dist/apps/control-plane/cli/aop.js +33 -1
  56. package/dist/apps/control-plane/cli/aop.js.map +1 -1
  57. package/dist/apps/control-plane/cli/cli-argument-parser.js +4 -0
  58. package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
  59. package/dist/apps/control-plane/cli/dashboard-command-handler.js +11 -5
  60. package/dist/apps/control-plane/cli/dashboard-command-handler.js.map +1 -1
  61. package/dist/apps/control-plane/cli/help-command-handler.js +5 -4
  62. package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -1
  63. package/dist/apps/control-plane/cli/init-command-handler.d.ts +1 -0
  64. package/dist/apps/control-plane/cli/init-command-handler.js +110 -26
  65. package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -1
  66. package/dist/apps/control-plane/cli/retry-command-handler.js +3 -6
  67. package/dist/apps/control-plane/cli/retry-command-handler.js.map +1 -1
  68. package/dist/apps/control-plane/cli/types.d.ts +1 -0
  69. package/dist/apps/control-plane/core/git.js +1 -3
  70. package/dist/apps/control-plane/core/git.js.map +1 -1
  71. package/dist/apps/control-plane/core/kernel.js +3 -5
  72. package/dist/apps/control-plane/core/kernel.js.map +1 -1
  73. package/dist/apps/control-plane/core/schemas.d.ts +2 -0
  74. package/dist/apps/control-plane/core/schemas.js +31 -1
  75. package/dist/apps/control-plane/core/schemas.js.map +1 -1
  76. package/dist/apps/control-plane/interfaces/cli/bootstrap.js +1 -1
  77. package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
  78. package/dist/apps/control-plane/mcp/tool-registry-loader.d.ts +2 -0
  79. package/dist/apps/control-plane/mcp/tool-registry-loader.js +31 -1
  80. package/dist/apps/control-plane/mcp/tool-registry-loader.js.map +1 -1
  81. package/dist/apps/control-plane/supervisor/build-wave-executor.js +1 -1
  82. package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -1
  83. package/dist/apps/control-plane/supervisor/qa-wave-executor.js +1 -1
  84. package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -1
  85. package/package.json +18 -17
  86. package/packages/web-dashboard/package.json +1 -1
  87. package/packages/web-dashboard/src/app/api/actions/route.ts +2 -2
  88. package/packages/web-dashboard/src/app/api/events/route.ts +1 -1
  89. package/packages/web-dashboard/src/app/api/features/[id]/checkout/route.ts +1 -1
  90. package/packages/web-dashboard/src/app/api/features/[id]/diff/route.ts +1 -1
  91. package/packages/web-dashboard/src/app/api/features/[id]/evidence/[artifact]/route.ts +1 -1
  92. package/packages/web-dashboard/src/app/api/features/[id]/review/route.ts +2 -2
  93. package/packages/web-dashboard/src/app/api/features/[id]/route.ts +1 -1
  94. package/packages/web-dashboard/src/app/api/projects/route.ts +2 -2
  95. package/packages/web-dashboard/src/app/api/status/route.ts +1 -1
  96. package/packages/web-dashboard/src/app/page.tsx +1 -1
  97. package/packages/web-dashboard/src/lib/aop-client.ts +1 -1
  98. package/packages/web-dashboard/src/lib/orchestrator-tools.ts +1 -1
  99. package/packages/web-dashboard/tsconfig.json +1 -0
  100. package/spec-files/completed/agentic_orchestrator_init_policy_ux_simplification_spec.md +481 -0
  101. package/spec-files/outstanding/agentic_orchestrator_artifact_database_publishing_spec.md +500 -0
  102. package/spec-files/outstanding/agentic_orchestrator_observability_integrity_diagnostics_spec.md +500 -195
  103. package/spec-files/outstanding/agentic_orchestrator_performance_improvements_spec.md +471 -162
  104. package/spec-files/outstanding/agentic_orchestrator_planning_review_quality_spec.md +532 -268
  105. package/spec-files/outstanding/agentic_orchestrator_productization_commercial_spec.md +645 -0
  106. package/spec-files/progress.md +99 -2
  107. package/tsconfig.base.json +4 -0
  108. /package/spec-files/{outstanding → completed}/agentic_orchestrator_validator_hardening_spec.md +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-orchestrator",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "private": false,
5
5
  "workspaces": [
6
6
  "packages/*"
@@ -19,6 +19,7 @@
19
19
  "validate:all": "npm run validate:mcp-contracts && npm run validate:docker-mcp && npm run validate:architecture",
20
20
  "lint": "eslint . --max-warnings 0",
21
21
  "lint:fix": "npm run lint -- --fix",
22
+ "publish:npm": "npm run typecheck && npm run validate:all && npm run test && npm run build && npm publish",
22
23
  "dashboard:dev": "npm run --workspace @aop/web-dashboard dev",
23
24
  "dashboard:build": "npm run --workspace @aop/web-dashboard build",
24
25
  "dashboard:start": "npm run --workspace @aop/web-dashboard start"
@@ -27,23 +28,23 @@
27
28
  "aop": "dist/apps/control-plane/cli/aop.js"
28
29
  },
29
30
  "devDependencies": {
30
- "@testing-library/react": "^14.3.1",
31
- "@eslint/js": "^9.37.0",
32
- "@types/node": "^22.13.10",
33
- "@vitest/coverage-v8": "^3.2.4",
34
- "eslint": "^9.37.0",
35
- "globals": "^16.4.0",
36
- "nx": "^20.5.0",
37
- "tsx": "^4.19.3",
38
- "typescript-eslint": "^8.46.1",
39
- "typescript": "^5.8.2",
40
- "msw": "^2.7.0",
41
- "vitest": "^3.2.4"
31
+ "@testing-library/react": "^16.3.2",
32
+ "@eslint/js": "^10.0.1",
33
+ "@types/node": "^25.3.3",
34
+ "@vitest/coverage-v8": "^4.0.18",
35
+ "eslint": "^10.0.2",
36
+ "globals": "^17.4.0",
37
+ "nx": "^22.5.3",
38
+ "tsx": "^4.21.0",
39
+ "typescript-eslint": "^8.56.1",
40
+ "typescript": "^5.9.3",
41
+ "msw": "^2.12.10",
42
+ "vitest": "^4.0.18"
42
43
  },
43
44
  "dependencies": {
44
- "ajv": "^8.17.1",
45
- "chalk": "^5.4.1",
46
- "minimatch": "^10.0.1",
47
- "yaml": "^2.6.1"
45
+ "ajv": "^8.18.0",
46
+ "chalk": "^5.6.2",
47
+ "minimatch": "^10.2.4",
48
+ "yaml": "^2.8.2"
48
49
  }
49
50
  }
@@ -7,7 +7,7 @@
7
7
  "dev": "next dev",
8
8
  "build": "next build",
9
9
  "start": "next start",
10
- "typecheck": "tsc --noEmit"
10
+ "typecheck": "tsc -p tsconfig.json --noEmit"
11
11
  },
12
12
  "dependencies": {
13
13
  "@monaco-editor/react": "^4.7.0",
@@ -1,5 +1,5 @@
1
- import { approveFeatureReview, denyFeatureReview, requestFeatureChanges } from '@/lib/orchestrator-tools';
2
- import { resolveProjectRoot } from '@/lib/aop-client';
1
+ import { approveFeatureReview, denyFeatureReview, requestFeatureChanges } from '@/lib/orchestrator-tools.js';
2
+ import { resolveProjectRoot } from '@/lib/aop-client.js';
3
3
 
4
4
  export const dynamic = 'force-dynamic';
5
5
 
@@ -1,4 +1,4 @@
1
- import { readDashboardStatus, resolveProjectRoot } from '@/lib/aop-client';
1
+ import { readDashboardStatus, resolveProjectRoot } from '@/lib/aop-client.js';
2
2
 
3
3
  export const dynamic = 'force-dynamic';
4
4
 
@@ -2,7 +2,7 @@ import { execFile } from 'node:child_process';
2
2
  import { access, mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
3
3
  import path from 'node:path';
4
4
  import { promisify } from 'node:util';
5
- import { readFeatureState, resolveProjectRoot } from '@/lib/aop-client';
5
+ import { readFeatureState, resolveProjectRoot } from '@/lib/aop-client.js';
6
6
 
7
7
  const execFileAsync = promisify(execFile);
8
8
 
@@ -1,4 +1,4 @@
1
- import { readFeatureDiff, resolveProjectRoot } from '@/lib/aop-client';
1
+ import { readFeatureDiff, resolveProjectRoot } from '@/lib/aop-client.js';
2
2
 
3
3
  export const dynamic = 'force-dynamic';
4
4
 
@@ -1,4 +1,4 @@
1
- import { readEvidenceArtifact, resolveProjectRoot } from '@/lib/aop-client';
1
+ import { readEvidenceArtifact, resolveProjectRoot } from '@/lib/aop-client.js';
2
2
 
3
3
  export const dynamic = 'force-dynamic';
4
4
 
@@ -2,8 +2,8 @@ import {
2
2
  approveFeatureReview,
3
3
  denyFeatureReview,
4
4
  requestFeatureChanges
5
- } from '@/lib/orchestrator-tools';
6
- import { resolveProjectRoot } from '@/lib/aop-client';
5
+ } from '@/lib/orchestrator-tools.js';
6
+ import { resolveProjectRoot } from '@/lib/aop-client.js';
7
7
 
8
8
  export const dynamic = 'force-dynamic';
9
9
 
@@ -1,4 +1,4 @@
1
- import { readFeatureDetail, resolveProjectRoot } from '@/lib/aop-client';
1
+ import { readFeatureDetail, resolveProjectRoot } from '@/lib/aop-client.js';
2
2
 
3
3
  export const dynamic = 'force-dynamic';
4
4
 
@@ -1,5 +1,5 @@
1
- import { getAopRoot } from '@/lib/aop-client';
2
- import { readMultiProjectConfig } from '@/lib/multi-project-config';
1
+ import { getAopRoot } from '@/lib/aop-client.js';
2
+ import { readMultiProjectConfig } from '@/lib/multi-project-config.js';
3
3
 
4
4
  export const dynamic = 'force-dynamic';
5
5
 
@@ -1,4 +1,4 @@
1
- import { readDashboardStatus, resolveProjectRoot } from '@/lib/aop-client';
1
+ import { readDashboardStatus, resolveProjectRoot } from '@/lib/aop-client.js';
2
2
 
3
3
  export const dynamic = 'force-dynamic';
4
4
 
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useCallback, useEffect, useMemo, useState } from 'react';
4
- import type { DashboardStatusPayload, FeatureDetail, FeatureSummary, SSEEvent } from '@/lib/types';
4
+ import type { DashboardStatusPayload, FeatureDetail, FeatureSummary, SSEEvent } from '@/lib/types.js';
5
5
 
6
6
  type ReviewAction = 'review.approve' | 'review.deny' | 'review.request_changes';
7
7
  type ProjectEntry = { name: string; path: string };
@@ -1,7 +1,7 @@
1
1
  import { readdir, readFile, stat } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import YAML from 'yaml';
4
- import { getProjectByName, readMultiProjectConfig } from './multi-project-config';
4
+ import { getProjectByName, readMultiProjectConfig } from './multi-project-config.js';
5
5
  import type {
6
6
  DashboardStatusPayload,
7
7
  EvidenceArtifact,
@@ -1,7 +1,7 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import path from 'node:path';
3
3
  import { pathToFileURL } from 'node:url';
4
- import { getAopRoot } from './aop-client';
4
+ import { getAopRoot } from './aop-client.js';
5
5
 
6
6
  const STATUS = {
7
7
  BLOCKED: 'blocked'
@@ -2,6 +2,7 @@
2
2
  "extends": "../../tsconfig.base.json",
3
3
  "compilerOptions": {
4
4
  "target": "ES2017",
5
+ "baseUrl": ".",
5
6
  "lib": [
6
7
  "dom",
7
8
  "dom.iterable",
@@ -0,0 +1,481 @@
1
+ # Feature Spec: Init UX + Policy Defaults Simplification (AOP)
2
+
3
+ > **Purpose of this document**: Define implementation-ready changes that make `aop init` simpler for default users while preserving full control for superusers and maintaining deterministic runtime behavior.
4
+
5
+ **Version:** 1.1
6
+ **Date:** 2026-03-03
7
+ **Status:** Draft (Expanded Implementation Detail)
8
+ **Roadmap Mapping:** M39
9
+
10
+ ---
11
+
12
+ ## 0. Standards and Dependencies
13
+
14
+ ### 0.1 Required Standards
15
+
16
+ All implementation MUST preserve:
17
+ - deterministic runtime behavior and MCP contract semantics
18
+ - existing CLI command names (`aop init`, `aop run`, etc.)
19
+ - schema validation as a hard gate for loaded policy
20
+ - full backward compatibility for existing full `policy.yaml` files
21
+ - test naming style (`GIVEN_..._WHEN_..._THEN_...`) and Vitest usage
22
+
23
+ ### 0.2 Upstream Inputs
24
+
25
+ Implementing agents MUST read:
26
+ - `apps/control-plane/src/cli/init-command-handler.ts`
27
+ - `apps/control-plane/src/cli/cli-argument-parser.ts`
28
+ - `apps/control-plane/src/cli/types.ts`
29
+ - `apps/control-plane/src/cli/help-command-handler.ts`
30
+ - `apps/control-plane/src/interfaces/cli/bootstrap.ts`
31
+ - `apps/control-plane/src/core/kernel.ts`
32
+ - `apps/control-plane/src/core/schemas.ts`
33
+ - `agentic/orchestrator/policy.yaml`
34
+ - `agentic/orchestrator/schemas/policy.schema.json`
35
+ - `apps/control-plane/test/init-wizard.spec.ts`
36
+ - `apps/control-plane/test/kernel.spec.ts`
37
+
38
+ ### 0.3 Current Baseline (Already Implemented in M39 Pre-Work)
39
+
40
+ As of 2026-03-03, these pieces are already done:
41
+ - `aop init` no longer copies schema files into target repos.
42
+ - schema loading can fall back to bundled AOP schemas when repo-local schemas are absent.
43
+ - `aop init` captures provider/model/SCM defaults.
44
+ - `activity-detector` in `adapters.yaml` is derived from provider.
45
+
46
+ This spec defines the next step: policy simplification and runtime composition.
47
+
48
+ ---
49
+
50
+ ## 1. Problem Analysis
51
+
52
+ ### 1.1 Primary UX Gap
53
+
54
+ `aop init` currently emits a verbose `policy.yaml` with many low-frequency controls (locks, RBAC internals, retry internals, path rules, hard constraints). Most teams do not need to edit these fields, but still must parse and own them.
55
+
56
+ ### 1.2 Resulting Risks
57
+
58
+ - Setup friction: first-time users face a large policy surface area.
59
+ - Misconfiguration risk: accidental edits to advanced controls.
60
+ - Upgrade friction: defaults cannot evolve cleanly when every repo stores a fully expanded copy.
61
+
62
+ ### 1.3 Desired UX Direction
63
+
64
+ Default users should configure only common controls; advanced users can opt into full explicit policy authoring.
65
+
66
+ ---
67
+
68
+ ## 2. Objectives
69
+
70
+ ### 2.1 Must-Have Outcomes
71
+
72
+ 1. Default `aop init` emits a lean, user-editable policy file.
73
+ 2. Runtime composes lean policy over bundled defaults into one canonical full snapshot.
74
+ 3. Superusers can still generate and maintain a full explicit policy.
75
+ 4. Existing full policies continue to work without migration.
76
+ 5. Validation errors remain clear and actionable.
77
+
78
+ ### 2.2 Non-Goals
79
+
80
+ - No redesign of locking, RBAC, or gate semantics.
81
+ - No changes to tool names or tool schemas.
82
+ - No removal of full policy support.
83
+ - No behavioral weakening of schema validation.
84
+
85
+ ---
86
+
87
+ ## 3. Architecture Decisions
88
+
89
+ ### ADP-1: Defaults-First Policy Composition
90
+
91
+ Runtime will always build a canonical full policy by:
92
+ 1. loading bundled `policy.defaults.yaml`,
93
+ 2. loading user `agentic/orchestrator/policy.yaml`,
94
+ 3. deep-merging user overrides over defaults,
95
+ 4. validating merged result against full `policy.schema.json`.
96
+
97
+ This removes the need for brittle full-vs-lean mode detection and keeps backward compatibility.
98
+
99
+ ### ADP-2: Explicit Advanced Init Mode
100
+
101
+ Add `aop init --advanced-policy` to generate the full explicit policy template (current behavior).
102
+
103
+ Default `aop init` generates lean policy.
104
+
105
+ ### ADP-3: Deterministic Merge Semantics
106
+
107
+ Policy merge must use deterministic rules:
108
+ - scalar values: override defaults
109
+ - objects: recursive merge
110
+ - arrays: replace when key exists in user policy
111
+ - absent keys: inherit defaults
112
+ - `null` values: rejected by schema unless explicitly allowed
113
+
114
+ ### ADP-4: Validation of User Shape + Canonical Shape
115
+
116
+ Two validations are required:
117
+ 1. optional user-shape validation (`policy.user.schema.json`) for clearer authoring errors
118
+ 2. mandatory canonical full validation (`policy.schema.json`) after merge
119
+
120
+ If user-shape validation is omitted for MVP, canonical full validation remains mandatory.
121
+
122
+ ---
123
+
124
+ ## 4. UX and Configuration Model
125
+
126
+ ### 4.1 Default `aop init` Output (Lean Policy)
127
+
128
+ Lean policy should include only common knobs:
129
+ - `version`
130
+ - `worktree.base_branch`
131
+ - `supervisor.max_parallel_gate_runs`
132
+ - `dashboard.enabled`
133
+ - `dashboard.port`
134
+ - `notifications`
135
+ - `merge_policy.require_user_approval`
136
+ - optional `recovery.orchestrator_session_reattach_timeout_ms`
137
+
138
+ Example shape:
139
+
140
+ ```yaml
141
+ version: 1
142
+ worktree:
143
+ base_branch: main
144
+ supervisor:
145
+ max_parallel_gate_runs: 3
146
+ dashboard:
147
+ enabled: true
148
+ port: 3000
149
+ merge_policy:
150
+ require_user_approval: true
151
+ notifications:
152
+ enabled: false
153
+ channels:
154
+ desktop:
155
+ enabled: false
156
+ slack:
157
+ enabled: false
158
+ webhook: ""
159
+ channel: "#aop-alerts"
160
+ webhook:
161
+ enabled: false
162
+ url: ""
163
+ ```
164
+
165
+ ### 4.2 Advanced `aop init --advanced-policy` Output
166
+
167
+ Generates current fully expanded `policy.yaml` template with all advanced fields.
168
+
169
+ ### 4.3 Init Prompt Surface
170
+
171
+ Interactive wizard continues to collect:
172
+ - default provider
173
+ - default model
174
+ - SCM provider
175
+ - base branch
176
+ - max parallel gates
177
+ - dashboard port
178
+ - notification channels + webhook values
179
+ - framework for gates
180
+
181
+ `adapters.yaml` activity-detector mapping:
182
+ - `claude` -> `claude-jsonl`
183
+ - `codex` -> `codex-rpc`
184
+ - everything else -> `process-heuristic`
185
+
186
+ ---
187
+
188
+ ## 5. Implementation Plan
189
+
190
+ ### M39-M1: CLI and Init Generation
191
+
192
+ ### INIT-T-001: Add Advanced Policy CLI Flag
193
+
194
+ **Files:**
195
+ - `apps/control-plane/src/cli/types.ts`
196
+ - `apps/control-plane/src/cli/cli-argument-parser.ts`
197
+ - `apps/control-plane/src/cli/help-command-handler.ts`
198
+ - `apps/control-plane/src/interfaces/cli/bootstrap.ts`
199
+
200
+ **Changes:**
201
+ - add `advanced_policy?: boolean` to `CliOptions`
202
+ - parse `--advanced-policy`
203
+ - pass through to `InitCommandHandler.execute({ auto, force, advanced_policy })`
204
+ - document flag in `aop help init`
205
+
206
+ ### INIT-T-002: Extend Init Options Contract
207
+
208
+ **File:** `apps/control-plane/src/cli/init-command-handler.ts`
209
+
210
+ **Changes:**
211
+ - add `advanced_policy?: boolean` to `InitOptions`
212
+ - branch policy template generation:
213
+ - `advanced_policy === true` -> full template
214
+ - else -> lean template
215
+
216
+ ### INIT-T-003: Split Policy Template Generation
217
+
218
+ **File:** `apps/control-plane/src/cli/init-command-handler.ts`
219
+
220
+ **Changes:**
221
+ - keep existing full generator as `generateFullPolicyYaml(...)`
222
+ - add `generateLeanPolicyYaml(...)`
223
+ - keep `gates.yaml`, `agents.yaml`, `adapters.yaml`, prompts generation unchanged
224
+
225
+ ---
226
+
227
+ ### M39-M2: Runtime Policy Composition
228
+
229
+ ### INIT-T-004: Add Bundled Defaults Artifact
230
+
231
+ **New file:**
232
+ - `agentic/orchestrator/defaults/policy.defaults.yaml`
233
+
234
+ **Requirements:**
235
+ - this file represents canonical defaults equivalent to current full template semantics
236
+ - should be versioned and reviewed like other bundled contracts
237
+
238
+ ### INIT-T-005: Implement Policy Composition Loader
239
+
240
+ **New file (recommended):**
241
+ - `apps/control-plane/src/application/services/policy-loader-service.ts`
242
+
243
+ **Interface (suggested):**
244
+
245
+ ```ts
246
+ interface LoadPolicyResult {
247
+ userPolicy: Record<string, unknown>;
248
+ mergedPolicy: Record<string, unknown>;
249
+ }
250
+
251
+ async function loadComposedPolicy(repoRoot: string, policyPath: string, schemaRegistry: SchemaRegistry): Promise<LoadPolicyResult>;
252
+ ```
253
+
254
+ **Behavior:**
255
+ - read defaults YAML (bundled path, not repo path)
256
+ - read user policy YAML (repo path)
257
+ - deep merge according to ADP-3 semantics
258
+ - validate merged policy against `policy.schema.json`
259
+ - return merged result
260
+
261
+ **Implementation details (normative):**
262
+
263
+ 1. Defaults path resolution:
264
+ - resolve from module location first (`import.meta.url` + upward walk), not from user repo.
265
+ - fail with explicit error if defaults artifact cannot be located.
266
+
267
+ 2. Merge algorithm:
268
+ - perform pure-function merge (do not mutate defaults or user objects).
269
+ - object + object -> recursive merge.
270
+ - array in user value -> replace defaults array wholesale.
271
+ - primitive in user value -> replace defaults primitive.
272
+ - `undefined` user fields -> ignored.
273
+
274
+ 3. Validation order:
275
+ - optional: validate user file against `policy.user.schema.json`.
276
+ - mandatory: validate merged output against `policy.schema.json`.
277
+
278
+ 4. Error contract:
279
+ - user-shape errors must point to user `policy.yaml`.
280
+ - canonical-shape errors must include merged key path and mention defaults composition.
281
+
282
+ **Reference merge pseudocode:**
283
+
284
+ ```ts
285
+ function mergePolicy(defaults: unknown, user: unknown): unknown {
286
+ if (Array.isArray(user)) return user.slice();
287
+ if (isObject(defaults) && isObject(user)) {
288
+ const out: Record<string, unknown> = { ...defaults };
289
+ for (const key of Object.keys(user)) {
290
+ const userVal = (user as Record<string, unknown>)[key];
291
+ if (userVal === undefined) continue;
292
+ out[key] = key in out ? mergePolicy(out[key], userVal) : clone(userVal);
293
+ }
294
+ return out;
295
+ }
296
+ return clone(user);
297
+ }
298
+ ```
299
+
300
+ ### INIT-T-006: Wire Kernel to Composed Policy
301
+
302
+ **File:** `apps/control-plane/src/core/kernel.ts`
303
+
304
+ **Current behavior:** direct `loadAndValidateYaml(... 'policy.schema.json', policyPath)`
305
+
306
+ **Target behavior:** load policy via composition loader from INIT-T-005, then assign merged policy to `this.policy`.
307
+
308
+ ### INIT-T-007: Optional User-Shape Schema
309
+
310
+ **New file (optional but recommended):**
311
+ - `agentic/orchestrator/schemas/policy.user.schema.json`
312
+
313
+ **Purpose:**
314
+ - validate lean authoring keys for better error messages before merge
315
+ - canonical enforcement still happens via full schema on merged result
316
+
317
+ **Schema policy:**
318
+ - `additionalProperties: false` at top level for lean mode.
319
+ - explicitly allow only intended user-editable sections.
320
+ - do not include internal sections (`locks`, `rbac`, `config_precedence`, etc.) in lean schema.
321
+
322
+ ---
323
+
324
+ ### M39-M3: Docs and Migration Clarity
325
+
326
+ ### INIT-T-008: Documentation Updates
327
+
328
+ **Files:**
329
+ - `README.md`
330
+ - `agentic/orchestrator/tools.md` (if references policy generation behavior)
331
+ - any init command docs/examples
332
+
333
+ **Documentation requirements:**
334
+ - clearly separate “common config” vs “advanced policy config”
335
+ - add `--advanced-policy` usage examples
336
+ - document merge semantics and where defaults live
337
+
338
+ ### INIT-T-009: Init Output Messaging
339
+
340
+ **File:** `apps/control-plane/src/cli/init-command-handler.ts`
341
+
342
+ **Changes:**
343
+ - `next_steps` output should state whether lean or advanced policy was generated
344
+ - mention `--advanced-policy` as escape hatch when lean mode is used
345
+
346
+ ---
347
+
348
+ ## 6. File-Level Delta Matrix
349
+
350
+ | File | Change Type | Scope |
351
+ |---|---|---|
352
+ | `apps/control-plane/src/cli/types.ts` | modify | add `advanced_policy` option |
353
+ | `apps/control-plane/src/cli/cli-argument-parser.ts` | modify | parse `--advanced-policy` |
354
+ | `apps/control-plane/src/cli/help-command-handler.ts` | modify | help text for new flag |
355
+ | `apps/control-plane/src/interfaces/cli/bootstrap.ts` | modify | pass flag into init handler |
356
+ | `apps/control-plane/src/cli/init-command-handler.ts` | modify | lean/full policy generation |
357
+ | `apps/control-plane/src/core/kernel.ts` | modify | use composed policy loader |
358
+ | `apps/control-plane/src/application/services/policy-loader-service.ts` | add | defaults + user merge + validate |
359
+ | `agentic/orchestrator/defaults/policy.defaults.yaml` | add | bundled canonical defaults |
360
+ | `agentic/orchestrator/schemas/policy.user.schema.json` | add (optional) | lean user policy shape |
361
+ | `README.md` | modify | init UX and policy authoring docs |
362
+
363
+ ---
364
+
365
+ ## 7. Acceptance Criteria
366
+
367
+ ### 7.1 Init UX
368
+
369
+ - [ ] `aop init` writes lean `policy.yaml` by default.
370
+ - [ ] `aop init --advanced-policy` writes full explicit `policy.yaml`.
371
+ - [ ] `aop init --auto` works in both lean and advanced modes.
372
+ - [ ] `aop help init` documents `--advanced-policy`.
373
+
374
+ ### 7.2 Runtime Composition
375
+
376
+ - [ ] Kernel boots correctly with lean policy.
377
+ - [ ] Kernel boots correctly with existing full legacy policy.
378
+ - [ ] Merged policy always passes full schema validation.
379
+ - [ ] Policy merge behavior is deterministic and documented.
380
+
381
+ ### 7.3 Compatibility
382
+
383
+ - [ ] Existing repositories with full policy require no changes.
384
+ - [ ] Existing tests for non-init commands remain green.
385
+ - [ ] No tool contract or transport behavior regressions.
386
+
387
+ ---
388
+
389
+ ## 8. Test Plan
390
+
391
+ ### 8.1 Init Tests
392
+
393
+ **File:** `apps/control-plane/test/init-wizard.spec.ts`
394
+
395
+ Add:
396
+ - `GIVEN_default_init_WHEN_policy_generated_THEN_policy_is_lean_shape`
397
+ - `GIVEN_advanced_policy_flag_WHEN_policy_generated_THEN_policy_is_full_shape`
398
+ - `GIVEN_advanced_policy_flag_WHEN_help_rendered_THEN_flag_is_documented`
399
+
400
+ ### 8.2 Policy Composition Tests
401
+
402
+ **New file:** `apps/control-plane/test/policy-loader-service.spec.ts`
403
+
404
+ Add:
405
+ - `GIVEN_defaults_and_lean_user_policy_WHEN_composed_THEN_merged_policy_is_valid`
406
+ - `GIVEN_full_user_policy_WHEN_composed_THEN_user_values_override_defaults`
407
+ - `GIVEN_array_override_WHEN_composed_THEN_array_replaces_default_array`
408
+ - `GIVEN_invalid_user_policy_WHEN_loaded_THEN_validation_error_is_actionable`
409
+
410
+ ### 8.3 Kernel Integration Tests
411
+
412
+ **File:** `apps/control-plane/test/kernel.spec.ts`
413
+
414
+ Add:
415
+ - `GIVEN_lean_policy_repo_WHEN_kernel_loads_THEN_runtime_boots_successfully`
416
+ - `GIVEN_full_policy_repo_WHEN_kernel_loads_THEN_runtime_boots_successfully`
417
+
418
+ ### 8.4 Regression Test Runs
419
+
420
+ Required run list:
421
+ - `npm run lint`
422
+ - `npm run typecheck`
423
+ - `npm test`
424
+ - `npm run validate:mcp-contracts`
425
+ - `npm run validate:architecture`
426
+
427
+ ### 8.5 Determinism and Edge Cases (Required)
428
+
429
+ Add explicit tests for:
430
+ - merge determinism with object key order differences (same result hash)
431
+ - array replacement semantics for `required_modes` and `protected_areas`
432
+ - missing defaults artifact error path (clear actionable message)
433
+ - behavior when user policy is empty `{}` (defaults-only canonical policy)
434
+ - behavior when user policy file is absent (hard failure or auto-init guidance; choose one and test)
435
+
436
+ ---
437
+
438
+ ## 9. Rollout Strategy
439
+
440
+ ### Phase A (Safe Introduction)
441
+
442
+ Ship runtime composition first while keeping full-policy init generation as default.
443
+
444
+ ### Phase B (UX Flip)
445
+
446
+ Flip `aop init` default to lean policy once composition is stable and tested.
447
+
448
+ ### Phase C (Docs and Adoption)
449
+
450
+ Document lean default and advanced mode; include migration note for teams that prefer explicit full policy.
451
+
452
+ ---
453
+
454
+ ## 10. Risks and Mitigations
455
+
456
+ - Risk: ambiguity around merge semantics.
457
+ - Mitigation: explicit deterministic rules + unit tests for scalars/objects/arrays.
458
+ - Risk: defaults drift from real runtime assumptions.
459
+ - Mitigation: keep defaults artifact under version control and validate merged output with full schema.
460
+ - Risk: advanced users lose discoverability of lower-level knobs.
461
+ - Mitigation: `--advanced-policy` and dedicated docs section with full template.
462
+ - Risk: error messages become less actionable due to merge layer.
463
+ - Mitigation: preserve source-path context (`policy.yaml` field path) in validation errors.
464
+
465
+ ---
466
+
467
+ ## 11. Definition of Done
468
+
469
+ This spec is complete when:
470
+ 1. INIT-T-001 through INIT-T-009 are implemented.
471
+ 2. acceptance criteria in Section 7 are all checked.
472
+ 3. test plan in Section 8 passes in CI.
473
+ 4. `spec-files/progress.md` is updated with delivered tasks and residual follow-ups.
474
+
475
+ ---
476
+
477
+ ## 12. Open Questions
478
+
479
+ 1. Should missing `agentic/orchestrator/policy.yaml` trigger hard failure or auto-bootstrap from defaults?
480
+ 2. Do we want `aop init --advanced-policy` as a one-time generator only, or also a conversion command from lean to full?
481
+ 3. Should lean mode permit `cleanup.*` (frequently edited in some teams) or keep it advanced-only?