chati-dev 4.5.16 → 4.5.27

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 (122) hide show
  1. package/README.md +8 -3
  2. package/bin/chati.js +124 -66
  3. package/framework/agents/build/dev.md +5 -5
  4. package/framework/agents/deploy/devops.md +7 -7
  5. package/framework/agents/discover/brief.md +4 -4
  6. package/framework/agents/discover/brownfield-wu.md +3 -3
  7. package/framework/agents/discover/greenfield-wu.md +3 -3
  8. package/framework/agents/plan/architect.md +2 -2
  9. package/framework/agents/plan/detail.md +4 -4
  10. package/framework/agents/plan/phases.md +2 -2
  11. package/framework/agents/plan/tasks.md +2 -2
  12. package/framework/agents/plan/ux.md +2 -2
  13. package/framework/agents/quality/qa-implementation.md +11 -10
  14. package/framework/agents/quality/qa-planning.md +3 -3
  15. package/framework/agents/quality/qa-visual.md +1 -1
  16. package/framework/config.yaml +3 -3
  17. package/framework/constitution.md +18 -18
  18. package/framework/context/protocols.md +1 -1
  19. package/framework/context/quality.md +1 -1
  20. package/framework/context/root.md +4 -4
  21. package/framework/data/entity-registry.yaml +1 -1
  22. package/framework/domains/agents/orchestrator.yaml +2 -2
  23. package/framework/domains/constitution.yaml +1 -1
  24. package/framework/hooks/advance-trigger.js +4 -6
  25. package/framework/hooks/git-push-authority.js +45 -37
  26. package/framework/hooks/mode-governance.js +149 -40
  27. package/framework/hooks/model-governance.js +13 -20
  28. package/framework/hooks/prism-engine.js +74 -92
  29. package/framework/hooks/reasoning-escalator.js +23 -40
  30. package/framework/hooks/session-digest.js +12 -13
  31. package/framework/hooks/session-reader.js +224 -0
  32. package/framework/hooks/session-writer.js +195 -0
  33. package/framework/hooks/team-quality-gate.js +34 -24
  34. package/framework/i18n/en.yaml +2 -2
  35. package/framework/i18n/es.yaml +2 -2
  36. package/framework/i18n/fr.yaml +2 -2
  37. package/framework/i18n/pt.yaml +2 -2
  38. package/framework/intelligence/context-engine.md +4 -4
  39. package/framework/intelligence/memory-layer.md +1 -1
  40. package/framework/manifest.json +129 -119
  41. package/framework/manifest.sig +1 -1
  42. package/framework/orchestrator/chati-router.js +252 -25
  43. package/framework/orchestrator/chati.md +238 -70
  44. package/framework/schemas/session.schema.json +1 -1
  45. package/framework/tasks/orchestrator-deviation.md +1 -1
  46. package/framework/tasks/orchestrator-escalate.md +1 -1
  47. package/framework/tasks/orchestrator-handoff.md +6 -6
  48. package/framework/tasks/orchestrator-health.md +5 -9
  49. package/framework/tasks/orchestrator-mode-switch.md +3 -7
  50. package/framework/tasks/orchestrator-resume.md +10 -14
  51. package/framework/tasks/orchestrator-route.md +3 -3
  52. package/framework/tasks/orchestrator-spawn-terminal.md +1 -1
  53. package/framework/tasks/orchestrator-status.md +9 -9
  54. package/framework/tasks/orchestrator-suggest-mode.md +1 -1
  55. package/framework/tasks/qa-impl-consolidate.md +2 -2
  56. package/framework/tasks/qa-impl-performance-test.md +4 -4
  57. package/framework/tasks/qa-impl-regression-check.md +4 -4
  58. package/framework/tasks/qa-impl-sast-scan.md +1 -1
  59. package/framework/tasks/qa-impl-test-execute.md +1 -1
  60. package/framework/tasks/qa-impl-verdict.md +2 -2
  61. package/framework/tasks/qa-planning-consolidate.md +3 -3
  62. package/framework/tasks/qa-planning-coverage-plan.md +2 -2
  63. package/framework/tasks/qa-planning-gate-define.md +4 -4
  64. package/framework/tasks/qa-planning-risk-matrix.md +4 -4
  65. package/framework/tasks/qa-planning-test-strategy.md +2 -2
  66. package/node_modules/@chati/browser-capability/src/index.js +12 -2
  67. package/node_modules/@chati/planning/src/index.js +24 -4
  68. package/node_modules/@chati/provider-registry/src/index.js +11 -0
  69. package/node_modules/@chati/rail/src/index.js +1967 -83
  70. package/node_modules/@chati/release-lane/README.md +12 -8
  71. package/node_modules/@chati/release-lane/package.json +1 -1
  72. package/node_modules/@chati/release-lane/src/index.js +1426 -58
  73. package/node_modules/@chati/review-council/src/index.js +63 -0
  74. package/node_modules/@chati/tracking-clickup/README.md +13 -0
  75. package/node_modules/@chati/tracking-clickup/src/index.js +690 -30
  76. package/package-artifact-manifest.json +1 -0
  77. package/package-artifact-manifest.sig +1 -0
  78. package/package.json +16 -7
  79. package/scripts/verify-real-harness-e2e.js +1581 -0
  80. package/src/config/framework-adapter.js +4 -4
  81. package/src/installer/core.js +148 -53
  82. package/src/installer/manifest.js +140 -9
  83. package/src/installer/package-artifact.js +249 -0
  84. package/src/installer/templates.js +65 -20
  85. package/src/installer-v2/catalog-client.js +531 -23
  86. package/src/installer-v2/index.js +91 -34
  87. package/src/installer-v2/installation-authority.js +327 -0
  88. package/src/installer-v2/provider-executable.js +235 -0
  89. package/src/installer-v2/wizard-installation.js +1 -1
  90. package/src/orchestrator/browser-runtime.js +44 -13
  91. package/src/orchestrator/cli.js +1545 -174
  92. package/src/orchestrator/clickup-projection.js +43 -1
  93. package/src/orchestrator/clickup-runtime.js +355 -39
  94. package/src/orchestrator/doctor.js +16 -3
  95. package/src/orchestrator/index.js +16 -0
  96. package/src/orchestrator/planning-runtime.js +20 -2
  97. package/src/orchestrator/rail-adjudication-evidence.js +234 -0
  98. package/src/orchestrator/rail-evidence-authority.js +147 -0
  99. package/src/orchestrator/rail-execution-evidence.js +45 -0
  100. package/src/orchestrator/rail-runtime.js +836 -56
  101. package/src/orchestrator/release-runtime.js +65 -6
  102. package/src/orchestrator/review-runtime.js +186 -41
  103. package/src/orchestrator/runtime-installation-v2.js +236 -20
  104. package/src/orchestrator/session-manager.js +1167 -53
  105. package/src/terminal/adapters/claude-adapter.js +3 -1
  106. package/src/terminal/adapters/codex-adapter.js +2 -0
  107. package/src/terminal/adapters/grok-adapter.js +7 -4
  108. package/src/terminal/handoff-parser.js +19 -1
  109. package/src/terminal/prompt-builder.js +9 -1
  110. package/src/terminal/provider-preflight.js +36 -3
  111. package/src/terminal/rail-execution-worktree.js +213 -0
  112. package/src/terminal/rail-prompts.js +169 -0
  113. package/src/terminal/rail-readonly-workspace.js +324 -0
  114. package/src/terminal/run-agent.js +384 -24
  115. package/src/terminal/run-parallel.js +5 -0
  116. package/src/terminal/run-rail-adjudication.js +323 -0
  117. package/src/terminal/run-rail-review.js +291 -0
  118. package/src/terminal/run-rail-rework.js +325 -0
  119. package/src/terminal/run-rail-task.js +380 -0
  120. package/src/terminal/run-team.js +5 -0
  121. package/src/terminal/spawner.js +1225 -77
  122. package/src/wizard/index.js +3 -2
