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.
- package/dist/cli/commands/operate.d.ts +10 -1
- package/dist/cli/commands/operate.d.ts.map +1 -1
- package/dist/cli/commands/operate.js +240 -13
- package/dist/cli/commands/operate.js.map +1 -1
- package/dist/services/ai-service.d.ts +25 -0
- package/dist/services/ai-service.d.ts.map +1 -1
- package/dist/services/ai-service.js +38 -0
- package/dist/services/ai-service.js.map +1 -1
- package/dist/services/operate/advisors.d.ts +82 -1
- package/dist/services/operate/advisors.d.ts.map +1 -1
- package/dist/services/operate/advisors.js +469 -17
- package/dist/services/operate/advisors.js.map +1 -1
- package/dist/services/operate/artifacts.d.ts +27 -1
- package/dist/services/operate/artifacts.d.ts.map +1 -1
- package/dist/services/operate/artifacts.js +103 -1
- package/dist/services/operate/artifacts.js.map +1 -1
- package/dist/services/operate/cadence.d.ts +50 -0
- package/dist/services/operate/cadence.d.ts.map +1 -0
- package/dist/services/operate/cadence.js +56 -0
- package/dist/services/operate/cadence.js.map +1 -0
- package/dist/services/operate/citation-resolution.d.ts +101 -0
- package/dist/services/operate/citation-resolution.d.ts.map +1 -0
- package/dist/services/operate/citation-resolution.js +308 -0
- package/dist/services/operate/citation-resolution.js.map +1 -0
- package/dist/services/operate/config.d.ts +93 -1
- package/dist/services/operate/config.d.ts.map +1 -1
- package/dist/services/operate/config.js +199 -9
- package/dist/services/operate/config.js.map +1 -1
- package/dist/services/operate/decision-brief.d.ts +148 -0
- package/dist/services/operate/decision-brief.d.ts.map +1 -0
- package/dist/services/operate/decision-brief.js +194 -0
- package/dist/services/operate/decision-brief.js.map +1 -0
- package/dist/services/operate/doctor.d.ts.map +1 -1
- package/dist/services/operate/doctor.js +271 -3
- package/dist/services/operate/doctor.js.map +1 -1
- package/dist/services/operate/engine.d.ts +66 -2
- package/dist/services/operate/engine.d.ts.map +1 -1
- package/dist/services/operate/engine.js +219 -7
- package/dist/services/operate/engine.js.map +1 -1
- package/dist/services/operate/event-store.d.ts +35 -1
- package/dist/services/operate/event-store.d.ts.map +1 -1
- package/dist/services/operate/event-store.js +142 -29
- package/dist/services/operate/event-store.js.map +1 -1
- package/dist/services/operate/evidence-cache.d.ts +25 -1
- package/dist/services/operate/evidence-cache.d.ts.map +1 -1
- package/dist/services/operate/evidence-cache.js +62 -1
- package/dist/services/operate/evidence-cache.js.map +1 -1
- package/dist/services/operate/evidence.d.ts +20 -1
- package/dist/services/operate/evidence.d.ts.map +1 -1
- package/dist/services/operate/evidence.js +148 -0
- package/dist/services/operate/evidence.js.map +1 -1
- package/dist/services/operate/index.d.ts +2 -0
- package/dist/services/operate/index.d.ts.map +1 -1
- package/dist/services/operate/index.js +309 -46
- package/dist/services/operate/index.js.map +1 -1
- package/dist/services/operate/interaction/action-service.d.ts +17 -0
- package/dist/services/operate/interaction/action-service.d.ts.map +1 -1
- package/dist/services/operate/interaction/action-service.js +19 -0
- package/dist/services/operate/interaction/action-service.js.map +1 -1
- package/dist/services/operate/interaction/answer-service.d.ts +17 -0
- package/dist/services/operate/interaction/answer-service.d.ts.map +1 -1
- package/dist/services/operate/interaction/answer-service.js +49 -7
- package/dist/services/operate/interaction/answer-service.js.map +1 -1
- package/dist/services/operate/interaction/question-engine.d.ts.map +1 -1
- package/dist/services/operate/interaction/question-engine.js +9 -3
- package/dist/services/operate/interaction/question-engine.js.map +1 -1
- package/dist/services/operate/interaction/question-registry.d.ts +13 -0
- package/dist/services/operate/interaction/question-registry.d.ts.map +1 -1
- package/dist/services/operate/interaction/question-registry.js +116 -26
- package/dist/services/operate/interaction/question-registry.js.map +1 -1
- package/dist/services/operate/interaction/terminal-renderer.d.ts +12 -1
- package/dist/services/operate/interaction/terminal-renderer.d.ts.map +1 -1
- package/dist/services/operate/interaction/terminal-renderer.js +26 -15
- package/dist/services/operate/interaction/terminal-renderer.js.map +1 -1
- package/dist/services/operate/journal.d.ts.map +1 -1
- package/dist/services/operate/journal.js +11 -5
- package/dist/services/operate/journal.js.map +1 -1
- package/dist/services/operate/lifecycle.d.ts +8 -0
- package/dist/services/operate/lifecycle.d.ts.map +1 -1
- package/dist/services/operate/lifecycle.js +19 -1
- package/dist/services/operate/lifecycle.js.map +1 -1
- package/dist/services/operate/maintenance.d.ts +22 -0
- package/dist/services/operate/maintenance.d.ts.map +1 -1
- package/dist/services/operate/maintenance.js +406 -46
- package/dist/services/operate/maintenance.js.map +1 -1
- package/dist/services/operate/migration.d.ts +68 -0
- package/dist/services/operate/migration.d.ts.map +1 -0
- package/dist/services/operate/migration.js +235 -0
- package/dist/services/operate/migration.js.map +1 -0
- package/dist/services/operate/mission-dispatch.d.ts +193 -0
- package/dist/services/operate/mission-dispatch.d.ts.map +1 -0
- package/dist/services/operate/mission-dispatch.js +444 -0
- package/dist/services/operate/mission-dispatch.js.map +1 -0
- package/dist/services/operate/projection-persistence.d.ts +6 -0
- package/dist/services/operate/projection-persistence.d.ts.map +1 -1
- package/dist/services/operate/projection-persistence.js +87 -11
- package/dist/services/operate/projection-persistence.js.map +1 -1
- package/dist/services/operate/projection.d.ts +26 -1
- package/dist/services/operate/projection.d.ts.map +1 -1
- package/dist/services/operate/projection.js +62 -0
- package/dist/services/operate/projection.js.map +1 -1
- package/dist/services/operate/protocol.d.ts +50 -3
- package/dist/services/operate/protocol.d.ts.map +1 -1
- package/dist/services/operate/protocol.js +57 -5
- package/dist/services/operate/protocol.js.map +1 -1
- package/dist/services/operate/read-only-providers.d.ts +37 -0
- package/dist/services/operate/read-only-providers.d.ts.map +1 -1
- package/dist/services/operate/read-only-providers.js +130 -0
- package/dist/services/operate/read-only-providers.js.map +1 -1
- package/dist/services/operate/reports.d.ts +22 -0
- package/dist/services/operate/reports.d.ts.map +1 -1
- package/dist/services/operate/reports.js +226 -1
- package/dist/services/operate/reports.js.map +1 -1
- package/dist/services/operate/routes.d.ts.map +1 -1
- package/dist/services/operate/routes.js +79 -5
- package/dist/services/operate/routes.js.map +1 -1
- package/dist/services/operate/types.d.ts +139 -4
- package/dist/services/operate/types.d.ts.map +1 -1
- package/dist/services/operate/types.js +13 -0
- package/dist/services/operate/types.js.map +1 -1
- package/dist/services/operate/workspace.d.ts +7 -0
- package/dist/services/operate/workspace.d.ts.map +1 -1
- package/dist/services/operate/workspace.js +14 -5
- package/dist/services/operate/workspace.js.map +1 -1
- package/dist/services/runtime-manager-service.d.ts.map +1 -1
- package/dist/services/runtime-manager-service.js +25 -5
- package/dist/services/runtime-manager-service.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type AdvisorAdapter } from './advisors.js';
|
|
2
|
-
import
|
|
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,
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/services/operate/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -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
|
|
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
|
-
|
|
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
|