openplanr 1.16.2 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/dist/cli/commands/operate.d.ts +10 -1
  2. package/dist/cli/commands/operate.d.ts.map +1 -1
  3. package/dist/cli/commands/operate.js +240 -13
  4. package/dist/cli/commands/operate.js.map +1 -1
  5. package/dist/services/ai-service.d.ts +25 -0
  6. package/dist/services/ai-service.d.ts.map +1 -1
  7. package/dist/services/ai-service.js +38 -0
  8. package/dist/services/ai-service.js.map +1 -1
  9. package/dist/services/operate/advisors.d.ts +82 -1
  10. package/dist/services/operate/advisors.d.ts.map +1 -1
  11. package/dist/services/operate/advisors.js +469 -17
  12. package/dist/services/operate/advisors.js.map +1 -1
  13. package/dist/services/operate/artifacts.d.ts +27 -1
  14. package/dist/services/operate/artifacts.d.ts.map +1 -1
  15. package/dist/services/operate/artifacts.js +103 -1
  16. package/dist/services/operate/artifacts.js.map +1 -1
  17. package/dist/services/operate/cadence.d.ts +50 -0
  18. package/dist/services/operate/cadence.d.ts.map +1 -0
  19. package/dist/services/operate/cadence.js +56 -0
  20. package/dist/services/operate/cadence.js.map +1 -0
  21. package/dist/services/operate/citation-resolution.d.ts +101 -0
  22. package/dist/services/operate/citation-resolution.d.ts.map +1 -0
  23. package/dist/services/operate/citation-resolution.js +308 -0
  24. package/dist/services/operate/citation-resolution.js.map +1 -0
  25. package/dist/services/operate/config.d.ts +93 -1
  26. package/dist/services/operate/config.d.ts.map +1 -1
  27. package/dist/services/operate/config.js +199 -9
  28. package/dist/services/operate/config.js.map +1 -1
  29. package/dist/services/operate/decision-brief.d.ts +148 -0
  30. package/dist/services/operate/decision-brief.d.ts.map +1 -0
  31. package/dist/services/operate/decision-brief.js +194 -0
  32. package/dist/services/operate/decision-brief.js.map +1 -0
  33. package/dist/services/operate/doctor.d.ts.map +1 -1
  34. package/dist/services/operate/doctor.js +271 -3
  35. package/dist/services/operate/doctor.js.map +1 -1
  36. package/dist/services/operate/engine.d.ts +66 -2
  37. package/dist/services/operate/engine.d.ts.map +1 -1
  38. package/dist/services/operate/engine.js +219 -7
  39. package/dist/services/operate/engine.js.map +1 -1
  40. package/dist/services/operate/event-store.d.ts +35 -1
  41. package/dist/services/operate/event-store.d.ts.map +1 -1
  42. package/dist/services/operate/event-store.js +142 -29
  43. package/dist/services/operate/event-store.js.map +1 -1
  44. package/dist/services/operate/evidence-cache.d.ts +25 -1
  45. package/dist/services/operate/evidence-cache.d.ts.map +1 -1
  46. package/dist/services/operate/evidence-cache.js +62 -1
  47. package/dist/services/operate/evidence-cache.js.map +1 -1
  48. package/dist/services/operate/evidence.d.ts +20 -1
  49. package/dist/services/operate/evidence.d.ts.map +1 -1
  50. package/dist/services/operate/evidence.js +148 -0
  51. package/dist/services/operate/evidence.js.map +1 -1
  52. package/dist/services/operate/index.d.ts +2 -0
  53. package/dist/services/operate/index.d.ts.map +1 -1
  54. package/dist/services/operate/index.js +309 -46
  55. package/dist/services/operate/index.js.map +1 -1
  56. package/dist/services/operate/interaction/action-service.d.ts +17 -0
  57. package/dist/services/operate/interaction/action-service.d.ts.map +1 -1
  58. package/dist/services/operate/interaction/action-service.js +19 -0
  59. package/dist/services/operate/interaction/action-service.js.map +1 -1
  60. package/dist/services/operate/interaction/answer-service.d.ts +17 -0
  61. package/dist/services/operate/interaction/answer-service.d.ts.map +1 -1
  62. package/dist/services/operate/interaction/answer-service.js +49 -7
  63. package/dist/services/operate/interaction/answer-service.js.map +1 -1
  64. package/dist/services/operate/interaction/question-engine.d.ts.map +1 -1
  65. package/dist/services/operate/interaction/question-engine.js +9 -3
  66. package/dist/services/operate/interaction/question-engine.js.map +1 -1
  67. package/dist/services/operate/interaction/question-registry.d.ts +13 -0
  68. package/dist/services/operate/interaction/question-registry.d.ts.map +1 -1
  69. package/dist/services/operate/interaction/question-registry.js +116 -26
  70. package/dist/services/operate/interaction/question-registry.js.map +1 -1
  71. package/dist/services/operate/interaction/terminal-renderer.d.ts +12 -1
  72. package/dist/services/operate/interaction/terminal-renderer.d.ts.map +1 -1
  73. package/dist/services/operate/interaction/terminal-renderer.js +26 -15
  74. package/dist/services/operate/interaction/terminal-renderer.js.map +1 -1
  75. package/dist/services/operate/journal.d.ts.map +1 -1
  76. package/dist/services/operate/journal.js +11 -5
  77. package/dist/services/operate/journal.js.map +1 -1
  78. package/dist/services/operate/lifecycle.d.ts +8 -0
  79. package/dist/services/operate/lifecycle.d.ts.map +1 -1
  80. package/dist/services/operate/lifecycle.js +19 -1
  81. package/dist/services/operate/lifecycle.js.map +1 -1
  82. package/dist/services/operate/maintenance.d.ts +22 -0
  83. package/dist/services/operate/maintenance.d.ts.map +1 -1
  84. package/dist/services/operate/maintenance.js +406 -46
  85. package/dist/services/operate/maintenance.js.map +1 -1
  86. package/dist/services/operate/migration.d.ts +68 -0
  87. package/dist/services/operate/migration.d.ts.map +1 -0
  88. package/dist/services/operate/migration.js +235 -0
  89. package/dist/services/operate/migration.js.map +1 -0
  90. package/dist/services/operate/mission-dispatch.d.ts +193 -0
  91. package/dist/services/operate/mission-dispatch.d.ts.map +1 -0
  92. package/dist/services/operate/mission-dispatch.js +444 -0
  93. package/dist/services/operate/mission-dispatch.js.map +1 -0
  94. package/dist/services/operate/projection-persistence.d.ts +6 -0
  95. package/dist/services/operate/projection-persistence.d.ts.map +1 -1
  96. package/dist/services/operate/projection-persistence.js +87 -11
  97. package/dist/services/operate/projection-persistence.js.map +1 -1
  98. package/dist/services/operate/projection.d.ts +26 -1
  99. package/dist/services/operate/projection.d.ts.map +1 -1
  100. package/dist/services/operate/projection.js +62 -0
  101. package/dist/services/operate/projection.js.map +1 -1
  102. package/dist/services/operate/protocol.d.ts +50 -3
  103. package/dist/services/operate/protocol.d.ts.map +1 -1
  104. package/dist/services/operate/protocol.js +57 -5
  105. package/dist/services/operate/protocol.js.map +1 -1
  106. package/dist/services/operate/read-only-providers.d.ts +37 -0
  107. package/dist/services/operate/read-only-providers.d.ts.map +1 -1
  108. package/dist/services/operate/read-only-providers.js +130 -0
  109. package/dist/services/operate/read-only-providers.js.map +1 -1
  110. package/dist/services/operate/reports.d.ts +22 -0
  111. package/dist/services/operate/reports.d.ts.map +1 -1
  112. package/dist/services/operate/reports.js +226 -1
  113. package/dist/services/operate/reports.js.map +1 -1
  114. package/dist/services/operate/routes.d.ts.map +1 -1
  115. package/dist/services/operate/routes.js +79 -5
  116. package/dist/services/operate/routes.js.map +1 -1
  117. package/dist/services/operate/types.d.ts +139 -4
  118. package/dist/services/operate/types.d.ts.map +1 -1
  119. package/dist/services/operate/types.js +13 -0
  120. package/dist/services/operate/types.js.map +1 -1
  121. package/dist/services/operate/workspace.d.ts +7 -0
  122. package/dist/services/operate/workspace.d.ts.map +1 -1
  123. package/dist/services/operate/workspace.js +14 -5
  124. package/dist/services/operate/workspace.js.map +1 -1
  125. package/dist/services/runtime-manager-service.d.ts.map +1 -1
  126. package/dist/services/runtime-manager-service.js +25 -5
  127. package/dist/services/runtime-manager-service.js.map +1 -1
  128. package/package.json +2 -2