package/README.md CHANGED
@@ -99,7 +99,7 @@ The agents guide you through each phase:
99
99
  |-------|-------------|--------|
100
100
  | **DISCOVER** | Agents interview you about what you want to build | Answer questions about your project |
101
101
  | **PLAN** | Agents create PRD, architecture, UX spec, phases, and tasks | Review and approve the plan |
102
- | **RAIL EXECUTION** | Dependency-ready tasks run on their explicitly selected model, with independent review, bounded rework, recovery, and local evidence | Review material scope or authority escalations |
102
+ | **RAIL EXECUTION** | Dependency-ready tasks run on their explicitly selected model, with independent review, bounded rework, core-observed recovery, and authority-signed CI and acceptance evidence | Review material scope or authority escalations |
103
103
  | **RELEASE** | A sealed release lane checks evidence, Git and CI readiness, with explicit human authorization for external actions | Authorize merge, deployment, or publication |
104
104
 
105
105
  Quality gates run automatically between phases. If something doesn't meet the threshold, the system loops back and fixes it.
@@ -163,7 +163,7 @@ Chati.dev is provider-agnostic. You choose your AI provider during installation,
163
163
  | Provider | CLI | Deep Reasoning | Lightweight | Status |
164
164
  |----------|-----|---------------|-------------|--------|
165
165
  | **Claude** | `claude` | Opus | Sonnet / Haiku | Default |
166
- | **Gemini** | `gemini` | Pro | Flash | Full support |
166
+ | **Gemini** | `gemini` | Pro | Flash | Legacy v1 support (outside the v2 RAIL pool) |
167
167
  | **Codex** | `codex` | Codex | Codex Mini | Full support |
168
168
 
169
169
  ### How Model Assignment Works
@@ -219,6 +219,11 @@ The system starts in `interactive` mode. Transition to `autonomous` requires bot
219
219
  | **RAIL EXECUTION** | Selected task executors, independent reviewers, browser capability where required | Execute the sealed task graph, collect evidence, recover interrupted attempts, and resolve bounded rework |
220
220
  | **RELEASE** | Release lane with human authority gate | Verify readiness and perform no external mutation without explicit authorization |
221
221
 
222
+ The installed CLI exposes release readiness only. Applications that own a
223
+ deployment integration can import `chati-dev/release`, inject a minted
224
+ `ReleaseTransport`, and execute release or rollback only with the exact signed
225
+ human authorization and smoke evidence required by the durable lane.
226
+
222
227
  ### How the Pipeline Works
223
228
 
224
229
  ```
@@ -258,7 +263,7 @@ The system starts in `interactive` mode. Transition to `autonomous` requires bot
258
263
  │ Dependency-ready task dispatch │
259
264
  │ Selected model and harness only │
260
265
  │ Independent review and rework │
261
- Recovery, tracking, local evidence
266
+ Recovery, tracking, signed evidence
262
267
  │ │
263
268
  └─ Opens release lane ───────────────────┐
264
269
 
package/bin/chati.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { resolve } from 'path';
4
+ import { randomUUID } from 'crypto';
4
5
  import { readFileSync } from 'fs';
5
6
  import { fileURLToPath } from 'url';
6
7
  import { dirname, join } from 'path';
@@ -27,8 +28,8 @@ const command = args[0] || 'init';
27
28
  // Without this, `chati orchestrate advance --agent detail` resolves targetDir to `<cwd>/detail/`.
28
29
  const KNOWN_SUBCOMMANDS = new Set([
29
30
  // CLI subcommands
30
- 'next', 'advance', 'init', 'status', 'validate-handoff', 'deviation', 'exit',
31
- 'install-v2', 'migrate-v2', 'rail-import', 'rail-next', 'rail-release-ready', 'rail-claim', 'rail-heartbeat', 'rail-recover', 'rail-complete', 'rail-review', 'rail-tracking-reconcile', 'rail-tracking-pending', 'rail-tracking-ack',
31
+ 'next', 'advance', 'init', 'status', 'validate-handoff', 'deviation', 'exit', 'activate-harness',
32
+ 'install-v2', 'migrate-v2', 'rail-import', 'rail-next', 'rail-dispatch', 'rail-review-run', 'rail-rework', 'rail-adjudicate', 'rail-release-ready', 'rail-recover', 'rail-complete', 'rail-tracking-reconcile', 'rail-tracking-pending', 'rail-tracking-ack', 'rail-tracking-lookup',
32
33
  'providers', 'detect-flow', 'backlog', 'qa-plan-score', 'qa-impl-score', 'scan',
33
34
  'spawn-team', 'team-status', 'team-dissolve',
34
35
  'stats', 'list', 'search', 'clean', 'check', // memory/registry subcommands
@@ -150,65 +151,102 @@ async function main() {
150
151
  break;
151
152
  }
152
153
 
153
- case 'rail-release-ready': {
154
- const handoffIndex = args.indexOf('--handoff-id');
155
- const handoff_id = handoffIndex === -1 ? null : args[handoffIndex + 1];
156
- if (!handoff_id) {
157
- console.error('Error: rail-release-ready requires --handoff-id <id>');
154
+ case 'rail-dispatch': {
155
+ const value = (flag) => { const index = args.indexOf(flag); return index === -1 ? null : args[index + 1]; };
156
+ if (!value('--handoff-id') || !value('--task-id')) {
157
+ console.error('Error: rail-dispatch requires --handoff-id <id> and --task-id <id>');
158
158
  process.exitCode = 1;
159
159
  break;
160
160
  }
161
+ const attemptId = value('--attempt-id') || `attempt-${randomUUID()}`;
161
162
  try {
162
- const { selectRailReleaseReadiness } = await import('../src/orchestrator/rail-runtime.js');
163
- console.log(JSON.stringify(selectRailReleaseReadiness({ projectDir: targetDir, handoff_id }), null, 2));
163
+ const { executeReadyRailTask } = await import('../src/terminal/run-rail-task.js');
164
+ const result = await executeReadyRailTask({
165
+ projectDir: targetDir,
166
+ handoff_id: value('--handoff-id'),
167
+ task_id: value('--task-id'),
168
+ attempt_id: attemptId,
169
+ operator_id: value('--operator-id') || 'operator://chati/cli',
170
+ ...(value('--timeout') ? { timeout: Number(value('--timeout')) } : {}),
171
+ ...(value('--browser-request-json') ? { browser_request: JSON.parse(value('--browser-request-json')) } : {}),
172
+ });
173
+ console.log(JSON.stringify(result, null, 2));
174
+ if (!result.ok) process.exitCode = 1;
164
175
  } catch (error) {
165
- console.error(`Error: ${error.code || 'RAIL_RELEASE_READINESS_FAILED'}: ${error.message}`);
176
+ let nextRequiredAction = 'rail_retry_same_attempt';
177
+ try {
178
+ const { resolveRailAttemptContext } = await import('../src/orchestrator/rail-runtime.js');
179
+ resolveRailAttemptContext({ projectDir: targetDir, handoff_id: value('--handoff-id'), attempt_id: attemptId });
180
+ nextRequiredAction = 'rail_recover_same_attempt_after_lease_expiry';
181
+ } catch {
182
+ // The dispatch never created a canonical claim.
183
+ }
184
+ console.error(JSON.stringify({
185
+ ok: false, action: 'error', error: error.code || 'RAIL_DISPATCH_FAILED',
186
+ detail: error.message, attempt_id: error.details?.attempt_id || attemptId,
187
+ next_required_action: nextRequiredAction,
188
+ }));
166
189
  process.exitCode = 1;
167
190
  }
168
191
  break;
169
192
  }
170
193
 
171
- case 'rail-claim': {
172
- const value = (flag) => {
173
- const index = args.indexOf(flag);
174
- return index === -1 ? null : args[index + 1];
175
- };
176
- const required = ['--handoff-id', '--task-id', '--attempt-id', '--operator-id', '--harness-process-id'];
177
- if (required.some((flag) => !value(flag))) {
178
- console.error(`Error: rail-claim requires ${required.join(', ')}`);
194
+ case 'rail-review-run':
195
+ case 'rail-rework':
196
+ case 'rail-adjudicate': {
197
+ const value = (flag) => { const index = args.indexOf(flag); return index === -1 ? null : args[index + 1]; };
198
+ if (!value('--handoff-id') || !value('--attempt-id')) {
199
+ console.error(`Error: ${command} requires --handoff-id <id> and --attempt-id <id>`);
179
200
  process.exitCode = 1;
180
201
  break;
181
202
  }
182
203
  try {
183
- const { claimRailTask } = await import('../src/orchestrator/rail-runtime.js');
184
- const result = claimRailTask({
185
- projectDir: targetDir, handoff_id: value('--handoff-id'), task_id: value('--task-id'), attempt_id: value('--attempt-id'),
186
- operator_id: value('--operator-id'), harness_process_id: value('--harness-process-id'), git_dir: value('--git-dir') || targetDir,
204
+ const modulePath = command === 'rail-review-run'
205
+ ? '../src/terminal/run-rail-review.js'
206
+ : command === 'rail-rework'
207
+ ? '../src/terminal/run-rail-rework.js'
208
+ : '../src/terminal/run-rail-adjudication.js';
209
+ const exportName = command === 'rail-review-run'
210
+ ? 'executeRailReview'
211
+ : command === 'rail-rework'
212
+ ? 'executeRailRework'
213
+ : 'executeRailAdjudication';
214
+ const runtime = await import(modulePath);
215
+ const result = await runtime[exportName]({
216
+ projectDir: targetDir,
217
+ handoff_id: value('--handoff-id'),
218
+ attempt_id: value('--attempt-id'),
219
+ ...(value('--timeout') ? { timeout: Number(value('--timeout')) } : {}),
187
220
  });
188
221
  console.log(JSON.stringify(result, null, 2));
222
+ const validReviewControlFlow = command === 'rail-review-run'
223
+ && ['rail_rework_required', 'rail_adjudication_required', 'human_authority_required'].includes(result.next_required_action);
224
+ if (!result.ok && !validReviewControlFlow) process.exitCode = 1;
189
225
  } catch (error) {
190
- console.error(`Error: ${error.code || 'RAIL_CLAIM_FAILED'}: ${error.message}`);
226
+ const code = command === 'rail-review-run'
227
+ ? 'RAIL_REVIEW_FAILED'
228
+ : command === 'rail-rework'
229
+ ? 'RAIL_REWORK_FAILED'
230
+ : 'RAIL_ADJUDICATION_FAILED';
231
+ console.error(`Error: ${error.code || code}: ${error.message}`);
191
232
  process.exitCode = 1;
192
233
  }
193
234
  break;
194
235
  }
195
236
 
196
- case 'rail-heartbeat': {
197
- const value = (flag) => { const index = args.indexOf(flag); return index === -1 ? null : args[index + 1]; };
198
- const required = ['--handoff-id', '--attempt-id', '--claim-id', '--operator-id'];
199
- if (required.some((flag) => !value(flag))) {
200
- console.error(`Error: rail-heartbeat requires ${required.join(', ')}`);
237
+ case 'rail-release-ready': {
238
+ const handoffIndex = args.indexOf('--handoff-id');
239
+ const handoff_id = handoffIndex === -1 ? null : args[handoffIndex + 1];
240
+ if (!handoff_id) {
241
+ console.error('Error: rail-release-ready requires --handoff-id <id>');
201
242
  process.exitCode = 1;
202
243
  break;
203
244
  }
204
245
  try {
205
- const { heartbeatRailTask } = await import('../src/orchestrator/rail-runtime.js');
206
- console.log(JSON.stringify(heartbeatRailTask({
207
- projectDir: targetDir, handoff_id: value('--handoff-id'), attempt_id: value('--attempt-id'),
208
- claim_id: value('--claim-id'), operator_id: value('--operator-id'),
209
- }), null, 2));
246
+ const { selectRailReleaseReadiness } = await import('../src/orchestrator/rail-runtime.js');
247
+ console.log(JSON.stringify(selectRailReleaseReadiness({ projectDir: targetDir, handoff_id }), null, 2));
210
248
  } catch (error) {
211
- console.error(`Error: ${error.code || 'RAIL_HEARTBEAT_FAILED'}: ${error.message}`);
249
+ console.error(`Error: ${error.code || 'RAIL_RELEASE_READINESS_FAILED'}: ${error.message}`);
212
250
  process.exitCode = 1;
213
251
  }
214
252
  break;
@@ -216,22 +254,40 @@ async function main() {
216
254
 
217
255
  case 'rail-recover': {
218
256
  const value = (flag) => { const index = args.indexOf(flag); return index === -1 ? null : args[index + 1]; };
219
- const required = ['--handoff-id', '--attempt-id', '--operator-id', '--harness-process-id', '--reconciliation'];
257
+ const required = ['--handoff-id', '--attempt-id', '--operator-id'];
220
258
  if (required.some((flag) => !value(flag))) {
221
259
  console.error(`Error: rail-recover requires ${required.join(', ')}`);
222
260
  process.exitCode = 1;
223
261
  break;
224
262
  }
263
+ const attemptId = value('--attempt-id');
225
264
  try {
226
- const reconciliation = JSON.parse(readFileSync(resolve(value('--reconciliation')), 'utf8'));
227
- const { recoverRailTask } = await import('../src/orchestrator/rail-runtime.js');
228
- console.log(JSON.stringify(recoverRailTask({
229
- projectDir: targetDir, handoff_id: value('--handoff-id'), attempt_id: value('--attempt-id'),
230
- operator_id: value('--operator-id'), harness_process_id: value('--harness-process-id'), reconciliation,
265
+ const { resolveRailAttemptContext } = await import('../src/orchestrator/rail-runtime.js');
266
+ const { executeReadyRailTask } = await import('../src/terminal/run-rail-task.js');
267
+ const context = resolveRailAttemptContext({
268
+ projectDir: targetDir,
269
+ handoff_id: value('--handoff-id'),
270
+ attempt_id: attemptId,
271
+ });
272
+ const result = await executeReadyRailTask({
273
+ projectDir: targetDir,
274
+ handoff_id: value('--handoff-id'),
275
+ task_id: context.task.task_id,
276
+ attempt_id: attemptId,
277
+ operator_id: value('--operator-id'),
231
278
  git_dir: value('--git-dir') || targetDir,
232
- }), null, 2));
279
+ recover_expired: true,
280
+ ...(value('--timeout') ? { timeout: Number(value('--timeout')) } : {}),
281
+ ...(value('--browser-request-json') ? { browser_request: JSON.parse(value('--browser-request-json')) } : {}),
282
+ });
283
+ console.log(JSON.stringify(result, null, 2));
284
+ if (!result.ok) process.exitCode = 1;
233
285
  } catch (error) {
234
- console.error(`Error: ${error.code || 'RAIL_RECOVERY_FAILED'}: ${error.message}`);
286
+ console.error(JSON.stringify({
287
+ ok: false, action: 'error', error: error.code || 'RAIL_RECOVERY_FAILED',
288
+ detail: error.message, attempt_id: error.details?.attempt_id || attemptId,
289
+ next_required_action: 'rail_recover_and_dispatch_same_attempt',
290
+ }));
235
291
  process.exitCode = 1;
236
292
  }
237
293
  break;
@@ -247,10 +303,10 @@ async function main() {
247
303
  try {
248
304
  const completion = JSON.parse(readFileSync(resolve(value('--completion')), 'utf8'));
249
305
  const { completeRailTask } = await import('../src/orchestrator/rail-runtime.js');
250
- const { completion_id, attempt_id, claim_id, operator_id, state, git, ci, reviews, acceptance_evidence_refs, completed_at, metrics } = completion;
306
+ const { completion_id, attempt_id, claim_id, operator_id, state, git, ci, reviews, acceptance_evidence_refs, acceptance_authority_receipt, completed_at, metrics } = completion;
251
307
  console.log(JSON.stringify(completeRailTask({
252
308
  projectDir: targetDir, handoff_id: value('--handoff-id'), completion_id, attempt_id, claim_id, operator_id, state, git, ci,
253
- reviews, acceptance_evidence_refs, ...(completed_at === undefined ? {} : { completed_at }), ...(metrics === undefined ? {} : { metrics }),
309
+ reviews, acceptance_evidence_refs, acceptance_authority_receipt, ...(completed_at === undefined ? {} : { completed_at }), ...(metrics === undefined ? {} : { metrics }),
254
310
  }), null, 2));
255
311
  } catch (error) {
256
312
  console.error(`Error: ${error.code || 'RAIL_COMPLETION_FAILED'}: ${error.message}`);
@@ -276,8 +332,8 @@ async function main() {
276
332
 
277
333
  case 'rail-tracking-pending': {
278
334
  try {
279
- const { listPendingClickUpProjections } = await import('../src/orchestrator/clickup-runtime.js');
280
- console.log(JSON.stringify(listPendingClickUpProjections({ projectDir: targetDir }), null, 2));
335
+ const { preparePendingClickUpProjections } = await import('../src/orchestrator/clickup-runtime.js');
336
+ console.log(JSON.stringify(preparePendingClickUpProjections({ projectDir: targetDir }), null, 2));
281
337
  } catch (error) {
282
338
  console.error(`Error: ${error.code || 'RAIL_TRACKING_PENDING_FAILED'}: ${error.message}`);
283
339
  process.exitCode = 1;
@@ -285,43 +341,45 @@ async function main() {
285
341
  break;
286
342
  }
287
343
 
288
- case 'rail-tracking-ack': {
344
+ case 'rail-tracking-lookup': {
289
345
  const value = (flag) => { const index = args.indexOf(flag); return index === -1 ? null : args[index + 1]; };
290
- if (!value('--handoff-id') || !value('--projection-id') || !value('--receipt')) {
291
- console.error('Error: rail-tracking-ack requires --handoff-id <id>, --projection-id <id> and --receipt <receipt.json>');
346
+ if (!value('--handoff-id') || !value('--projection-id') || !value('--result')) {
347
+ console.error('Error: rail-tracking-lookup requires --handoff-id <id>, --projection-id <id> and --result <lookup.json>');
292
348
  process.exitCode = 1;
293
349
  break;
294
350
  }
295
351
  try {
296
- const receipt = JSON.parse(readFileSync(resolve(value('--receipt')), 'utf8'));
297
- const { acknowledgeClickUpProjection } = await import('../src/orchestrator/clickup-runtime.js');
298
- console.log(JSON.stringify(acknowledgeClickUpProjection({
299
- projectDir: targetDir,
300
- handoff_id: value('--handoff-id'),
301
- projection_id: value('--projection-id'),
302
- receipt,
352
+ const result = JSON.parse(readFileSync(resolve(value('--result')), 'utf8'));
353
+ const { resolveClickUpProjectionLookup } = await import('../src/orchestrator/clickup-runtime.js');
354
+ console.log(JSON.stringify(resolveClickUpProjectionLookup({
355
+ projectDir: targetDir, handoff_id: value('--handoff-id'),
356
+ projection_id: value('--projection-id'), result,
303
357
  }), null, 2));
304
358
  } catch (error) {
305
- console.error(`Error: ${error.code || 'RAIL_TRACKING_ACK_FAILED'}: ${error.message}`);
359
+ console.error(`Error: ${error.code || 'RAIL_TRACKING_LOOKUP_FAILED'}: ${error.message}`);
306
360
  process.exitCode = 1;
307
361
  }
308
362
  break;
309
363
  }
310
364
 
311
- case 'rail-review': {
365
+ case 'rail-tracking-ack': {
312
366
  const value = (flag) => { const index = args.indexOf(flag); return index === -1 ? null : args[index + 1]; };
313
- if (!value('--review') || !value('--invocation')) {
314
- console.error('Error: rail-review requires --review <review.json> and --invocation <invocation.json>');
367
+ if (!value('--handoff-id') || !value('--projection-id') || !value('--receipt')) {
368
+ console.error('Error: rail-tracking-ack requires --handoff-id <id>, --projection-id <id> and --receipt <receipt.json>');
315
369
  process.exitCode = 1;
316
370
  break;
317
371
  }
318
372
  try {
319
- const review = JSON.parse(readFileSync(resolve(value('--review')), 'utf8'));
320
- const invocation = JSON.parse(readFileSync(resolve(value('--invocation')), 'utf8'));
321
- const { recordRailReview } = await import('../src/orchestrator/review-runtime.js');
322
- console.log(JSON.stringify(recordRailReview({ projectDir: targetDir, review, invocation }), null, 2));
373
+ const receipt = JSON.parse(readFileSync(resolve(value('--receipt')), 'utf8'));
374
+ const { acknowledgeClickUpProjection } = await import('../src/orchestrator/clickup-runtime.js');
375
+ console.log(JSON.stringify(acknowledgeClickUpProjection({
376
+ projectDir: targetDir,
377
+ handoff_id: value('--handoff-id'),
378
+ projection_id: value('--projection-id'),
379
+ receipt,
380
+ }), null, 2));
323
381
  } catch (error) {
324
- console.error(`Error: ${error.code || 'RAIL_REVIEW_FAILED'}: ${error.message}`);
382
+ console.error(`Error: ${error.code || 'RAIL_TRACKING_ACK_FAILED'}: ${error.message}`);
325
383
  process.exitCode = 1;
326
384
  }
327
385
  break;
@@ -834,7 +892,7 @@ Telemetry:
834
892
  // (e.g., `chati orchestrate xyz` should not silently create cwd/xyz/ as targetDir)
835
893
  const VALID_ORCHESTRATE_SUBS = new Set([
836
894
  'next', 'advance', 'init', 'status', 'validate-handoff',
837
- 'deviation', 'exit', 'providers', 'detect-flow', 'backlog',
895
+ 'deviation', 'exit', 'activate-harness', 'providers', 'detect-flow', 'backlog',
838
896
  'qa-plan-score', 'qa-impl-score', 'qa-visual-score', 'scan',
839
897
  'spawn-team', 'team-status', 'team-dissolve',
840
898
  'wait-for-capture', 'wave-status', 'assess-coverage',
@@ -35,7 +35,7 @@ Implement each task from the approved task breakdown with high quality, followin
35
35
  ## On Activation
36
36
 
37
37
  1. Read handoff from QA-Planning
38
- 2. Read `.chati/session.yaml` for execution_mode and project context
38
+ 2. Use the validated canonical session context supplied in the activation prompt for `execution_mode` and project context. Never read `.chati/session.yaml` directly.
39
39
  3. Read Tasks: `artifacts/6-Tasks/tasks.md`
40
40
  4. Read Architecture: `artifacts/3-Architecture/architecture.md`
41
41
  5. Read UX: `artifacts/4-UX/ux-specification.md` (Design System tokens)
@@ -574,7 +574,7 @@ User can intervene at any point.
574
574
 
575
575
  ### Autonomous Mode (Ralph Wiggum)
576
576
  ```