@@ -1,5 +1,6 @@
1
- import { type AdvisorAdapter } from './advisors.js';
2
- import { type OperatingCycleManifest, type OperatingDataGap, type OperatingDecision, type OperatingEvidence, type OperatingEvidenceReadiness, type OperatingFinding, type OperatingProviderManifest, type OperatingRoleResult, type OperatingRoutePlan, type OperatingState } from './types.js';
1
+ import { type AdvisorAdapter, type AdvisorDispatchResult, type AdvisorOperatingContext } from './advisors.js';
2
+ import type { CitationResolutionContext } from './citation-resolution.js';
3
+ import { type OperatingConfig, type OperatingCycleManifest, type OperatingDataGap, type OperatingDecision, type OperatingEvidence, type OperatingEvidenceIndexItem, type OperatingEvidenceReadiness, type OperatingFinding, type OperatingMissionPacket, type OperatingMissionPacketState, type OperatingProviderManifest, type OperatingRoleId, type OperatingRoleResult, type OperatingRoutePlan, type OperatingSensitivity, type OperatingState, type OperatingWorkspaceManifest } from './types.js';
3
4
  export interface RunOperatingCycleInput {
4
5
  projectRoot: string;
5
6
  cycleId?: string;
@@ -43,12 +44,75 @@ export interface RunOperatingCycleResult {
43
44
  modelCalls: number;
44
45
  warnings: string[];
45
46
  nativeHandoff?: NativeAdvisorHandoff;
47
+ /**
48
+ * Per-role dispatch provenance from this run's advisor dispatch (FR4 / E-004).
49
+ * Carries the configured `dispatchMode` (registry default overridden by the
50
+ * persisted per-project `dispatchModeOverrides`) so a persisted override is
51
+ * observable end-to-end. Empty for preview/dry-run/native-handoff returns.
52
+ */
53
+ dispatchProvenance?: AdvisorDispatchResult['provenance'];
46
54
  }
55
+ /**
56
+ * Source a mission packet's non-evidence payload (FR1/E-001) from live cycle
57
+ * and workspace state at the point mission packets are constructed: the product
58
+ * charter and current goals, a prior-cycle summary with its open
59
+ * decisions/gaps/pending outcomes, planning and delivery status, the read roots
60
+ * declared for the index, and the revision pinned once at cycle start (recorded
61
+ * in the workspace manifest's control repository and threaded identically into
62
+ * every mission packet). Nothing here is invented: every value is read from the
63
+ * parsed charter context, the reduced state, the operating config, and the
64
+ * captured workspace manifest.
65
+ */
66
+ export declare function sourceOperatingMissionPacketState(input: {
67
+ cycleId: string;
68
+ config: OperatingConfig;
69
+ workspace: OperatingWorkspaceManifest;
70
+ context: AdvisorOperatingContext;
71
+ evidenceIndex: readonly OperatingEvidenceIndexItem[];
72
+ }): OperatingMissionPacketState;
73
+ /**
74
+ * Build the Protocol v1.3 mission packets (FR1/E-001) for a cycle from live
75
+ * state: derive the body-free evidence index from the collected snapshot,
76
+ * source the non-evidence payload once, and construct one digest-bound packet
77
+ * per requested role. Each packet is measured against its role's derived
78
+ * single-digit-KiB mission budget and fails closed with
79
+ * `E_OPERATE_MISSION_PACKET_BUDGET` naming the role before any dispatch. Pack
80
+ * mode (`createOperatingAdvisorPack`) is untouched.
81
+ */
82
+ export declare function buildOperatingMissionPackets(input: {
83
+ cycleId: string;
84
+ config: OperatingConfig;
85
+ workspace: OperatingWorkspaceManifest;
86
+ context: AdvisorOperatingContext;
87
+ evidence: OperatingEvidence;
88
+ roleIds?: OperatingRoleId[];
89
+ sensitivityCeiling?: OperatingSensitivity;
90
+ maxEvidenceItems?: number;
91
+ }): Promise<OperatingMissionPacket[]>;
47
92
  export declare function buildChairEvidence(evidence: OperatingEvidence, results: OperatingRoleResult[], now: string): OperatingEvidence;
48
93
  /**
49
94
  * Full evidence → advisors → deterministic consolidation lifecycle. All
50
95
  * mutations are serialized under the process-identity lease; preview and
51
96
  * dry-run never enter the mutating branch.
52
97
  */
98
+ /**
99
+ * FR3 / E-003 citation gate, invoked immediately before consolidation.
100
+ *
101
+ * Every recorded proposal that carries citations is resolved against the cycle's
102
+ * pinned revision through T-004's `enforceRecordedProposalCitations`. A proposal
103
+ * with ANY unresolvable citation is DROPPED — it never reaches
104
+ * `consolidateOperatingResults` — and exactly one `unresolvable-citation` gap is
105
+ * opened in its place. A proposal whose citations all resolve keeps its minted
106
+ * evidence IDs. Proposals carrying no citations (the v1.2 evidence-ref path) pass
107
+ * through untouched, so this is a byte-for-byte no-op for every non-citation
108
+ * cycle: the same `roleResults` reference is returned and no gap is emitted.
109
+ */
110
+ export declare function gateRecordedProposalCitations(input: {
111
+ roleResults: OperatingRoleResult[];
112
+ context: CitationResolutionContext;
113
+ }): Promise<{
114
+ roleResults: OperatingRoleResult[];
115
+ gaps: OperatingDataGap[];
116
+ }>;
53
117
  export declare function runOperatingCycle(input: RunOperatingCycleInput): Promise<RunOperatingCycleResult>;
54
118
  //# sourceMappingURL=engine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/services/operate/engine.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,cAAc,EAQpB,MAAM,eAAe,CAAC;AA0BvB,OAAO,EAIL,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EAEtB,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAC/B,KAAK,gBAAgB,EAErB,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EAEpB,MAAM,YAAY,CAAC;AAOpB,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,UAAU,MAAM,EAAE,CAAC;IACnC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,sBAAsB,CAAC;IAC9B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,SAAS,CAAC,EAAE,0BAA0B,CAAC;IACvC,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACtC;AA+HD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,mBAAmB,EAAE,EAC9B,GAAG,EAAE,MAAM,GACV,iBAAiB,CA6DnB;AAuPD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,sBAAsB,GAC5B,OAAO,CAAC,uBAAuB,CAAC,CAs4BlC"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/services/operate/engine.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAS7B,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAEV,yBAAyB,EAE1B,MAAM,0BAA0B,CAAC;AAgClC,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EAEtB,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAC/B,KAAK,0BAA0B,EAC/B,KAAK,gBAAgB,EAErB,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,EAC9B,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,0BAA0B,EAChC,MAAM,YAAY,CAAC;AAOpB,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,UAAU,MAAM,EAAE,CAAC;IACnC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,sBAAsB,CAAC;IAC9B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,SAAS,CAAC,EAAE,0BAA0B,CAAC;IACvC,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAC;CAC1D;AA+BD;;;;;;;;;;GAUG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,0BAA0B,CAAC;IACtC,OAAO,EAAE,uBAAuB,CAAC;IACjC,aAAa,EAAE,SAAS,0BAA0B,EAAE,CAAC;CACtD,GAAG,2BAA2B,CA6D9B;AAED;;;;;;;;GAQG;AACH,wBAAsB,4BAA4B,CAAC,KAAK,EAAE;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,0BAA0B,CAAC;IACtC,OAAO,EAAE,uBAAuB,CAAC;IACjC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,kBAAkB,CAAC,EAAE,oBAAoB,CAAC;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAwBpC;AAiHD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,mBAAmB,EAAE,EAC9B,GAAG,EAAE,MAAM,GACV,iBAAiB,CA6DnB;AAuPD;;;;GAIG;AACH;;;;;;;;;;;GAWG;AACH,wBAAsB,6BAA6B,CAAC,KAAK,EAAE;IACzD,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,OAAO,EAAE,yBAAyB,CAAC;CACpC,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC;IAAC,IAAI,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAAC,CAmC5E;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,sBAAsB,GAC5B,OAAO,CAAC,uBAAuB,CAAC,CAw8BlC"}
@@ -3,15 +3,17 @@ import { mkdir, readFile } from 'node:fs/promises';
3
3
  import path from 'node:path';
4
4
  import { OPENPLANR_VERSION } from '../../utils/package-version.js';
5
5
  import { loadConfig } from '../config-service.js';
6
- import { advisorFailureGaps, buildAdvisorOperatingContext, configuredAdvisorProviderPolicy, createConfiguredStructuredAdapter, createOfflineAdvisorAdapter, dispatchOperatingAdvisors, ensureOperatingProviderConsent, } from './advisors.js';
6
+ import { advisorFailureGaps, buildAdvisorOperatingContext, buildOperatingMissionPacket, configuredAdvisorProviderPolicy, createConfiguredStructuredAdapter, createOfflineAdvisorAdapter, dispatchOperatingAdvisors, ensureOperatingProviderConsent, } from './advisors.js';
7
+ import { recordOperatingCadenceRun } from './cadence.js';
7
8
  import { canonicalDigest, canonicalize } from './canonical.js';
8
- import { operatingProjectKey, validateOperatingConfiguration } from './config.js';
9
+ import { operatingProjectKey, readOperatingDispatchModeOverrides, validateOperatingConfiguration, } from './config.js';
9
10
  import { consolidateOperatingResults } from './consolidation.js';
10
11
  import { OperatingEventStore } from './event-store.js';
11
- import { collectOperatingEvidence, evidenceProjectionSources, unqualifiedCommercialEvidenceGaps, } from './evidence.js';
12
+ import { buildOperatingEvidenceIndex, collectOperatingEvidence, deriveOperatingDeclaredRoots, evidenceProjectionSources, unqualifiedCommercialEvidenceGaps, } from './evidence.js';
12
13
  import { OperatingEvidenceCache } from './evidence-cache.js';
13
14
  import { evaluateEvidenceReadiness } from './evidence-readiness.js';
14
15
  import { nextCycleId } from './ids.js';
16
+ import { enforceRecordedProposalCitations } from './interaction/action-service.js';
15
17
  import { applyJournalTransaction, prepareJournalTransaction, readJournal, rollbackJournalTransaction, } from './journal.js';
16
18
  import { reconcileOperatingDecisionDeadlines } from './lifecycle.js';
17
19
  import { withOperatingLock } from './lock-service.js';
@@ -20,7 +22,7 @@ import { persistOperatingProjections } from './projection-persistence.js';
20
22
  import { assertOperatingArtifact, loadOperatingProtocol } from './protocol.js';
21
23
  import { maximumSensitivity } from './redaction.js';
22
24
  import { createOperatingRoutePlan, nextOperatingSpecOrdinal } from './routes.js';
23
- import { OPERATE_PROTOCOL_VERSION, OPERATE_SCHEMA_VERSION, OperateError, } from './types.js';
25
+ import { OPERATE_MISSION_PROTOCOL_VERSION, OPERATE_PROTOCOL_VERSION, OPERATE_SCHEMA_VERSION, OperateError, } from './types.js';
24
26
  import { assertOperatingProject, refreshOperatingWorkspaceManifest, resolveOperatingPaths, } from './workspace.js';
25
27
  function normalizeFocus(focus) {
26
28
  const supported = new Set(['strategy', 'product', 'growth', 'operations', 'technology', 'all']);
@@ -32,6 +34,110 @@ function normalizeFocus(focus) {
32
34
  function loadJson(target) {
33
35
  return readFile(target, 'utf8').then((raw) => JSON.parse(raw));
34
36
  }
37
+ const MISSION_REVISION_PATTERN = /^[a-f0-9]{7,64}$/;
38
+ const MISSION_CYCLE_PATTERN = /^CYCLE-[0-9]{3,}$/;
39
+ const MISSION_DECISION_PATTERN = /^DEC-[0-9]{3,}$/;
40
+ const MISSION_GAP_PATTERN = /^GAP-[A-Za-z0-9._-]+$/;
41
+ const MISSION_OUTCOME_PATTERN = /^OUT-[0-9]{3,}$/;
42
+ function boundedMissionText(value, maximum, fallback) {
43
+ const text = value.replace(/\s+/g, ' ').trim().slice(0, maximum);
44
+ return text || fallback;
45
+ }
46
+ function missionOpenItemIds(items, pattern) {
47
+ return [...new Set(items.map((item) => item.id).filter((id) => pattern.test(id)))].sort();
48
+ }
49
+ /**
50
+ * Source a mission packet's non-evidence payload (FR1/E-001) from live cycle
51
+ * and workspace state at the point mission packets are constructed: the product
52
+ * charter and current goals, a prior-cycle summary with its open
53
+ * decisions/gaps/pending outcomes, planning and delivery status, the read roots
54
+ * declared for the index, and the revision pinned once at cycle start (recorded
55
+ * in the workspace manifest's control repository and threaded identically into
56
+ * every mission packet). Nothing here is invented: every value is read from the
57
+ * parsed charter context, the reduced state, the operating config, and the
58
+ * captured workspace manifest.
59
+ */
60
+ export function sourceOperatingMissionPacketState(input) {
61
+ const { context } = input;
62
+ const charter = context.charter;
63
+ const charterLine = [
64
+ charter.purpose && `Purpose: ${charter.purpose}`,
65
+ charter.stage && `Stage: ${charter.stage}`,
66
+ charter.businessModel && `Business model: ${charter.businessModel}`,
67
+ charter.idealCustomer && `Ideal customer: ${charter.idealCustomer}`,
68
+ ]
69
+ .filter(Boolean)
70
+ .join('. ');
71
+ const currentGoals = [...new Set(charter.goals.map((goal) => goal.trim()).filter(Boolean))]
72
+ .map((goal) => goal.slice(0, 512))
73
+ .sort();
74
+ const prior = context.priorCycle;
75
+ const priorSummaryText = prior
76
+ ? `Prior cycle ${prior.id} (${prior.state}, health ${prior.health ?? 'unknown'}) closed with ` +
77
+ `${prior.findings} finding(s), ${prior.decisions} decision(s), ${prior.gaps} gap(s), and ` +
78
+ `${prior.pendingOutcomes} pending outcome(s).`
79
+ : 'No prior operating cycle.';
80
+ const priorCycleSummary = {
81
+ ...(prior && MISSION_CYCLE_PATTERN.test(prior.id) ? { cycleId: prior.id } : {}),
82
+ summary: boundedMissionText(priorSummaryText, 8192, 'No prior operating cycle.'),
83
+ openDecisions: missionOpenItemIds(context.openDecisions, MISSION_DECISION_PATTERN),
84
+ openGaps: missionOpenItemIds(context.openGaps, MISSION_GAP_PATTERN),
85
+ pendingOutcomes: missionOpenItemIds(context.pendingOutcomes, MISSION_OUTCOME_PATTERN),
86
+ };
87
+ const planning = boundedMissionText(`${context.openDecisions.length} open decision(s); ${context.openGaps.length} open gap(s); ` +
88
+ `${context.pendingOutcomes.length} pending outcome(s).`, 2048, 'No open planning items.');
89
+ const delivery = boundedMissionText(prior
90
+ ? `Most recent cycle ${prior.id} is ${prior.state}.`
91
+ : 'No delivery cycle has completed yet.', 2048, 'No delivery status recorded.');
92
+ const pinnedRevision = input.workspace.controlRepository.pinnedRevision;
93
+ return {
94
+ cycleId: input.cycleId,
95
+ ...(pinnedRevision && MISSION_REVISION_PATTERN.test(pinnedRevision) ? { pinnedRevision } : {}),
96
+ charter: {
97
+ productCharter: boundedMissionText(charterLine, 8192, 'No product charter recorded.'),
98
+ currentGoals,
99
+ },
100
+ priorCycleSummary,
101
+ planningStatus: {
102
+ planningEngine: input.config.planningEngine,
103
+ planning,
104
+ delivery,
105
+ },
106
+ declaredRoots: deriveOperatingDeclaredRoots(input.evidenceIndex),
107
+ };
108
+ }
109
+ /**
110
+ * Build the Protocol v1.3 mission packets (FR1/E-001) for a cycle from live
111
+ * state: derive the body-free evidence index from the collected snapshot,
112
+ * source the non-evidence payload once, and construct one digest-bound packet
113
+ * per requested role. Each packet is measured against its role's derived
114
+ * single-digit-KiB mission budget and fails closed with
115
+ * `E_OPERATE_MISSION_PACKET_BUDGET` naming the role before any dispatch. Pack
116
+ * mode (`createOperatingAdvisorPack`) is untouched.
117
+ */
118
+ export async function buildOperatingMissionPackets(input) {
119
+ const evidenceIndex = buildOperatingEvidenceIndex(input.evidence, {
120
+ sensitivityCeiling: input.sensitivityCeiling,
121
+ });
122
+ const state = sourceOperatingMissionPacketState({
123
+ cycleId: input.cycleId,
124
+ config: input.config,
125
+ workspace: input.workspace,
126
+ context: input.context,
127
+ evidenceIndex,
128
+ });
129
+ const roleIds = input.roleIds ?? input.config.enabledRoles;
130
+ const packets = [];
131
+ for (const roleId of roleIds) {
132
+ packets.push(await buildOperatingMissionPacket({
133
+ roleId,
134
+ ...state,
135
+ evidenceIndex,
136
+ maxEvidenceItems: input.maxEvidenceItems,
137
+ }));
138
+ }
139
+ return packets;
140
+ }
35
141
  async function snapshotWorkspace(projectRoot, localRoot) {
36
142
  return refreshOperatingWorkspaceManifest(projectRoot, { localRoot });
37
143
  }
@@ -323,6 +429,52 @@ async function persistedCycleRoleResults(store, events, cycleId) {
323
429
  * mutations are serialized under the process-identity lease; preview and
324
430
  * dry-run never enter the mutating branch.
325
431
  */
432
+ /**
433
+ * FR3 / E-003 citation gate, invoked immediately before consolidation.
434
+ *
435
+ * Every recorded proposal that carries citations is resolved against the cycle's
436
+ * pinned revision through T-004's `enforceRecordedProposalCitations`. A proposal
437
+ * with ANY unresolvable citation is DROPPED — it never reaches
438
+ * `consolidateOperatingResults` — and exactly one `unresolvable-citation` gap is
439
+ * opened in its place. A proposal whose citations all resolve keeps its minted
440
+ * evidence IDs. Proposals carrying no citations (the v1.2 evidence-ref path) pass
441
+ * through untouched, so this is a byte-for-byte no-op for every non-citation
442
+ * cycle: the same `roleResults` reference is returned and no gap is emitted.
443
+ */
444
+ export async function gateRecordedProposalCitations(input) {
445
+ const bearing = [];
446
+ for (const result of input.roleResults) {
447
+ for (const proposal of result.proposals) {
448
+ const citations = proposal.citations;
449
+ if (Array.isArray(citations) && citations.length > 0) {
450
+ bearing.push({ proposalKey: proposal.proposalKey, citations });
451
+ }
452
+ }
453
+ }
454
+ if (bearing.length === 0)
455
+ return { roleResults: input.roleResults, gaps: [] };
456
+ const enforcement = await enforceRecordedProposalCitations(bearing, input.context);
457
+ const rejectedKeys = new Set(enforcement.rejected.map((entry) => entry.proposalKey));
458
+ const evidenceByKey = new Map(enforcement.accepted.map((entry) => [entry.proposal.proposalKey, entry.evidenceRefs]));
459
+ const roleResults = input.roleResults.map((result) => ({
460
+ ...result,
461
+ proposals: result.proposals
462
+ .filter((proposal) => !rejectedKeys.has(proposal.proposalKey))
463
+ .map((proposal) => {
464
+ const minted = evidenceByKey.get(proposal.proposalKey);
465
+ return minted && minted.length > 0
466
+ ? {
467
+ ...proposal,
468
+ evidenceRefs: [...new Set([...proposal.evidenceRefs, ...minted])].sort(),
469
+ }
470
+ : proposal;
471
+ }),
472
+ }));
473
+ // The unresolvable-citation gaps are Protocol v1.3 data gaps (they validate
474
+ // against the v1.3 operating-data-gap schema, which admits `category`). They
475
+ // are persisted alongside the cycle's other gaps by the committed path.
476
+ return { roleResults, gaps: enforcement.gaps };
477
+ }
326
478
  export async function runOperatingCycle(input) {
327
479
  const projectRoot = await assertOperatingProject(input.projectRoot);
328
480
  const config = await validateOperatingConfiguration(projectRoot);
@@ -330,6 +482,12 @@ export async function runOperatingCycle(input) {
330
482
  const initializedWorkspace = await loadJson(paths.workspace);
331
483
  await assertOperatingArtifact('operating-workspace-manifest', initializedWorkspace);
332
484
  const preferences = await readPreferences(projectRoot, input.localRoot);
485
+ // FR4 / E-004 fold-in: the live dispatch call site reads the persisted
486
+ // per-project dispatch-mode overrides once and threads them into every advisor
487
+ // dispatch below, so a persisted override reaches dispatch provenance.
488
+ const dispatchModeOverrides = await readOperatingDispatchModeOverrides(projectRoot, {
489
+ localRoot: input.localRoot,
490
+ });
333
491
  const store = new OperatingEventStore(projectRoot, { localRoot: input.localRoot });
334
492
  const now = input.now ?? new Date();
335
493
  const deadlineReconciliation = !input.preview && !input.dryRun
@@ -579,9 +737,11 @@ export async function runOperatingCycle(input) {
579
737
  adapter: await resolveAdapter(),
580
738
  depth,
581
739
  runtime: resolvedRuntime,
740
+ dispatchModeOverrides,
582
741
  })
583
742
  : {
584
743
  results: [],
744
+ provenance: [],
585
745
  modelCalls: 0,
586
746
  blocked: false,
587
747
  skipped: skippedMissingNonChair,
@@ -593,6 +753,7 @@ export async function runOperatingCycle(input) {
593
753
  ];
594
754
  let modelCalls = first.modelCalls;
595
755
  let blocked = first.blocked;
756
+ const dispatchProvenance = [...first.provenance];
596
757
  const skipped = [...first.skipped];
597
758
  const failed = [...first.failed];
598
759
  let consolidationEvidence = evidence;
@@ -648,6 +809,7 @@ export async function runOperatingCycle(input) {
648
809
  const chair = persistedChair
649
810
  ? {
650
811
  results: [persistedChair],
812
+ provenance: [],
651
813
  modelCalls: 0,
652
814
  blocked: false,
653
815
  skipped: [],
@@ -661,9 +823,11 @@ export async function runOperatingCycle(input) {
661
823
  adapter: await resolveAdapter(),
662
824
  depth,
663
825
  runtime: resolvedRuntime,
826
+ dispatchModeOverrides,
664
827
  });
665
828
  roleResults = [...roleResults, ...chair.results];
666
829
  modelCalls += chair.modelCalls;
830
+ dispatchProvenance.push(...chair.provenance);
667
831
  skipped.push(...chair.skipped);
668
832
  failed.push(...chair.failed);
669
833
  blocked ||= chair.blocked || chairReadiness.roles.some((role) => !role.modelCallAllowed);
@@ -672,9 +836,28 @@ export async function runOperatingCycle(input) {
672
836
  const technologyRiskFailed = failed.some((entry) => entry.roleId === 'technology-risk');
673
837
  const sensitiveRouteBlocked = containsSensitiveRouteProposal(roleResults) && (!technologyRiskReady || technologyRiskFailed);
674
838
  blocked ||= sensitiveRouteBlocked;
839
+ // FR3 / E-003: resolve every recorded proposal's citations against the cycle's
840
+ // pinned revision before consolidation. A proposal built on a fabricated,
841
+ // drifted, or uncommitted citation is dropped here and can never reach
842
+ // consolidation; its place is taken by a single unresolvable-citation gap.
843
+ const citationGate = await gateRecordedProposalCitations({
844
+ roleResults,
845
+ context: {
846
+ projectRoot,
847
+ cycleId: cycle.id,
848
+ descriptor: workspace.controlRepository,
849
+ cache: new OperatingEvidenceCache(resolveOperatingPaths(projectRoot, { localRoot: input.localRoot }).evidence, preferences.sensitivityCeiling),
850
+ owner: config.decisionOwner,
851
+ now,
852
+ },
853
+ });
854
+ // Only the gated proposals feed consolidation, so a proposal with an
855
+ // unresolvable citation can never become a finding/route. The raw advisor
856
+ // result stays intact as the audit record; the rejection is recorded as the
857
+ // opened unresolvable-citation gap threaded into `gaps` below.
675
858
  const consolidated = await consolidateOperatingResults({
676
859
  cycleId: cycle.id,
677
- results: roleResults,
860
+ results: citationGate.roleResults,
678
861
  evidence: consolidationEvidence,
679
862
  config,
680
863
  now: timestamp,
@@ -740,16 +923,23 @@ export async function runOperatingCycle(input) {
740
923
  roleResults,
741
924
  findings: [...reconciledFindings, ...reconciledParked],
742
925
  decisions: remapped.decisions,
743
- gaps: [...readinessGaps(readiness, config.decisionOwner, timestamp), ...remapped.gaps],
926
+ // Citation gaps bypass remapConsolidation (their IDs are digest-derived and
927
+ // already canonical) and are persisted alongside the cycle's other gaps.
928
+ gaps: [
929
+ ...readinessGaps(readiness, config.decisionOwner, timestamp),
930
+ ...remapped.gaps,
931
+ ...citationGate.gaps,
932
+ ],
744
933
  routes: [],
745
934
  provider,
746
935
  modelCalls,
747
936
  warnings,
937
+ dispatchProvenance,
748
938
  };
749
939
  };
750
940
  if (input.dryRun)
751
941
  return evaluate(false);
752
- return withOperatingLock(projectRoot, {
942
+ const cycleResult = await withOperatingLock(projectRoot, {
753
943
  projectKey: operatingProjectKey(projectRoot),
754
944
  expectedEventHead: initial.eventHead,
755
945
  currentEventHead: initial.eventHead,
@@ -1030,6 +1220,12 @@ export async function runOperatingCycle(input) {
1030
1220
  correlationId,
1031
1221
  evidenceRefs: route.actions.flatMap((action) => action.evidenceRefs),
1032
1222
  payload: { record: route },
1223
+ // A v1.3 (create-quick-task) route plan embedded in the event
1224
+ // payload stamps the event v1.3, whose schema accepts either
1225
+ // route-plan version; every v1.2 route keeps the frozen v1.2 event.
1226
+ ...(route.protocolVersion === OPERATE_MISSION_PROTOCOL_VERSION
1227
+ ? { protocolVersion: OPERATE_MISSION_PROTOCOL_VERSION }
1228
+ : {}),
1033
1229
  });
1034
1230
  head = appended.head;
1035
1231
  }
@@ -1119,5 +1315,21 @@ export async function runOperatingCycle(input) {
1119
1315
  throw error;
1120
1316
  }
1121
1317
  });
1318
+ // FR8 / E-008: persist the cadence `lastRunAt` marker once a committed cycle
1319
+ // reaches a terminal reviewable/blocked/closed state, so a later `operate
1320
+ // status` surfaces the pipeline's `nextDueAt` without re-running a cycle. Uses
1321
+ // the injected clock (`timestamp`), never a wall-clock read. Preview, dry-run,
1322
+ // and native-handoff returns have not completed a cycle and record nothing.
1323
+ if (!cycleResult.preview && !cycleResult.dryRun && !cycleResult.nativeHandoff) {
1324
+ const finalCycleState = cycleResult.state?.cycles.find((candidate) => candidate.id === cycle.id)?.state;
1325
+ if (finalCycleState && ['reviewable', 'blocked', 'closed'].includes(finalCycleState)) {
1326
+ await recordOperatingCadenceRun({
1327
+ projectRoot,
1328
+ localRoot: input.localRoot,
1329
+ runAt: timestamp,
1330
+ });
1331
+ }
1332
+ }
1333
+ return cycleResult;
1122
1334
  }
1123
1335
  //# sourceMappingURL=engine.js.map