577
- Activated when session.yaml execution_mode = autonomous
577
+ Activated when the router-validated prompt context has `execution_mode = autonomous`
578
578
 
579
579
  ANTI-LOOP GUARANTEE: Each step (5.5, 6.5) executes ONCE per attempt.
580
580
  No re-running tests after 6.5. No cycling back to 5.5.
@@ -987,13 +987,13 @@ This agent supports TASK-LEVEL parallelization (all modes):
987
987
 
988
988
  | Level | Source | Purpose |
989
989
  |-------|--------|---------|
990
- | L0 | `.chati/session.yaml` | Execution mode (interactive/autonomous), pipeline state, agent statuses |
990
+ | L0 | Router-validated prompt context | Execution mode (interactive/autonomous), pipeline state, agent statuses |
991
991
  | L1 | `chati.dev/constitution.md` | Protocols, validation thresholds, blocker taxonomy, handoff rules |
992
992
  | L2 | `artifacts/6-Tasks/tasks.md` | Task definitions with acceptance criteria (Given-When-Then) |
993
993
  | L3 | `artifacts/3-Architecture/architecture.md` | Tech stack, patterns, conventions, file structure |
994
994
  | L4 | `artifacts/4-UX/ux-specification.md` | Design System tokens for token enforcement |
995
995
 
996
- **Workflow Awareness**: The Dev agent must check `session.yaml` for `execution_mode` to determine whether to operate in interactive (user acknowledgment per task) or autonomous (Ralph Wiggum) mode. It must also read intelligence files for known gotchas before each task.
996
+ **Workflow Awareness**: The Dev agent uses `execution_mode` from its validated activation context to determine whether to operate in interactive (user acknowledgment per task) or autonomous (Ralph Wiggum) mode. If absent, return `needs_input`; never inspect canonical session storage directly. It must also read intelligence files for known gotchas before each task.
997
997
 
998
998
  ---
999
999
 
@@ -1097,7 +1097,7 @@ ANTI-CYCLE RULE: Levels are a one-way escalation path. NEVER go back to a previo
1097
1097
 
1098
1098
  ### Team Mode Detection
1099
1099
 
1100
- Team mode is active when ANY of these is true: (a) your activation prompt contains "Team mode active", (b) `CHATI_TEAM_ID` environment variable is set, or (c) `session.yaml` `teams[]` has an active entry where your name appears in the roster.
1100
+ Team mode is active when your validated activation prompt says "Team mode active" or `CHATI_TEAM_ID` is set. Never inspect canonical session storage to infer membership.
1101
1101
 
1102
1102
  If team mode is active:
1103
1103
  1. Read your Shared Task List from the team's `task_list_path`.
@@ -34,7 +34,7 @@ Ship the validated code to production: organize commits, create pull requests, d
34
34
  ## On Activation
35
35
 
36
36
  1. Read handoff from QA-Implementation
37
- 2. Read `.chati/session.yaml` for project context
37
+ 2. Use the validated canonical session context supplied in the activation prompt for project context. Never read `.chati/session.yaml` directly.
38
38
  3. Read QA-Implementation report: `artifacts/9-QA-Implementation/qa-implementation-report.md`
39
39
  4. Verify QA-Implementation status is APPROVED
40
40
  5. Read QA-Visual report if it exists: `artifacts/9-QA-Implementation/qa-visual-report.md`. If found, verify QA-Visual score >= 90% before proceeding. If the report is missing, note it as "QA-Visual not run" and continue (it is not a hard blocker if the project has no UI).
@@ -142,9 +142,9 @@ Validation:
142
142
  ```
143
143
  1. Complete your handoff document (artifacts/handoffs/devops-handoff.md) with final state.
144
144
  Do NOT edit session.yaml directly — the mode-governance hook blocks this.
145
- The CLI records completion and updates session.yaml when you run:
145
+ The CLI records completion in canonical state when you run:
146
146
  node chati.dev/orchestrator/chati-router.js advance --agent devops --score <N>
147
- Reference state for handoff document (orchestrator will apply to session.yaml):
147
+ Reference state for the handoff document (the orchestrator will persist it canonically):
148
148
  - project.state: completed
149
149
  - devops status: completed
150
150
  2. Update `.chati/project-context.md` with final project state
@@ -167,7 +167,7 @@ Criteria (binary pass/fail):
167
167
  7. CHANGELOG.md generated/updated
168
168
  8. No hardcoded secrets in deployed code
169
169
  9. SSL is valid on deployed URL
170
- 10. Session.yaml updated to completed state
170
+ 10. Canonical state recorded as completed
171
171
 
172
172
  Score = criteria met / total criteria
173
173
  Threshold: >= 90% (9/10 minimum)
@@ -340,7 +340,7 @@ Rules:
340
340
  | `git-ops` | Git Operations | Organize commits, ensure conventional format, create PR, push to remote | After verify-prereqs |
341
341
  | `deploy` | Deploy | Build project, deploy to target platform, verify deployment (URL, SSL, response) | After git-ops |
342
342
  | `docs-gen` | Generate Documentation | Generate/update README.md, CHANGELOG.md, API.md | After deploy |
343
- | `finalize` | Finalize | Generate final handoff (CLI advances session.yaml to completed), update `.chati/project-context.md`, generate final summary | After docs-gen |
343
+ | `finalize` | Finalize | Generate final handoff (CLI records canonical completion), update `.chati/project-context.md`, generate final summary | After docs-gen |
344
344
 
345
345
  ---
346
346
 
@@ -348,7 +348,7 @@ Rules:
348
348
 
349
349
  | Level | Source | Purpose |
350
350
  |-------|--------|---------|
351
- | L0 | `.chati/session.yaml` | Project state, pipeline position, agent statuses, deployment configuration |
351
+ | L0 | Router-validated prompt context | Project state, pipeline position, agent statuses, deployment configuration |
352
352
  | L1 | `chati.dev/constitution.md` | Protocols, handoff rules, session finalization requirements |
353
353
  | L2 | `artifacts/9-QA-Implementation/qa-implementation-report.md` | Approval status, test results, security scan, code review findings |
354
354
  | L3 | `artifacts/3-Architecture/architecture.md` | Deployment strategy, platform target, infrastructure configuration |
@@ -414,7 +414,7 @@ signals to the signed router. This agent cannot change its provider or model.
414
414
  4. **Documentation is not optional**: README.md and CHANGELOG.md are part of the deployment - code without documentation is an incomplete delivery
415
415
  5. **Only DevOps pushes**: No other agent is authorized to push to remote or create PRs - this boundary is absolute
416
416
  6. **Conventional commits enforced**: All commits must follow the conventional format (feat:, fix:, docs:, chore:) - free-form commit messages are rejected
417
- 7. **Session finalization is the last action**: Updating session.yaml to `state: completed` and `.chati/project-context.md` with the final project state is the definitive last step
417
+ 7. **Session finalization is the last action**: Return `state: completed` and the final project-context changes in the handoff so the router and canonical session manager persist them as the definitive last step
418
418
 
419
419
  ---
420
420
 
@@ -32,7 +32,7 @@ Extract, analyze, and document the core problems, desired outcomes, target users
32
32
  ## On Activation
33
33
 
34
34
  1. Read handoff from previous agent (greenfield-wu or brownfield-wu)
35
- 2. Read `.chati/session.yaml` for language and project context
35
+ 2. Use the validated canonical session context supplied in the activation prompt for language and project context. Never read `.chati/session.yaml` directly.
36
36
  3. Process Layer 1 (Summary), then Layer 2 if present
37
37
  4. Acknowledge inherited context before starting work
38
38
 
@@ -91,7 +91,7 @@ Adapt method depth to user level:
91
91
  Purpose: Get everything out of the user's head without filtering
92
92
 
93
93
  IMPORTANT - Check for initial_context FIRST:
94
- IF session.yaml contains initial_context (from /chati <prompt> inline input):
94
+ IF the validated activation context contains `initial_context` (from /chati <prompt> inline input):
95
95
  1. Treat initial_context as the PRIMARY brain dump input
96
96
  2. Parse it for: vision, problems, users, constraints, references
97
97
  3. Acknowledge what was captured: "From your initial description, I captured: {summary}"
@@ -573,7 +573,7 @@ domains:
573
573
  Pre-conditions:
574
574
  - WU agent completed with score >= 85%
575
575
  - WU handoff file exists at artifacts/handoffs/
576
- - session.yaml updated with WU completion data
576
+ - Canonical state contains WU completion data
577
577
  Input data:
578
578
  Layer 1 (Summary):
579
579
  - Project type (greenfield/brownfield)
@@ -603,7 +603,7 @@ Contents:
603
603
  - User-approved brief status
604
604
  Post-conditions:
605
605
  - Brief report at artifacts/1-Brief/brief-report.md
606
- - session.yaml updated with Brief completion data
606
+ - Canonical state contains Brief completion data
607
607
  - User has explicitly approved the brief
608
608
  ```
609
609
 
@@ -32,7 +32,7 @@ Produce a comprehensive understanding of the existing project: its tech stack, a
32
32
  ## On Activation
33
33
 
34
34
  1. Read handoff from orchestrator (if any)
35
- 2. Read `.chati/session.yaml` for project context and language
35
+ 2. Use the validated canonical session context supplied in the activation prompt for project context and language. Never read `.chati/session.yaml` directly.
36
36
  3. Acknowledge inherited context
37
37
  4. Begin discovery in user's interaction language
38
38
 
@@ -389,7 +389,7 @@ domains:
389
389
  ```
390
390
  Pre-conditions:
391
391
  - Project identified as brownfield
392
- - session.yaml initialized with project.type = brownfield
392
+ - Canonical session state initialized by the session manager with `project.type = brownfield`
393
393
  - Existing codebase accessible at project root
394
394
  Input data:
395
395
  - User's project description and goals
@@ -417,7 +417,7 @@ Contents:
417
417
  - Integration map with external service details
418
418
  Post-conditions:
419
419
  - Full WU report at artifacts/0-WU/wu-full-report.md
420
- - session.yaml updated with WU completion data
420
+ - Canonical state contains WU completion data
421
421
  ```
422
422
 
423
423
  ---
@@ -32,7 +32,7 @@ Capture the user's current operational context - their workflow, tools, friction
32
32
  ## On Activation
33
33
 
34
34
  1. Read handoff from orchestrator (if any)
35
- 2. Read `.chati/session.yaml` for project context and language
35
+ 2. Use the validated canonical session context supplied in the activation prompt for project context and language. Never read `.chati/session.yaml` directly.
36
36
  3. Acknowledge inherited context
37
37
  4. Begin operational discovery in user's interaction language
38
38
 
@@ -389,7 +389,7 @@ word per line. If nothing qualifies, omit the section entirely (empty list).
389
389
  ```
390
390
  Pre-conditions:
391
391
  - Project identified as greenfield
392
- - session.yaml initialized with project.type = greenfield
392
+ - Canonical session state initialized by the session manager with `project.type = greenfield`
393
393
  Input data:
394
394
  - User's initial project description
395
395
  - Detected language
@@ -408,7 +408,7 @@ Contents:
408
408
  - User level assessment update
409
409
  Post-conditions:
410
410
  - WU report at artifacts/0-WU/wu-operational-report.md
411
- - session.yaml updated by CLI via `node chati.dev/orchestrator/chati-router.js advance --agent greenfield-wu --score <N>` (do NOT edit session.yaml directly)
411
+ - Canonical state updated by CLI via `node chati.dev/orchestrator/chati-router.js advance --agent greenfield-wu --score <N>`
412
412
  ```
413
413
 
414
414
  ---
@@ -41,7 +41,7 @@ Coordinate the technical design by activating 2 specialist sub-agents in sequenc
41
41
  ## On Activation
42
42
 
43
43
  1. Read handoff from Detail (greenfield) or Brief (brownfield)
44
- 2. Read `.chati/session.yaml` for project context
44
+ 2. Use the validated canonical session context supplied in the activation prompt for project context. Never read `.chati/session.yaml` directly.
45
45
  3. Read PRD: `artifacts/2-PRD/prd.md`
46
46
  4. Read Brief: `artifacts/1-Brief/brief-report.md` (includes visual reference captures with animation libraries detected — GSAP, Lenis, ScrollTrigger counts — use to inform frontend stack decisions)
47
47
  5. If brownfield: Read WU report for existing stack/schema assessment
@@ -222,7 +222,7 @@ Score = criteria met / 10. Threshold: >= 90% (9/10 minimum).
222
222
 
223
223
  ### Team Mode Detection
224
224
 
225
- Team mode is active when ANY of these is true: (a) your activation prompt contains "Team mode active", (b) `CHATI_TEAM_ID` environment variable is set, or (c) `session.yaml` `teams[]` has an active entry where your name appears in the roster.
225
+ Team mode is active when your validated activation prompt says "Team mode active" or `CHATI_TEAM_ID` is set. Never inspect canonical session storage to infer membership.
226
226
 
227
227
  If team mode is active:
228
228
  1. Read your Shared Task List from the team's `task_list_path`.
@@ -33,7 +33,7 @@ Create a comprehensive, unambiguous Product Requirements Document that translate
33
33
  ## On Activation
34
34
 
35
35
  1. Read handoff from previous agent (Brief or Architect in brownfield)
36
- 2. Read `.chati/session.yaml` for project context
36
+ 2. Use the validated canonical session context supplied in the activation prompt for project context. Never read `.chati/session.yaml` directly.
37
37
  3. Read Brief artifact: `artifacts/1-Brief/brief-report.md`
38
38
  4. If brownfield: also read Architecture artifact for existing constraints
39
39
  5. Acknowledge inherited context
@@ -323,13 +323,13 @@ Rules:
323
323
 
324
324
  | Level | Source | Purpose |
325
325
  |-------|--------|---------|
326
- | L0 | `.chati/session.yaml` | Project type, current pipeline position, mode, agent statuses |
326
+ | L0 | Router-validated prompt context | Project type, current pipeline position, mode, agent statuses |
327
327
  | L1 | `chati.dev/constitution.md` | Protocols, validation thresholds, handoff rules |
328
328
  | L1.5 | `chati.dev/rules/human-writing-style.md` | Anti-AI prose rules for human-facing PRD sections |
329
329
  | L2 | `artifacts/1-Brief/brief-report.md` | Problems, desired outcomes, constraints, target users |
330
330
  | L3 | `artifacts/handoffs/brief-handoff.md` | Brief agent handoff with decisions and open questions |
331
331
 
332
- **Workflow Awareness**: The Detail agent must check `session.yaml` to understand its pipeline position and whether it is operating in a greenfield or brownfield flow, as this changes which upstream artifacts are available.
332
+ **Workflow Awareness**: Use the validated session context in the activation prompt to understand pipeline position and whether the flow is greenfield or brownfield. If that context is missing, return `needs_input`; never inspect the session file directly.
333
333
 
334
334
  ---
335
335
 
@@ -414,7 +414,7 @@ or substitute that binding.
414
414
 
415
415
  ### Team Mode Detection
416
416
 
417
- Team mode is active when ANY of these is true: (a) your activation prompt contains "Team mode active", (b) `CHATI_TEAM_ID` environment variable is set, or (c) `session.yaml` `teams[]` has an active entry where your name appears in the roster.
417
+ Team mode is active when your validated activation prompt says "Team mode active" or `CHATI_TEAM_ID` is set. Never inspect canonical session storage to infer membership.
418
418
 
419
419
  If team mode is active:
420
420
  1. Read your Shared Task List from the team's `task_list_path`.
@@ -33,7 +33,7 @@ Break the PRD requirements into ordered development phases where Phase 1 is alwa
33
33
  ## On Activation
34
34
 
35
35
  1. Read handoff from UX agent
36
- 2. Read `.chati/session.yaml` for project context
36
+ 2. Use the validated canonical session context supplied in the activation prompt for project context. Never read `.chati/session.yaml` directly.
37
37
  3. Read PRD: `artifacts/2-PRD/prd.md`
38
38
  4. Read Architecture: `artifacts/3-Architecture/architecture.md`
39
39
  5. Acknowledge inherited context
@@ -294,7 +294,7 @@ Rules:
294
294
 
295
295
  | Level | Source | Purpose |
296
296
  |-------|--------|---------|
297
- | L0 | `.chati/session.yaml` | Project type, current pipeline position, mode, agent statuses |
297
+ | L0 | Router-validated prompt context | Project type, current pipeline position, mode, agent statuses |
298
298
  | L1 | `chati.dev/constitution.md` | Protocols, validation thresholds, handoff rules |
299
299
  | L2 | `artifacts/2-PRD/prd.md` | Full requirements list with IDs, priorities, and acceptance criteria |
300
300
  | L3 | `artifacts/3-Architecture/architecture.md` | Tech constraints, infrastructure dependencies, deployment strategy |
@@ -33,7 +33,7 @@ Create atomic, testable, estimable tasks for each phase. Every task has a clear
33
33
  ## On Activation
34
34
 
35
35
  1. Read handoff from Phases agent
36
- 2. Read `.chati/session.yaml` for project context
36
+ 2. Use the validated canonical session context supplied in the activation prompt for project context. Never read `.chati/session.yaml` directly.
37
37
  3. Read Phases: `artifacts/5-Phases/phases.md`
38
38
  4. Read PRD: `artifacts/2-PRD/prd.md`
39
39
  5. Read Architecture: `artifacts/3-Architecture/architecture.md`
@@ -476,7 +476,7 @@ Rules:
476
476
 
477
477
  | Level | Source | Purpose |
478
478
  |-------|--------|---------|
479
- | L0 | `.chati/session.yaml` | Project type, current pipeline position, mode, agent statuses |
479
+ | L0 | Router-validated prompt context | Project type, current pipeline position, mode, agent statuses |
480
480
  | L1 | `chati.dev/constitution.md` | Protocols, validation thresholds, handoff rules |
481
481
  | L2 | `artifacts/5-Phases/phases.md` | Phase breakdown, wave structure, requirement assignments |
482
482
  | L3 | `artifacts/2-PRD/prd.md` | Full requirements list with acceptance criteria for traceability |