snipara-companion 2.1.1 → 2.3.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/README.md CHANGED
@@ -55,6 +55,8 @@ After the first impact check, keep the work resumable:
55
55
  npx -y snipara-companion workflow start --goal "ship auth hardening"
56
56
  npx -y snipara-companion workflow phase-start audit
57
57
  npx -y snipara-companion lead-plan --task "ship auth hardening" --changed-files src/auth/session.ts --proof "pnpm test auth" --acceptance "auth tests pass"
58
+ npx -y snipara-companion lead-plan --from-plan ./project-health-lead-plan.json --reconcile --changed-files src/auth/session.ts
59
+ npx -y snipara-companion lead-plan --from-plan ./project-health-lead-plan.json --json | jq '.engineeringLeadPlan.executionReceipts'
58
60
  npx -y snipara-companion workflow phase-commit audit --summary "mapped auth impact"
59
61
  npx -y snipara-companion handoff --summary "auth impact mapped" --next "run auth tests"
60
62
  ```
package/dist/index.d.ts CHANGED
@@ -2157,7 +2157,20 @@ declare const ENGINEERING_LEAD_STATUSES: readonly ["healthy", "watch", "risk", "
2157
2157
  declare const ENGINEERING_LEAD_POSTURES: readonly ["lead_ready", "lead_watch", "lead_blocked", "lead_cold_start"];
2158
2158
  declare const ENGINEERING_LEAD_WORKER_ROLES: readonly ["main_agent", "coding_worker", "test_worker", "reviewer", "documentation_worker", "human_approver"];
2159
2159
  declare const ENGINEERING_LEAD_ROUTING_MODES: readonly ["hold", "main_agent_execute", "explicit_handoff_ready", "needs_contract"];
2160
+ declare const ENGINEERING_LEAD_WORK_PACKAGE_STATUSES: readonly ["contracting", "ready_for_handoff", "executing", "verifying", "blocked", "closed", "unknown"];
2161
+ declare const ENGINEERING_LEAD_SUPERVISION_STATUSES: readonly ["on_track", "needs_review", "needs_replan", "blocked", "cold_start", "unknown"];
2162
+ declare const ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES: readonly ["pending_handoff", "handoff_ready", "executing", "verification_required", "blocked", "closed", "unknown"];
2163
+ declare const ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES: readonly ["handoff", "claim", "approval", "proof", "outcome", "brain_update"];
2160
2164
  type EngineeringLeadPlanSummary = ProjectIntelligenceEngineeringLeadPlanSummary;
2165
+ interface CompanionEngineeringLeadReconciliation {
2166
+ status: "on_track" | "needs_review" | "needs_replan" | "blocked";
2167
+ summary: string;
2168
+ replanRequired: boolean;
2169
+ reviewRequired: boolean;
2170
+ changedSignals: string[];
2171
+ recommendedActions: string[];
2172
+ reasonCodes: string[];
2173
+ }
2161
2174
  interface CompanionEngineeringLeadPlanReport {
2162
2175
  version: "snipara.companion_engineering_lead_plan.v1";
2163
2176
  generatedAt: string;
@@ -2176,6 +2189,7 @@ interface CompanionEngineeringLeadPlanReport {
2176
2189
  declaredRisks: string[];
2177
2190
  };
2178
2191
  localSignals: AgentReadinessLocalSignals;
2192
+ reconciliation?: CompanionEngineeringLeadReconciliation;
2179
2193
  suggestedCommands: string[];
2180
2194
  caveats: string[];
2181
2195
  }
@@ -2188,6 +2202,8 @@ interface LeadPlanCommandOptions {
2188
2202
  acceptance?: string[];
2189
2203
  risk?: string[];
2190
2204
  fromCockpit?: string;
2205
+ fromPlan?: string;
2206
+ reconcile?: boolean;
2191
2207
  dir?: string;
2192
2208
  output?: string;
2193
2209
  json?: boolean;
@@ -3505,4 +3521,4 @@ declare function buildOrchestratorHandoff(options: OrchestratorHandoffOptions):
3505
3521
  declare function buildAdaptiveWorkRoutingRecommendation(options: AdaptiveWorkRoutingOptions): AdaptiveWorkRoutingRecommendation;
3506
3522
  declare function writeOrchestratorHandoff(options: OrchestratorHandoffOptions): WrittenOrchestratorHandoff;
3507
3523
 
3508
- export { AUTOMATION_MANIFEST_RELATIVE_PATH, AutomationInstallConflictError, AutomationUnsupportedHookBundleError, COLLABORATION_STATE_RELATIVE_PATH, ENGINEERING_LEAD_POSTURES, ENGINEERING_LEAD_ROUTING_MODES, ENGINEERING_LEAD_STATUSES, ENGINEERING_LEAD_WORKER_ROLES, ORCHESTRATOR_HANDOFF_RELATIVE_PATH, TEAM_SYNC_STATE_RELATIVE_PATH, WORKFLOW_PLANS_RELATIVE_DIR, WORKFLOW_STATE_RELATIVE_PATH, agentReadinessAuditCommand, archiveInactiveTeamSyncWork, attachLocalContextPackReceipts, autoArchiveTeamSyncState, buildAdaptiveWorkRoutingRecommendation, buildAgentReadinessAuditReport, buildAgenticHandoffMarkdown, buildAgenticTimeline, buildAgenticWorkStatus, buildAutomationInstallPlan, buildCanonicalEvent, buildCodeHooksInstallPlan, buildCodePromotionResult, buildCodeStatusResult, buildCodeSyncResult, buildCollaborationActor, buildCollaborationGuardActionCards, buildCollaborationHooksInstallPlan, buildCompanionEngineeringLeadPlanReport, buildContextPackStats, buildEvalCaseArtifact, buildGeneratedWorkflowPlanDocument, buildHostedCodeOverlayUploadPayload, buildHostedGuardPayload, buildJournalCheckpointEntry, buildLocalCallersResult, buildLocalCodeOverlay, buildLocalContextPackReceipt, buildLocalContextPackReceipts, buildLocalImpactResult, buildLocalImportsResult, buildLocalNeighborsResult, buildLocalShortestPathResult, buildMemoryAudit, buildOnboardFolderManifest, buildOrchestratorHandoff, buildProjectIntelligenceBrief, buildProjectIntelligenceRun, buildProjectJudgmentCard, buildSessionBootstrapQuality, buildSyncDocumentsDryRun, buildTeamSyncHandoffRecord, buildTeamSyncStartWorkRecord, buildTeamSyncSummary, buildToolCallPayload, buildToolResultPayload, buildVerificationPlan, buildWorkflowImpactGate, buildWorkflowPhaseCommitSummary, buildWorkflowPlanScaffold, categoryFromGuardTag, classifyToolResult, cleanContextPacks, collaborationIdeStatusCommand, collectAgentReadinessLocalSignals, collectSyncDocuments, collectSyncDocumentsInput, compactHostedGuardResources, completeTeamSyncStateFromEvidence, completeTeamSyncWorkFromEvidence, contextPackCleanCommand, contextPackPackCommand, contextPackRetrieveCommand, contextPackStatsCommand, createClient, createEmptyCollaborationState, createEmptyTeamSyncState, createLocalQueryCache, deriveLocalCollaborationResourcesFromFiles, detectReleaseSurfacesFromFiles, detectRuntimeEnvironment, evalExportCommand, evalRunCommand, evaluateProjectPolicyGates, extractCommandFromToolInput, extractFilesFromToolInput, formatAgentReadinessAuditReport, formatCompanionEngineeringLeadPlanReport, formatOrchestratorRecommendationReason, formatPolicyGateDecision, formatProjectJudgmentCard, formatStuckGuardDecision, getAutomationManifestPath, getAutomationStatus, getCollaborationStatePath, getConfigPath, getContextPackStoragePaths, getLocalCodeOverlayCachePath, getLocalCodePromotionStatePath, getOrchestratorRecommendation, getPlanStepDisplayTitle, getStagedFiles, getStuckGuardInjection, getTeamSyncStatePath, ingestReferences, installAutomationBundle, leadPlanCommand, listProjectsForApiKey, loadAutomationManifest, loadCollaborationState, loadConfig, loadTeamSyncState, memoryAuditCommand, memoryCleanCandidatesCommand, memoryCompactCommand, memoryHealthCommand, memoryLocalCommand, normalizeCollaborationFiles, normalizeGuardTag, normalizeWorkflowPlanInput, packContext, parseCollaborationResources, projectIntelligenceBriefCommand, projectIntelligenceRunCommand, readLocalCodeOverlayCache, readLocalCodePromotionState, referencesIngestCommand, referencesScanCommand, resolveContextPackRecord, resolveFullWorkflowTokenBudget, resolveQueryFromToolInput, retrieveContextPack, runMemoryGuardCheck, saveCollaborationState, saveConfig, saveTeamSyncState, scanReferences, shouldSuggestOrchestratorForWorkflow, shouldSuggestRuntimeForWorkflow, summarizeLocalCodeOverlay, teamSyncSweepCommand, validatePlanResult, verifyCommand, writeLocalCodeOverlayCache, writeLocalCodePromotionState, writeOrchestratorHandoff };
3524
+ export { AUTOMATION_MANIFEST_RELATIVE_PATH, AutomationInstallConflictError, AutomationUnsupportedHookBundleError, COLLABORATION_STATE_RELATIVE_PATH, ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES, ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES, ENGINEERING_LEAD_POSTURES, ENGINEERING_LEAD_ROUTING_MODES, ENGINEERING_LEAD_STATUSES, ENGINEERING_LEAD_SUPERVISION_STATUSES, ENGINEERING_LEAD_WORKER_ROLES, ENGINEERING_LEAD_WORK_PACKAGE_STATUSES, ORCHESTRATOR_HANDOFF_RELATIVE_PATH, TEAM_SYNC_STATE_RELATIVE_PATH, WORKFLOW_PLANS_RELATIVE_DIR, WORKFLOW_STATE_RELATIVE_PATH, agentReadinessAuditCommand, archiveInactiveTeamSyncWork, attachLocalContextPackReceipts, autoArchiveTeamSyncState, buildAdaptiveWorkRoutingRecommendation, buildAgentReadinessAuditReport, buildAgenticHandoffMarkdown, buildAgenticTimeline, buildAgenticWorkStatus, buildAutomationInstallPlan, buildCanonicalEvent, buildCodeHooksInstallPlan, buildCodePromotionResult, buildCodeStatusResult, buildCodeSyncResult, buildCollaborationActor, buildCollaborationGuardActionCards, buildCollaborationHooksInstallPlan, buildCompanionEngineeringLeadPlanReport, buildContextPackStats, buildEvalCaseArtifact, buildGeneratedWorkflowPlanDocument, buildHostedCodeOverlayUploadPayload, buildHostedGuardPayload, buildJournalCheckpointEntry, buildLocalCallersResult, buildLocalCodeOverlay, buildLocalContextPackReceipt, buildLocalContextPackReceipts, buildLocalImpactResult, buildLocalImportsResult, buildLocalNeighborsResult, buildLocalShortestPathResult, buildMemoryAudit, buildOnboardFolderManifest, buildOrchestratorHandoff, buildProjectIntelligenceBrief, buildProjectIntelligenceRun, buildProjectJudgmentCard, buildSessionBootstrapQuality, buildSyncDocumentsDryRun, buildTeamSyncHandoffRecord, buildTeamSyncStartWorkRecord, buildTeamSyncSummary, buildToolCallPayload, buildToolResultPayload, buildVerificationPlan, buildWorkflowImpactGate, buildWorkflowPhaseCommitSummary, buildWorkflowPlanScaffold, categoryFromGuardTag, classifyToolResult, cleanContextPacks, collaborationIdeStatusCommand, collectAgentReadinessLocalSignals, collectSyncDocuments, collectSyncDocumentsInput, compactHostedGuardResources, completeTeamSyncStateFromEvidence, completeTeamSyncWorkFromEvidence, contextPackCleanCommand, contextPackPackCommand, contextPackRetrieveCommand, contextPackStatsCommand, createClient, createEmptyCollaborationState, createEmptyTeamSyncState, createLocalQueryCache, deriveLocalCollaborationResourcesFromFiles, detectReleaseSurfacesFromFiles, detectRuntimeEnvironment, evalExportCommand, evalRunCommand, evaluateProjectPolicyGates, extractCommandFromToolInput, extractFilesFromToolInput, formatAgentReadinessAuditReport, formatCompanionEngineeringLeadPlanReport, formatOrchestratorRecommendationReason, formatPolicyGateDecision, formatProjectJudgmentCard, formatStuckGuardDecision, getAutomationManifestPath, getAutomationStatus, getCollaborationStatePath, getConfigPath, getContextPackStoragePaths, getLocalCodeOverlayCachePath, getLocalCodePromotionStatePath, getOrchestratorRecommendation, getPlanStepDisplayTitle, getStagedFiles, getStuckGuardInjection, getTeamSyncStatePath, ingestReferences, installAutomationBundle, leadPlanCommand, listProjectsForApiKey, loadAutomationManifest, loadCollaborationState, loadConfig, loadTeamSyncState, memoryAuditCommand, memoryCleanCandidatesCommand, memoryCompactCommand, memoryHealthCommand, memoryLocalCommand, normalizeCollaborationFiles, normalizeGuardTag, normalizeWorkflowPlanInput, packContext, parseCollaborationResources, projectIntelligenceBriefCommand, projectIntelligenceRunCommand, readLocalCodeOverlayCache, readLocalCodePromotionState, referencesIngestCommand, referencesScanCommand, resolveContextPackRecord, resolveFullWorkflowTokenBudget, resolveQueryFromToolInput, retrieveContextPack, runMemoryGuardCheck, saveCollaborationState, saveConfig, saveTeamSyncState, scanReferences, shouldSuggestOrchestratorForWorkflow, shouldSuggestRuntimeForWorkflow, summarizeLocalCodeOverlay, teamSyncSweepCommand, validatePlanResult, verifyCommand, writeLocalCodeOverlayCache, writeLocalCodePromotionState, writeOrchestratorHandoff };
package/dist/index.js CHANGED
@@ -35,10 +35,14 @@ __export(index_exports, {
35
35
  AutomationInstallConflictError: () => AutomationInstallConflictError,
36
36
  AutomationUnsupportedHookBundleError: () => AutomationUnsupportedHookBundleError,
37
37
  COLLABORATION_STATE_RELATIVE_PATH: () => COLLABORATION_STATE_RELATIVE_PATH,
38
+ ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES: () => ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES,
39
+ ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES: () => ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES,
38
40
  ENGINEERING_LEAD_POSTURES: () => ENGINEERING_LEAD_POSTURES,
39
41
  ENGINEERING_LEAD_ROUTING_MODES: () => ENGINEERING_LEAD_ROUTING_MODES,
40
42
  ENGINEERING_LEAD_STATUSES: () => ENGINEERING_LEAD_STATUSES,
43
+ ENGINEERING_LEAD_SUPERVISION_STATUSES: () => ENGINEERING_LEAD_SUPERVISION_STATUSES,
41
44
  ENGINEERING_LEAD_WORKER_ROLES: () => ENGINEERING_LEAD_WORKER_ROLES,
45
+ ENGINEERING_LEAD_WORK_PACKAGE_STATUSES: () => ENGINEERING_LEAD_WORK_PACKAGE_STATUSES,
42
46
  ORCHESTRATOR_HANDOFF_RELATIVE_PATH: () => ORCHESTRATOR_HANDOFF_RELATIVE_PATH,
43
47
  TEAM_SYNC_STATE_RELATIVE_PATH: () => TEAM_SYNC_STATE_RELATIVE_PATH,
44
48
  WORKFLOW_PLANS_RELATIVE_DIR: () => WORKFLOW_PLANS_RELATIVE_DIR,
@@ -10459,6 +10463,7 @@ var path15 = __toESM(require("path"));
10459
10463
  // ../project-intelligence-contracts/src/index.ts
10460
10464
  var PROJECT_HEALTH_COCKPIT_STATUSES = ["healthy", "watch", "risk", "unknown"];
10461
10465
  var PROJECT_INTELLIGENCE_ENGINEERING_LEAD_PLAN_VERSION = "project-intelligence-engineering-lead-plan-v0";
10466
+ var PROJECT_INTELLIGENCE_ENGINEERING_LEAD_CONTRACT_VERSION = "engineering-lead-contract-v1";
10462
10467
  var PROJECT_INTELLIGENCE_ENGINEERING_LEAD_POSTURES = [
10463
10468
  "lead_ready",
10464
10469
  "lead_watch",
@@ -10479,12 +10484,50 @@ var PROJECT_INTELLIGENCE_ENGINEERING_LEAD_ROUTING_MODES = [
10479
10484
  "explicit_handoff_ready",
10480
10485
  "needs_contract"
10481
10486
  ];
10487
+ var PROJECT_INTELLIGENCE_ENGINEERING_LEAD_WORK_PACKAGE_STATUSES = [
10488
+ "contracting",
10489
+ "ready_for_handoff",
10490
+ "executing",
10491
+ "verifying",
10492
+ "blocked",
10493
+ "closed",
10494
+ "unknown"
10495
+ ];
10496
+ var PROJECT_INTELLIGENCE_ENGINEERING_LEAD_SUPERVISION_STATUSES = [
10497
+ "on_track",
10498
+ "needs_review",
10499
+ "needs_replan",
10500
+ "blocked",
10501
+ "cold_start",
10502
+ "unknown"
10503
+ ];
10504
+ var PROJECT_INTELLIGENCE_ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES = [
10505
+ "pending_handoff",
10506
+ "handoff_ready",
10507
+ "executing",
10508
+ "verification_required",
10509
+ "blocked",
10510
+ "closed",
10511
+ "unknown"
10512
+ ];
10513
+ var PROJECT_INTELLIGENCE_ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES = [
10514
+ "handoff",
10515
+ "claim",
10516
+ "approval",
10517
+ "proof",
10518
+ "outcome",
10519
+ "brain_update"
10520
+ ];
10482
10521
 
10483
10522
  // src/commands/lead-plan.ts
10484
10523
  var ENGINEERING_LEAD_STATUSES = PROJECT_HEALTH_COCKPIT_STATUSES;
10485
10524
  var ENGINEERING_LEAD_POSTURES = PROJECT_INTELLIGENCE_ENGINEERING_LEAD_POSTURES;
10486
10525
  var ENGINEERING_LEAD_WORKER_ROLES = PROJECT_INTELLIGENCE_ENGINEERING_LEAD_WORKER_ROLES;
10487
10526
  var ENGINEERING_LEAD_ROUTING_MODES = PROJECT_INTELLIGENCE_ENGINEERING_LEAD_ROUTING_MODES;
10527
+ var ENGINEERING_LEAD_WORK_PACKAGE_STATUSES = PROJECT_INTELLIGENCE_ENGINEERING_LEAD_WORK_PACKAGE_STATUSES;
10528
+ var ENGINEERING_LEAD_SUPERVISION_STATUSES = PROJECT_INTELLIGENCE_ENGINEERING_LEAD_SUPERVISION_STATUSES;
10529
+ var ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES = PROJECT_INTELLIGENCE_ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES;
10530
+ var ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES = PROJECT_INTELLIGENCE_ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES;
10488
10531
  var TARGET_LABELS = {
10489
10532
  codex: "Codex",
10490
10533
  "claude-code": "Claude Code",
@@ -10724,6 +10767,238 @@ function suggestedCommands2(input) {
10724
10767
  }
10725
10768
  return commands;
10726
10769
  }
10770
+ function localWorkPackageStatus(input) {
10771
+ if (input.posture === "lead_cold_start") return "unknown";
10772
+ if (input.posture === "lead_blocked") return "blocked";
10773
+ if (input.routingMode === "explicit_handoff_ready") return "ready_for_handoff";
10774
+ return "contracting";
10775
+ }
10776
+ function localWorkPackageReplanTriggers(input) {
10777
+ const triggers = /* @__PURE__ */ new Set();
10778
+ if (!input.task) {
10779
+ triggers.add("Define the task before treating this as a work package.");
10780
+ }
10781
+ if (input.changedFiles.length === 0) {
10782
+ triggers.add("Declare the write scope before delegation.");
10783
+ }
10784
+ if (input.acceptanceCriteria.length === 0) {
10785
+ triggers.add("Add acceptance criteria before worker handoff.");
10786
+ }
10787
+ if (input.proofGates.length === 0) {
10788
+ triggers.add("Add proof gates before worker handoff.");
10789
+ }
10790
+ if (!input.localSignals.workflow.present || input.localSignals.workflow.status !== "active") {
10791
+ triggers.add("Start or resume a Companion workflow before delegated execution.");
10792
+ }
10793
+ if (!input.localSignals.teamSync.present) {
10794
+ triggers.add("Record a Team Sync breadcrumb before handing work to another agent.");
10795
+ }
10796
+ if (input.declaredRisks.length > 0) {
10797
+ triggers.add("Review declared risks before promoting Brain update candidates.");
10798
+ }
10799
+ return Array.from(triggers);
10800
+ }
10801
+ function buildLocalWorkPackages(input) {
10802
+ if (!input.workPackageId) {
10803
+ return [];
10804
+ }
10805
+ const workPackageStatus = localWorkPackageStatus({
10806
+ posture: input.posture,
10807
+ routingMode: input.routingMode
10808
+ });
10809
+ const replanTriggers = localWorkPackageReplanTriggers(input);
10810
+ return [
10811
+ {
10812
+ id: input.workPackageId,
10813
+ title: input.workPackageTitle,
10814
+ status: workPackageStatus,
10815
+ health: input.status,
10816
+ owner: input.owner,
10817
+ dependencies: [],
10818
+ writeScope: input.changedFiles,
10819
+ acceptanceCriteria: input.acceptanceCriteria,
10820
+ proofRequired: input.proofGates,
10821
+ resultExpectation: input.routingMode === "explicit_handoff_ready" ? "Return changed files, proof receipts, residual risks, and candidate Project Brain updates." : "Return a bounded implementation summary only after the contract is complete.",
10822
+ nextAction: workPackageStatus === "ready_for_handoff" ? "Generate a handoff or adapter pack, then collect proof receipts before closure." : replanTriggers[0] ?? "Tighten the work package contract before handoff.",
10823
+ replanTriggers,
10824
+ evidence: input.evidence,
10825
+ reasonCodes: [
10826
+ `engineering_lead_work_package_${workPackageStatus}`,
10827
+ `engineering_lead_${input.posture}`,
10828
+ `routing_${input.routingMode}`
10829
+ ]
10830
+ }
10831
+ ];
10832
+ }
10833
+ function buildLocalSupervision(input) {
10834
+ const replanTriggers = Array.from(
10835
+ new Set(input.workPackages.flatMap((workPackage) => workPackage.replanTriggers))
10836
+ );
10837
+ const reviewRequired = input.posture === "lead_watch" || input.routingMode === "main_agent_execute" || input.workPackages.some((workPackage) => workPackage.replanTriggers.length > 0);
10838
+ const replanRequired = input.posture === "lead_blocked" || input.workPackages.some((workPackage) => workPackage.status === "blocked");
10839
+ const status = input.workPackages.length === 0 ? "cold_start" : replanRequired ? "blocked" : reviewRequired ? "needs_review" : "on_track";
10840
+ const readyWorkPackages = input.workPackages.filter(
10841
+ (workPackage) => workPackage.status === "ready_for_handoff"
10842
+ ).length;
10843
+ const blockedWorkPackages = input.workPackages.filter(
10844
+ (workPackage) => workPackage.status === "blocked"
10845
+ ).length;
10846
+ const receiptsRequired = /* @__PURE__ */ new Set();
10847
+ if (input.routingMode === "explicit_handoff_ready") {
10848
+ receiptsRequired.add("handoff_receipt");
10849
+ receiptsRequired.add("proof_receipt");
10850
+ }
10851
+ if (!input.localSignals.teamSync.present) {
10852
+ receiptsRequired.add("team_sync_handoff");
10853
+ }
10854
+ return {
10855
+ status,
10856
+ summary: status === "cold_start" ? "No local work package is available for supervision yet." : status === "blocked" ? "Local delegation is blocked until the worker contract has scope, acceptance, and proof." : status === "needs_review" ? "Local work is scoped, but workflow continuity or handoff readiness still needs review." : "Local work package is ready for advisory handoff supervision.",
10857
+ openWorkPackages: input.workPackages.length,
10858
+ blockedWorkPackages,
10859
+ readyWorkPackages,
10860
+ executingWorkPackages: 0,
10861
+ verifyingWorkPackages: 0,
10862
+ closedWorkPackages: 0,
10863
+ reviewRequired,
10864
+ replanRequired,
10865
+ nextCheck: status === "cold_start" ? "Define task scope, files, context refs, and proof gates." : status === "blocked" ? "Close contract gaps before delegated execution." : status === "needs_review" ? "Review workflow, Team Sync, risks, and proof gates before handoff." : "Collect proof and outcome receipts after handoff.",
10866
+ replanTriggers,
10867
+ receiptsRequired: Array.from(receiptsRequired),
10868
+ reasonCodes: [
10869
+ "engineering_lead_contract_v1_supervision",
10870
+ `engineering_lead_supervision_${status}`,
10871
+ `routing_${input.routingMode}`
10872
+ ]
10873
+ };
10874
+ }
10875
+ function executionReceiptRequiredStagesForRecommendation(recommendation) {
10876
+ const stages = /* @__PURE__ */ new Set(["handoff", "proof", "outcome"]);
10877
+ if (recommendation && recommendation.role !== "main_agent") {
10878
+ stages.add("claim");
10879
+ }
10880
+ if (recommendation?.contract.approvalRequired) {
10881
+ stages.add("approval");
10882
+ }
10883
+ if ((recommendation?.brainUpdateCandidates.length ?? 0) > 0) {
10884
+ stages.add("brain_update");
10885
+ }
10886
+ return ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES.filter((stage) => stages.has(stage));
10887
+ }
10888
+ function missingRequirementsForExecutionReceipt(input) {
10889
+ const completed = new Set(input.completedStages);
10890
+ const missing = /* @__PURE__ */ new Set();
10891
+ if (!input.workPackage.owner) missing.add("owner");
10892
+ if (input.workPackage.writeScope.length === 0) missing.add("write_scope");
10893
+ if (input.workPackage.acceptanceCriteria.length === 0) missing.add("acceptance_criteria");
10894
+ if (input.workPackage.proofRequired.length === 0) missing.add("proof_gate");
10895
+ if (input.requiredStages.includes("handoff") && !completed.has("handoff")) {
10896
+ missing.add("handoff_receipt");
10897
+ }
10898
+ if (input.requiredStages.includes("claim") && !completed.has("claim")) {
10899
+ missing.add("claim_id");
10900
+ }
10901
+ if (input.requiredStages.includes("approval") && !completed.has("approval")) {
10902
+ missing.add("approval_receipt");
10903
+ }
10904
+ if (input.requiredStages.includes("proof") && !completed.has("proof")) {
10905
+ missing.add("proof_receipt");
10906
+ }
10907
+ if (input.requiredStages.includes("outcome") && !completed.has("outcome")) {
10908
+ missing.add("outcome_receipt");
10909
+ }
10910
+ if (input.brainUpdateCandidates.length > 0 && input.requiredStages.includes("brain_update") && !completed.has("brain_update")) {
10911
+ missing.add("brain_update_receipt");
10912
+ }
10913
+ return Array.from(missing).sort();
10914
+ }
10915
+ function executionReceiptStatusFromWorkPackage(input) {
10916
+ if (input.workPackage.status === "blocked") return "blocked";
10917
+ if (input.workPackage.status === "closed" && input.requiredStages.every((stage) => input.completedStages.includes(stage))) {
10918
+ return "closed";
10919
+ }
10920
+ if (input.workPackage.status === "executing") return "executing";
10921
+ if (input.workPackage.status === "verifying") return "verification_required";
10922
+ if (input.workPackage.status === "ready_for_handoff") return "handoff_ready";
10923
+ if (input.missingRequirements.length > 0) return "pending_handoff";
10924
+ return "handoff_ready";
10925
+ }
10926
+ function executionReceiptNextAction(input) {
10927
+ if (input.status === "blocked") {
10928
+ return "Resolve the blocking receipt or proof issue before delegated execution.";
10929
+ }
10930
+ if (input.missingRequirements.includes("handoff_receipt")) {
10931
+ return "Create or attach the handoff receipt before treating this package as delegated.";
10932
+ }
10933
+ if (input.missingRequirements.includes("approval_receipt")) {
10934
+ return "Capture approval before delegated execution can proceed.";
10935
+ }
10936
+ if (input.missingRequirements.includes("proof_receipt")) {
10937
+ return "Attach proof receipts before closure.";
10938
+ }
10939
+ if (input.missingRequirements.includes("outcome_receipt")) {
10940
+ return "Attach an outcome or closure receipt before Brain promotion.";
10941
+ }
10942
+ if (input.missingRequirements.includes("brain_update_receipt")) {
10943
+ return "Record the reviewed Project Brain update receipt.";
10944
+ }
10945
+ if (input.status === "closed") {
10946
+ return "Keep the closed receipt linked for future routing calibration.";
10947
+ }
10948
+ if (input.status === "executing") {
10949
+ return "Monitor liveness and collect proof, outcome, and Brain-update receipts.";
10950
+ }
10951
+ if (input.status === "verification_required") {
10952
+ return "Verify proof and outcome receipts before closure.";
10953
+ }
10954
+ return "Issue the explicit handoff package and collect the required receipts.";
10955
+ }
10956
+ function buildExpectedExecutionReceipts(input) {
10957
+ const recommendationsByWorkPackageId = new Map(
10958
+ input.workerRecommendations.filter((recommendation) => recommendation.workPackageId).map((recommendation) => [recommendation.workPackageId, recommendation])
10959
+ );
10960
+ return input.workPackages.map((workPackage) => {
10961
+ const recommendation = recommendationsByWorkPackageId.get(workPackage.id);
10962
+ const requiredStages = executionReceiptRequiredStagesForRecommendation(recommendation);
10963
+ const completedStages = [];
10964
+ const brainUpdateCandidates2 = recommendation?.brainUpdateCandidates ?? [];
10965
+ const missingRequirements = missingRequirementsForExecutionReceipt({
10966
+ workPackage,
10967
+ requiredStages,
10968
+ completedStages,
10969
+ brainUpdateCandidates: brainUpdateCandidates2
10970
+ });
10971
+ const status = executionReceiptStatusFromWorkPackage({
10972
+ workPackage,
10973
+ requiredStages,
10974
+ completedStages,
10975
+ missingRequirements
10976
+ });
10977
+ return {
10978
+ id: `engineering-lead-receipt:${workPackage.id}`,
10979
+ workPackageId: workPackage.id,
10980
+ workPackageTitle: workPackage.title,
10981
+ status,
10982
+ requiredStages,
10983
+ completedStages,
10984
+ handoffReceiptId: null,
10985
+ claimId: null,
10986
+ htaskId: null,
10987
+ approvalReceiptId: null,
10988
+ proofReceiptIds: [],
10989
+ outcomeReceiptId: null,
10990
+ brainUpdateReceiptId: null,
10991
+ proofRequired: workPackage.proofRequired,
10992
+ proofExecuted: [],
10993
+ missingRequirements,
10994
+ nextAction: executionReceiptNextAction({ status, missingRequirements }),
10995
+ replanTriggers: workPackage.replanTriggers,
10996
+ brainUpdateCandidates: brainUpdateCandidates2,
10997
+ evidence: workPackage.evidence,
10998
+ reasonCodes: [`engineering_lead_execution_receipt_${status}`, ...workPackage.reasonCodes]
10999
+ };
11000
+ });
11001
+ }
10727
11002
  function buildLocalEngineeringLeadPlan(input) {
10728
11003
  const score = computeScore(input);
10729
11004
  const posture = postureForLocalPlan({ ...input, score });
@@ -10743,6 +11018,7 @@ function buildLocalEngineeringLeadPlan(input) {
10743
11018
  ].slice(0, 10);
10744
11019
  const brainCandidates = brainUpdateCandidates(input);
10745
11020
  const workPackageId = posture === "lead_cold_start" ? null : `lead-plan:${slug(workPackageTitle, "work-package")}`;
11021
+ const owner = posture === "lead_cold_start" ? "main_agent" : TARGET_LABELS[input.target];
10746
11022
  const worker = {
10747
11023
  id: workPackageId ?? "engineering-lead:cold-start",
10748
11024
  role,
@@ -10751,7 +11027,7 @@ function buildLocalEngineeringLeadPlan(input) {
10751
11027
  routingMode,
10752
11028
  workPackageId,
10753
11029
  workPackageTitle: posture === "lead_cold_start" ? null : workPackageTitle,
10754
- owner: posture === "lead_cold_start" ? "main_agent" : TARGET_LABELS[input.target],
11030
+ owner,
10755
11031
  rationale: routingMode === "explicit_handoff_ready" ? "Local scope, workflow continuity, acceptance, and proof gates are present for an explicit handoff." : routingMode === "main_agent_execute" ? "The contract is usable, but no active Companion workflow is present; keep execution with the main agent." : routingMode === "needs_contract" ? "Proof gates or acceptance criteria are incomplete; hold worker launch until the contract is explicit." : "No bounded work package exists yet; the main agent must define scope before delegation.",
10756
11032
  contract: {
10757
11033
  writeScope: input.changedFiles,
@@ -10770,8 +11046,34 @@ function buildLocalEngineeringLeadPlan(input) {
10770
11046
  `routing_${routingMode}`
10771
11047
  ]
10772
11048
  };
11049
+ const workPackages = buildLocalWorkPackages({
11050
+ workPackageId,
11051
+ workPackageTitle,
11052
+ status,
11053
+ posture,
11054
+ routingMode,
11055
+ owner,
11056
+ changedFiles: input.changedFiles,
11057
+ acceptanceCriteria: input.acceptanceCriteria,
11058
+ proofGates: input.proofGates,
11059
+ evidence,
11060
+ declaredRisks: input.declaredRisks,
11061
+ localSignals: input.localSignals,
11062
+ task: input.task
11063
+ });
11064
+ const supervision = buildLocalSupervision({
11065
+ posture,
11066
+ routingMode,
11067
+ workPackages,
11068
+ localSignals: input.localSignals
11069
+ });
11070
+ const executionReceipts = buildExpectedExecutionReceipts({
11071
+ workPackages,
11072
+ workerRecommendations: [worker]
11073
+ });
10773
11074
  return {
10774
11075
  version: PROJECT_INTELLIGENCE_ENGINEERING_LEAD_PLAN_VERSION,
11076
+ contractVersion: PROJECT_INTELLIGENCE_ENGINEERING_LEAD_CONTRACT_VERSION,
10775
11077
  posture,
10776
11078
  status,
10777
11079
  score,
@@ -10780,6 +11082,9 @@ function buildLocalEngineeringLeadPlan(input) {
10780
11082
  nextAction: routingMode === "explicit_handoff_ready" ? "Generate a handoff or adapter pack, then require proof receipts before closure." : routingMode === "main_agent_execute" ? "Start or resume a Companion workflow before assigning this to another worker." : routingMode === "needs_contract" ? "Define proof gates and acceptance criteria before worker handoff." : "Define task scope, files, context refs, and proof gates.",
10781
11083
  workersSpawned: 0,
10782
11084
  failClosedFallback: "main_agent",
11085
+ workPackages,
11086
+ supervision,
11087
+ executionReceipts,
10783
11088
  workerRecommendations: [worker],
10784
11089
  proofGates: input.proofGates,
10785
11090
  brainUpdateActions: brainCandidates,
@@ -10787,6 +11092,7 @@ function buildLocalEngineeringLeadPlan(input) {
10787
11092
  { label: "Work packages", value: workPackageId ? 1 : 0 },
10788
11093
  { label: "Ready packages", value: routingMode === "explicit_handoff_ready" ? 1 : 0 },
10789
11094
  { label: "Blocked packages", value: posture === "lead_blocked" ? 1 : 0 },
11095
+ { label: "Supervision", value: supervision.status },
10790
11096
  { label: "Context refs", value: input.contextRefs.length },
10791
11097
  { label: "Proof gates", value: input.proofGates.length },
10792
11098
  { label: "Acceptance criteria", value: input.acceptanceCriteria.length },
@@ -10859,12 +11165,235 @@ function normalizeWorkerRecommendation(value, index) {
10859
11165
  ]
10860
11166
  };
10861
11167
  }
11168
+ function normalizeWorkPackage(value, index) {
11169
+ const status = cockpitEnumValue(
11170
+ "work_package_status",
11171
+ ENGINEERING_LEAD_WORK_PACKAGE_STATUSES,
11172
+ value.status,
11173
+ "unknown"
11174
+ );
11175
+ const health = cockpitEnumValue(
11176
+ "work_package_health",
11177
+ ENGINEERING_LEAD_STATUSES,
11178
+ value.health,
11179
+ "unknown"
11180
+ );
11181
+ const reasonCodes = [
11182
+ .../* @__PURE__ */ new Set([
11183
+ ...stringList(value.reasonCodes),
11184
+ ...compactReasonCodes([status.droppedReasonCode, health.droppedReasonCode])
11185
+ ])
11186
+ ];
11187
+ return {
11188
+ id: stringValue3(value.id) ?? `work-package:${index + 1}`,
11189
+ title: stringValue3(value.title) ?? `Imported work package ${index + 1}`,
11190
+ status: status.value,
11191
+ health: health.value,
11192
+ owner: stringValue3(value.owner) ?? null,
11193
+ dependencies: stringList(value.dependencies),
11194
+ writeScope: stringList(value.writeScope),
11195
+ acceptanceCriteria: stringList(value.acceptanceCriteria),
11196
+ proofRequired: stringList(value.proofRequired),
11197
+ resultExpectation: stringValue3(value.resultExpectation) ?? "Return proof receipts, residual risks, and candidate Project Brain updates.",
11198
+ nextAction: stringValue3(value.nextAction) ?? "Review imported work package before creating handoffs.",
11199
+ replanTriggers: stringList(value.replanTriggers),
11200
+ evidence: normalizeEvidence(value.evidence),
11201
+ reasonCodes
11202
+ };
11203
+ }
11204
+ function normalizeReceiptStages(field, value) {
11205
+ if (!Array.isArray(value)) {
11206
+ return { stages: [], reasonCodes: [] };
11207
+ }
11208
+ const stages = [];
11209
+ const reasonCodes = /* @__PURE__ */ new Set();
11210
+ for (const item of value) {
11211
+ const stage = cockpitEnumValue(
11212
+ field,
11213
+ ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES,
11214
+ item,
11215
+ "handoff"
11216
+ );
11217
+ if (stage.droppedReasonCode) {
11218
+ reasonCodes.add(stage.droppedReasonCode);
11219
+ continue;
11220
+ }
11221
+ if (!stages.includes(stage.value)) {
11222
+ stages.push(stage.value);
11223
+ }
11224
+ }
11225
+ return { stages, reasonCodes: Array.from(reasonCodes) };
11226
+ }
11227
+ function normalizeExecutionReceipt(value, index, workPackages, workerRecommendations) {
11228
+ const workPackageId = stringValue3(value.workPackageId) ?? workPackages[index]?.id ?? `work-package:${index + 1}`;
11229
+ const workPackage = workPackages.find((candidate) => candidate.id === workPackageId);
11230
+ const recommendation = workerRecommendations.find(
11231
+ (candidate) => candidate.workPackageId === workPackageId
11232
+ );
11233
+ const fallbackRequiredStages = executionReceiptRequiredStagesForRecommendation(recommendation);
11234
+ const requiredStages = normalizeReceiptStages("execution_receipt_stage", value.requiredStages);
11235
+ const completedStages = normalizeReceiptStages("execution_receipt_stage", value.completedStages);
11236
+ const normalizedRequiredStages = requiredStages.stages.length > 0 ? requiredStages.stages : fallbackRequiredStages;
11237
+ const normalizedCompletedStages = completedStages.stages.filter(
11238
+ (stage) => normalizedRequiredStages.includes(stage)
11239
+ );
11240
+ const brainUpdateCandidates2 = stringList(value.brainUpdateCandidates).length > 0 ? stringList(value.brainUpdateCandidates) : recommendation?.brainUpdateCandidates ?? [];
11241
+ const derivedMissing = workPackage && missingRequirementsForExecutionReceipt({
11242
+ workPackage,
11243
+ requiredStages: normalizedRequiredStages,
11244
+ completedStages: normalizedCompletedStages,
11245
+ brainUpdateCandidates: brainUpdateCandidates2
11246
+ });
11247
+ const missingRequirements = stringList(value.missingRequirements).length > 0 ? stringList(value.missingRequirements) : derivedMissing ?? [];
11248
+ const fallbackStatus = workPackage ? executionReceiptStatusFromWorkPackage({
11249
+ workPackage,
11250
+ requiredStages: normalizedRequiredStages,
11251
+ completedStages: normalizedCompletedStages,
11252
+ missingRequirements
11253
+ }) : "pending_handoff";
11254
+ const status = cockpitEnumValue(
11255
+ "execution_receipt_status",
11256
+ ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES,
11257
+ value.status,
11258
+ fallbackStatus
11259
+ );
11260
+ return {
11261
+ id: stringValue3(value.id) ?? `engineering-lead-receipt:${workPackageId}`,
11262
+ workPackageId,
11263
+ workPackageTitle: stringValue3(value.workPackageTitle) ?? workPackage?.title ?? `Imported work package ${index + 1}`,
11264
+ status: status.value,
11265
+ requiredStages: normalizedRequiredStages,
11266
+ completedStages: normalizedCompletedStages,
11267
+ handoffReceiptId: stringValue3(value.handoffReceiptId) ?? null,
11268
+ claimId: stringValue3(value.claimId) ?? null,
11269
+ htaskId: stringValue3(value.htaskId) ?? null,
11270
+ approvalReceiptId: stringValue3(value.approvalReceiptId) ?? null,
11271
+ proofReceiptIds: stringList(value.proofReceiptIds),
11272
+ outcomeReceiptId: stringValue3(value.outcomeReceiptId) ?? null,
11273
+ brainUpdateReceiptId: stringValue3(value.brainUpdateReceiptId) ?? null,
11274
+ proofRequired: stringList(value.proofRequired).length > 0 ? stringList(value.proofRequired) : workPackage?.proofRequired ?? [],
11275
+ proofExecuted: stringList(value.proofExecuted),
11276
+ missingRequirements,
11277
+ nextAction: stringValue3(value.nextAction) ?? executionReceiptNextAction({ status: status.value, missingRequirements }),
11278
+ replanTriggers: stringList(value.replanTriggers).length > 0 ? stringList(value.replanTriggers) : workPackage?.replanTriggers ?? [],
11279
+ brainUpdateCandidates: brainUpdateCandidates2,
11280
+ evidence: normalizeEvidence(value.evidence).length > 0 ? normalizeEvidence(value.evidence) : workPackage?.evidence ?? [],
11281
+ reasonCodes: [
11282
+ .../* @__PURE__ */ new Set([
11283
+ ...stringList(value.reasonCodes),
11284
+ ...compactReasonCodes([status.droppedReasonCode]),
11285
+ ...requiredStages.reasonCodes,
11286
+ ...completedStages.reasonCodes
11287
+ ])
11288
+ ]
11289
+ };
11290
+ }
11291
+ function summarizeSupervisionFromWorkPackages(workPackages) {
11292
+ const blockedWorkPackages = workPackages.filter(
11293
+ (workPackage) => workPackage.status === "blocked"
11294
+ ).length;
11295
+ const readyWorkPackages = workPackages.filter(
11296
+ (workPackage) => workPackage.status === "ready_for_handoff"
11297
+ ).length;
11298
+ const executingWorkPackages = workPackages.filter(
11299
+ (workPackage) => workPackage.status === "executing"
11300
+ ).length;
11301
+ const verifyingWorkPackages = workPackages.filter(
11302
+ (workPackage) => workPackage.status === "verifying"
11303
+ ).length;
11304
+ const closedWorkPackages = workPackages.filter(
11305
+ (workPackage) => workPackage.status === "closed"
11306
+ ).length;
11307
+ const replanTriggers = Array.from(
11308
+ new Set(workPackages.flatMap((workPackage) => workPackage.replanTriggers))
11309
+ );
11310
+ const reviewRequired = workPackages.some((workPackage) => workPackage.health === "watch") || workPackages.some((workPackage) => workPackage.replanTriggers.length > 0);
11311
+ const replanRequired = blockedWorkPackages > 0;
11312
+ const status = workPackages.length === 0 ? "cold_start" : replanRequired ? "needs_replan" : reviewRequired ? "needs_review" : "on_track";
11313
+ return {
11314
+ status,
11315
+ summary: workPackages.length === 0 ? "No imported work packages are available for supervision." : replanRequired ? `${blockedWorkPackages} imported work package(s) require replan.` : reviewRequired ? "Imported work packages need review before delegated execution." : "Imported work packages are on track for advisory supervision.",
11316
+ openWorkPackages: Math.max(0, workPackages.length - closedWorkPackages),
11317
+ blockedWorkPackages,
11318
+ readyWorkPackages,
11319
+ executingWorkPackages,
11320
+ verifyingWorkPackages,
11321
+ closedWorkPackages,
11322
+ reviewRequired,
11323
+ replanRequired,
11324
+ nextCheck: status === "cold_start" ? "Import or create bounded work packages." : status === "needs_replan" ? "Replan blocked imported packages before handoff." : status === "needs_review" ? "Review imported package contracts and receipts." : "Collect proof and outcome receipts after handoff.",
11325
+ replanTriggers,
11326
+ receiptsRequired: [],
11327
+ reasonCodes: [
11328
+ "engineering_lead_contract_v1_supervision",
11329
+ `engineering_lead_supervision_${status}`
11330
+ ]
11331
+ };
11332
+ }
11333
+ function normalizeSupervision(value, workPackages) {
11334
+ if (!isRecord5(value)) {
11335
+ return summarizeSupervisionFromWorkPackages(workPackages);
11336
+ }
11337
+ const fallback = summarizeSupervisionFromWorkPackages(workPackages);
11338
+ const fallbackStatus = fallback.status === "on_track" ? "needs_review" : fallback.status;
11339
+ const status = cockpitEnumValue(
11340
+ "supervision_status",
11341
+ ENGINEERING_LEAD_SUPERVISION_STATUSES,
11342
+ value.status,
11343
+ fallbackStatus
11344
+ );
11345
+ return {
11346
+ status: status.value,
11347
+ summary: stringValue3(value.summary) ?? fallback.summary,
11348
+ openWorkPackages: Math.max(
11349
+ 0,
11350
+ Math.round(numberValue2(value.openWorkPackages, fallback.openWorkPackages))
11351
+ ),
11352
+ blockedWorkPackages: Math.max(
11353
+ 0,
11354
+ Math.round(numberValue2(value.blockedWorkPackages, fallback.blockedWorkPackages))
11355
+ ),
11356
+ readyWorkPackages: Math.max(
11357
+ 0,
11358
+ Math.round(numberValue2(value.readyWorkPackages, fallback.readyWorkPackages))
11359
+ ),
11360
+ executingWorkPackages: Math.max(
11361
+ 0,
11362
+ Math.round(numberValue2(value.executingWorkPackages, fallback.executingWorkPackages))
11363
+ ),
11364
+ verifyingWorkPackages: Math.max(
11365
+ 0,
11366
+ Math.round(numberValue2(value.verifyingWorkPackages, fallback.verifyingWorkPackages))
11367
+ ),
11368
+ closedWorkPackages: Math.max(
11369
+ 0,
11370
+ Math.round(numberValue2(value.closedWorkPackages, fallback.closedWorkPackages))
11371
+ ),
11372
+ reviewRequired: booleanValue(value.reviewRequired, fallback.reviewRequired),
11373
+ replanRequired: booleanValue(value.replanRequired, fallback.replanRequired),
11374
+ nextCheck: stringValue3(value.nextCheck) ?? fallback.nextCheck,
11375
+ replanTriggers: stringList(value.replanTriggers),
11376
+ receiptsRequired: stringList(value.receiptsRequired),
11377
+ reasonCodes: [
11378
+ .../* @__PURE__ */ new Set([
11379
+ ...stringList(value.reasonCodes),
11380
+ ...compactReasonCodes([status.droppedReasonCode])
11381
+ ])
11382
+ ]
11383
+ };
11384
+ }
10862
11385
  function normalizeCockpitPlan(cockpit) {
10863
11386
  const rawPlan = isRecord5(cockpit.engineeringLeadPlan) ? cockpit.engineeringLeadPlan : cockpit;
10864
11387
  const score = Math.round(numberValue2(rawPlan.score, 0));
10865
11388
  const workerRecommendations = recordList2(rawPlan.workerRecommendations).map(
10866
11389
  normalizeWorkerRecommendation
10867
11390
  );
11391
+ const workPackages = recordList2(rawPlan.workPackages).map(normalizeWorkPackage);
11392
+ const supervision = normalizeSupervision(rawPlan.supervision, workPackages);
11393
+ const rawExecutionReceipts = recordList2(rawPlan.executionReceipts);
11394
+ const executionReceipts = rawExecutionReceipts.length > 0 ? rawExecutionReceipts.map(
11395
+ (receipt, index) => normalizeExecutionReceipt(receipt, index, workPackages, workerRecommendations)
11396
+ ) : buildExpectedExecutionReceipts({ workPackages, workerRecommendations });
10868
11397
  const posture = cockpitEnumValue(
10869
11398
  "posture",
10870
11399
  ENGINEERING_LEAD_POSTURES,
@@ -10880,8 +11409,18 @@ function normalizeCockpitPlan(cockpit) {
10880
11409
  const workerDroppedReasonCodes = workerRecommendations.flatMap(
10881
11410
  (worker) => worker.reasonCodes.filter((code2) => code2.startsWith("companion_dropped_unknown_"))
10882
11411
  );
11412
+ const workPackageDroppedReasonCodes = workPackages.flatMap(
11413
+ (workPackage) => workPackage.reasonCodes.filter((code2) => code2.startsWith("companion_dropped_unknown_"))
11414
+ );
11415
+ const supervisionDroppedReasonCodes = supervision.reasonCodes.filter(
11416
+ (code2) => code2.startsWith("companion_dropped_unknown_")
11417
+ );
11418
+ const executionReceiptDroppedReasonCodes = executionReceipts.flatMap(
11419
+ (receipt) => receipt.reasonCodes.filter((code2) => code2.startsWith("companion_dropped_unknown_"))
11420
+ );
10883
11421
  return {
10884
11422
  version: PROJECT_INTELLIGENCE_ENGINEERING_LEAD_PLAN_VERSION,
11423
+ contractVersion: PROJECT_INTELLIGENCE_ENGINEERING_LEAD_CONTRACT_VERSION,
10885
11424
  posture: posture.value,
10886
11425
  status: status.value,
10887
11426
  score,
@@ -10890,6 +11429,9 @@ function normalizeCockpitPlan(cockpit) {
10890
11429
  nextAction: stringValue3(rawPlan.nextAction) ?? "Review the imported cockpit plan before creating worker handoffs.",
10891
11430
  workersSpawned: 0,
10892
11431
  failClosedFallback: "main_agent",
11432
+ workPackages,
11433
+ supervision,
11434
+ executionReceipts,
10893
11435
  workerRecommendations,
10894
11436
  proofGates: stringList(rawPlan.proofGates),
10895
11437
  brainUpdateActions: stringList(rawPlan.brainUpdateActions),
@@ -10910,11 +11452,135 @@ function normalizeCockpitPlan(cockpit) {
10910
11452
  "companion_imported_project_health_lead_plan",
10911
11453
  ...compactReasonCodes([posture.droppedReasonCode, status.droppedReasonCode]),
10912
11454
  ...stringList(rawPlan.reasonCodes),
10913
- ...workerDroppedReasonCodes
11455
+ ...workerDroppedReasonCodes,
11456
+ ...workPackageDroppedReasonCodes,
11457
+ ...supervisionDroppedReasonCodes,
11458
+ ...executionReceiptDroppedReasonCodes
10914
11459
  ])
10915
11460
  ]
10916
11461
  };
10917
11462
  }
11463
+ function scopeSetForPlan(plan) {
11464
+ return /* @__PURE__ */ new Set([
11465
+ ...plan.workPackages.flatMap((workPackage) => workPackage.writeScope),
11466
+ ...plan.workerRecommendations.flatMap((worker) => worker.contract.writeScope)
11467
+ ]);
11468
+ }
11469
+ function reconcileEngineeringLeadPlan(input) {
11470
+ const changedSignals = /* @__PURE__ */ new Set();
11471
+ const recommendedActions = /* @__PURE__ */ new Set();
11472
+ const reasonCodes = /* @__PURE__ */ new Set(["companion_lead_plan_reconciled"]);
11473
+ const plannedScope = scopeSetForPlan(input.plan);
11474
+ const outOfScopeFiles = input.changedFiles.filter((file) => !plannedScope.has(file));
11475
+ const executionReceipts = input.plan.executionReceipts ?? [];
11476
+ if (input.plan.workPackages.length === 0) {
11477
+ changedSignals.add("no_imported_work_packages");
11478
+ recommendedActions.add("Create or import bounded work packages before delegation.");
11479
+ reasonCodes.add("companion_reconcile_no_work_packages");
11480
+ }
11481
+ if (outOfScopeFiles.length > 0) {
11482
+ changedSignals.add(`out_of_scope_files:${outOfScopeFiles.join(",")}`);
11483
+ recommendedActions.add(
11484
+ "Replan because current changed files are outside the imported write scope."
11485
+ );
11486
+ reasonCodes.add("companion_reconcile_scope_changed");
11487
+ }
11488
+ if (!input.localSignals.workflow.present || input.localSignals.workflow.status !== "active") {
11489
+ changedSignals.add("workflow_not_active");
11490
+ recommendedActions.add("Start or resume a Companion workflow before delegated execution.");
11491
+ reasonCodes.add("companion_reconcile_workflow_not_active");
11492
+ }
11493
+ if (!input.localSignals.teamSync.present) {
11494
+ changedSignals.add("team_sync_missing");
11495
+ recommendedActions.add(
11496
+ "Record Team Sync start-work or handoff before assigning work to another agent."
11497
+ );
11498
+ reasonCodes.add("companion_reconcile_team_sync_missing");
11499
+ }
11500
+ if (input.proofGates.length === 0 && input.plan.proofGates.length === 0) {
11501
+ changedSignals.add("proof_gates_missing");
11502
+ recommendedActions.add("Define proof gates before worker handoff.");
11503
+ reasonCodes.add("companion_reconcile_missing_proof");
11504
+ }
11505
+ if (input.acceptanceCriteria.length === 0) {
11506
+ const importedAcceptance = input.plan.workPackages.some(
11507
+ (workPackage) => workPackage.acceptanceCriteria.length > 0
11508
+ );
11509
+ if (!importedAcceptance) {
11510
+ changedSignals.add("acceptance_criteria_missing");
11511
+ recommendedActions.add("Define acceptance criteria before worker handoff.");
11512
+ reasonCodes.add("companion_reconcile_missing_acceptance");
11513
+ }
11514
+ }
11515
+ if (input.declaredRisks.length > 0) {
11516
+ changedSignals.add("declared_risks_present");
11517
+ recommendedActions.add("Review declared risks before promoting Brain update candidates.");
11518
+ reasonCodes.add("companion_reconcile_declared_risks");
11519
+ }
11520
+ for (const trigger of input.plan.supervision.replanTriggers) {
11521
+ recommendedActions.add(trigger);
11522
+ }
11523
+ for (const receipt of executionReceipts) {
11524
+ if (receipt.status === "blocked") {
11525
+ changedSignals.add(`blocked_execution_receipt:${receipt.workPackageId}`);
11526
+ recommendedActions.add(receipt.nextAction);
11527
+ reasonCodes.add("companion_reconcile_execution_receipt_blocked");
11528
+ }
11529
+ if (receipt.missingRequirements.length > 0) {
11530
+ changedSignals.add(
11531
+ `execution_receipt_missing:${receipt.workPackageId}:${receipt.missingRequirements.join(",")}`
11532
+ );
11533
+ recommendedActions.add(
11534
+ `Attach missing execution receipt requirement(s) for ${receipt.workPackageTitle}: ${receipt.missingRequirements.join(", ")}.`
11535
+ );
11536
+ reasonCodes.add("companion_reconcile_execution_receipt_missing_requirements");
11537
+ }
11538
+ }
11539
+ const blocked = input.plan.supervision.status === "blocked" || input.plan.workPackages.some((workPackage) => workPackage.status === "blocked") || executionReceipts.some((receipt) => receipt.status === "blocked");
11540
+ const replanRequired = blocked || input.plan.supervision.replanRequired || outOfScopeFiles.length > 0 || !input.localSignals.workflow.present || input.localSignals.workflow.status !== "active";
11541
+ const reviewRequired = replanRequired || input.plan.supervision.reviewRequired || executionReceipts.some((receipt) => receipt.missingRequirements.length > 0) || !input.localSignals.teamSync.present || input.declaredRisks.length > 0;
11542
+ const status = blocked ? "blocked" : replanRequired ? "needs_replan" : reviewRequired ? "needs_review" : "on_track";
11543
+ return {
11544
+ status,
11545
+ summary: status === "blocked" ? "Imported lead plan has blocked work or blocked supervision signals." : status === "needs_replan" ? "Imported lead plan no longer matches current local execution signals." : status === "needs_review" ? "Imported lead plan is usable, but local continuity or risk review is required." : "Imported lead plan matches current local execution signals.",
11546
+ replanRequired,
11547
+ reviewRequired,
11548
+ changedSignals: Array.from(changedSignals),
11549
+ recommendedActions: Array.from(recommendedActions),
11550
+ reasonCodes: Array.from(reasonCodes)
11551
+ };
11552
+ }
11553
+ function applyReconciliationToPlan(plan, reconciliation) {
11554
+ if (!reconciliation.replanRequired && !reconciliation.reviewRequired) {
11555
+ return {
11556
+ ...plan,
11557
+ reasonCodes: [.../* @__PURE__ */ new Set([...plan.reasonCodes, ...reconciliation.reasonCodes])]
11558
+ };
11559
+ }
11560
+ const supervisionStatus = reconciliation.status === "blocked" ? "blocked" : reconciliation.status === "needs_replan" ? "needs_replan" : "needs_review";
11561
+ return {
11562
+ ...plan,
11563
+ nextAction: reconciliation.recommendedActions[0] ?? plan.nextAction,
11564
+ supervision: {
11565
+ ...plan.supervision,
11566
+ status: supervisionStatus,
11567
+ summary: reconciliation.summary,
11568
+ reviewRequired: reconciliation.reviewRequired,
11569
+ replanRequired: reconciliation.replanRequired,
11570
+ replanTriggers: [
11571
+ .../* @__PURE__ */ new Set([...plan.supervision.replanTriggers, ...reconciliation.recommendedActions])
11572
+ ],
11573
+ reasonCodes: [.../* @__PURE__ */ new Set([...plan.supervision.reasonCodes, ...reconciliation.reasonCodes])]
11574
+ },
11575
+ caveats: [
11576
+ .../* @__PURE__ */ new Set([
11577
+ ...plan.caveats,
11578
+ "This plan was reconciled against current local Companion signals; replan signals are advisory and fail-closed."
11579
+ ])
11580
+ ],
11581
+ reasonCodes: [.../* @__PURE__ */ new Set([...plan.reasonCodes, ...reconciliation.reasonCodes])]
11582
+ };
11583
+ }
10918
11584
  function readJsonFile3(filePath) {
10919
11585
  const parsed = JSON.parse(fs16.readFileSync(path15.resolve(filePath), "utf8"));
10920
11586
  if (!isRecord5(parsed)) {
@@ -10932,8 +11598,8 @@ function buildCompanionEngineeringLeadPlanReport(options = {}) {
10932
11598
  const proofGates = unique3(options.proof);
10933
11599
  const acceptanceCriteria = unique3(options.acceptance);
10934
11600
  const declaredRisks = unique3(options.risk);
10935
- const cockpit = options.cockpit ?? (options.fromCockpit ? readJsonFile3(options.fromCockpit) : void 0);
10936
- const engineeringLeadPlan = cockpit ? normalizeCockpitPlan(cockpit) : buildLocalEngineeringLeadPlan({
11601
+ const cockpit = options.cockpit ?? (options.fromCockpit || options.fromPlan ? readJsonFile3(options.fromCockpit ?? options.fromPlan ?? "") : void 0);
11602
+ const importedPlan = cockpit ? normalizeCockpitPlan(cockpit) : buildLocalEngineeringLeadPlan({
10937
11603
  target,
10938
11604
  task,
10939
11605
  changedFiles,
@@ -10943,6 +11609,15 @@ function buildCompanionEngineeringLeadPlanReport(options = {}) {
10943
11609
  declaredRisks,
10944
11610
  localSignals
10945
11611
  });
11612
+ const reconciliation = options.reconcile && cockpit ? reconcileEngineeringLeadPlan({
11613
+ plan: importedPlan,
11614
+ changedFiles,
11615
+ proofGates,
11616
+ acceptanceCriteria,
11617
+ declaredRisks,
11618
+ localSignals
11619
+ }) : void 0;
11620
+ const engineeringLeadPlan = reconciliation ? applyReconciliationToPlan(importedPlan, reconciliation) : importedPlan;
10946
11621
  return {
10947
11622
  version: "snipara.companion_engineering_lead_plan.v1",
10948
11623
  generatedAt: (options.now ?? /* @__PURE__ */ new Date()).toISOString(),
@@ -10961,6 +11636,7 @@ function buildCompanionEngineeringLeadPlanReport(options = {}) {
10961
11636
  declaredRisks
10962
11637
  },
10963
11638
  localSignals,
11639
+ ...reconciliation ? { reconciliation } : {},
10964
11640
  suggestedCommands: suggestedCommands2({
10965
11641
  target,
10966
11642
  task,
@@ -10980,6 +11656,7 @@ function formatList2(values, empty = "none") {
10980
11656
  }
10981
11657
  function formatCompanionEngineeringLeadPlanReport(report) {
10982
11658
  const plan = report.engineeringLeadPlan;
11659
+ const executionReceipts = plan.executionReceipts ?? [];
10983
11660
  const lines = [];
10984
11661
  lines.push("Companion Engineering Lead Plan");
10985
11662
  lines.push(`Generated: ${report.generatedAt}`);
@@ -10996,6 +11673,56 @@ function formatCompanionEngineeringLeadPlanReport(report) {
10996
11673
  lines.push(`Headline: ${plan.headline}`);
10997
11674
  lines.push(`Next action: ${plan.nextAction}`);
10998
11675
  lines.push("");
11676
+ lines.push("Supervision");
11677
+ lines.push(`Status: ${plan.supervision.status}`);
11678
+ lines.push(`Summary: ${plan.supervision.summary}`);
11679
+ lines.push(`Review required: ${plan.supervision.reviewRequired}`);
11680
+ lines.push(`Replan required: ${plan.supervision.replanRequired}`);
11681
+ lines.push(`Next check: ${plan.supervision.nextCheck}`);
11682
+ lines.push(`Replan triggers: ${formatList2(plan.supervision.replanTriggers)}`);
11683
+ lines.push("");
11684
+ if (report.reconciliation) {
11685
+ lines.push("Reconciliation");
11686
+ lines.push(`Status: ${report.reconciliation.status}`);
11687
+ lines.push(`Summary: ${report.reconciliation.summary}`);
11688
+ lines.push(`Changed signals: ${formatList2(report.reconciliation.changedSignals)}`);
11689
+ lines.push(`Recommended actions: ${formatList2(report.reconciliation.recommendedActions)}`);
11690
+ lines.push("");
11691
+ }
11692
+ lines.push("Work Packages");
11693
+ if (plan.workPackages.length === 0) {
11694
+ lines.push("- none");
11695
+ } else {
11696
+ for (const workPackage of plan.workPackages) {
11697
+ lines.push(`- [${workPackage.health}] ${workPackage.title} (${workPackage.status})`);
11698
+ if (workPackage.owner) {
11699
+ lines.push(` owner: ${workPackage.owner}`);
11700
+ }
11701
+ lines.push(` next: ${workPackage.nextAction}`);
11702
+ lines.push(` scope: ${formatList2(workPackage.writeScope)}`);
11703
+ lines.push(` proof: ${formatList2(workPackage.proofRequired)}`);
11704
+ }
11705
+ }
11706
+ lines.push("");
11707
+ lines.push("Execution Receipts");
11708
+ if (executionReceipts.length === 0) {
11709
+ lines.push("- none");
11710
+ } else {
11711
+ for (const receipt of executionReceipts) {
11712
+ lines.push(`- [${receipt.status}] ${receipt.workPackageTitle}`);
11713
+ lines.push(` package: ${receipt.workPackageId}`);
11714
+ lines.push(` required stages: ${formatList2(receipt.requiredStages)}`);
11715
+ lines.push(` completed stages: ${formatList2(receipt.completedStages)}`);
11716
+ lines.push(` handoff receipt: ${receipt.handoffReceiptId ?? "missing"}`);
11717
+ lines.push(` claim: ${receipt.claimId ?? "missing"}`);
11718
+ lines.push(` approval receipt: ${receipt.approvalReceiptId ?? "missing"}`);
11719
+ lines.push(` outcome receipt: ${receipt.outcomeReceiptId ?? "missing"}`);
11720
+ lines.push(` brain update receipt: ${receipt.brainUpdateReceiptId ?? "missing"}`);
11721
+ lines.push(` missing: ${formatList2(receipt.missingRequirements)}`);
11722
+ lines.push(` next: ${receipt.nextAction}`);
11723
+ }
11724
+ }
11725
+ lines.push("");
10999
11726
  lines.push("Worker Recommendations");
11000
11727
  for (const worker of plan.workerRecommendations) {
11001
11728
  lines.push(`- [${worker.status}] ${worker.label} (${worker.role}, ${worker.routingMode})`);
@@ -23365,7 +24092,7 @@ program.command("agent-readiness").description("Audit whether a repo/task is rea
23365
24092
  program.command("lead-plan").description("Create a fail-closed Companion Engineering Lead Plan").option("--task <task>", "Current task or work package summary").option(
23366
24093
  "--target <target>",
23367
24094
  "Target agent or ADE (codex|claude-code|cursor|orca|windsurf|custom)"
23368
- ).option("--changed-files <files...>", "Changed or relevant files").option("--context <refs...>", "Context references, decisions, docs, or source facts").option("--proof <proof...>", "Required proof gates or verification evidence").option("--acceptance <criteria...>", "Acceptance criteria for the delegated work").option("--risk <risks...>", "Known risks or caveats").option("--from-cockpit <file>", "Read a Project Health cockpit JSON export").option("-d, --dir <directory>", "Project directory (default: current)").option("-o, --output <file>", "Write Markdown or JSON report").option("--json", "Print raw JSON").action(async (options) => {
24095
+ ).option("--changed-files <files...>", "Changed or relevant files").option("--context <refs...>", "Context references, decisions, docs, or source facts").option("--proof <proof...>", "Required proof gates or verification evidence").option("--acceptance <criteria...>", "Acceptance criteria for the delegated work").option("--risk <risks...>", "Known risks or caveats").option("--from-cockpit <file>", "Read a Project Health cockpit JSON export").option("--from-plan <file>", "Read a Companion or Project Health Engineering Lead Plan JSON").option("--reconcile", "Reconcile an imported lead plan against current local Companion signals").option("-d, --dir <directory>", "Project directory (default: current)").option("-o, --output <file>", "Write Markdown or JSON report").option("--json", "Print raw JSON").action(async (options) => {
23369
24096
  await leadPlanCommand({
23370
24097
  task: options.task,
23371
24098
  target: options.target,
@@ -23375,6 +24102,8 @@ program.command("lead-plan").description("Create a fail-closed Companion Enginee
23375
24102
  acceptance: options.acceptance,
23376
24103
  risk: options.risk,
23377
24104
  fromCockpit: options.fromCockpit,
24105
+ fromPlan: options.fromPlan,
24106
+ reconcile: Boolean(options.reconcile),
23378
24107
  dir: options.dir,
23379
24108
  output: options.output,
23380
24109
  json: Boolean(options.json)
@@ -24883,10 +25612,14 @@ if (require.main === module) {
24883
25612
  AutomationInstallConflictError,
24884
25613
  AutomationUnsupportedHookBundleError,
24885
25614
  COLLABORATION_STATE_RELATIVE_PATH,
25615
+ ENGINEERING_LEAD_EXECUTION_RECEIPT_STAGES,
25616
+ ENGINEERING_LEAD_EXECUTION_RECEIPT_STATUSES,
24886
25617
  ENGINEERING_LEAD_POSTURES,
24887
25618
  ENGINEERING_LEAD_ROUTING_MODES,
24888
25619
  ENGINEERING_LEAD_STATUSES,
25620
+ ENGINEERING_LEAD_SUPERVISION_STATUSES,
24889
25621
  ENGINEERING_LEAD_WORKER_ROLES,
25622
+ ENGINEERING_LEAD_WORK_PACKAGE_STATUSES,
24890
25623
  ORCHESTRATOR_HANDOFF_RELATIVE_PATH,
24891
25624
  TEAM_SYNC_STATE_RELATIVE_PATH,
24892
25625
  WORKFLOW_PLANS_RELATIVE_DIR,
@@ -309,13 +309,22 @@ snipara-companion lead-plan \
309
309
 
310
310
  The command reads local workflow state, Team Sync, project instructions, and
311
311
  explicit inputs. The output uses the same lead-plan vocabulary as Project
312
- Health: posture, score, routing mode, bounded worker contract, proof gates,
313
- candidate Project Brain updates, `workersSpawned: 0`, and `main_agent` fallback.
314
-
315
- Use `--from-cockpit <file>` when Project Health has exported a cockpit JSON
316
- artifact and Companion only needs to normalize it into Markdown or JSON for
317
- handoff. This is still advisory and fail-closed: the command does not approve
318
- work, execute proof gates, or spawn workers.
312
+ Health: posture, score, routing mode, bounded worker contract, supervised work
313
+ packages, supervision/replan status, proof gates, candidate Project Brain
314
+ updates, `workersSpawned: 0`, and `main_agent` fallback.
315
+
316
+ Engineering Lead Execution Receipts V1 adds `executionReceipts` to that plan.
317
+ Each receipt records the expected handoff, claim, approval, proof, outcome, and
318
+ Project Brain update stages for a work package, plus missing requirements and
319
+ next actions. Unknown future receipt enum values fail closed with
320
+ `companion_dropped_unknown_execution_receipt_*` reason codes.
321
+
322
+ Use `--from-cockpit <file>` or `--from-plan <file>` when Project Health has
323
+ exported a cockpit/lead-plan JSON artifact and Companion only needs to normalize
324
+ it into Markdown or JSON for handoff. Add `--reconcile` to compare the imported
325
+ plan against current local workflow, Team Sync, proof, acceptance, and file
326
+ scope signals. This is still advisory and fail-closed: the command does not
327
+ approve work, execute proof gates, or spawn workers.
319
328
 
320
329
  ## Verification Plans
321
330
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snipara-companion",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "Local-first CLI that asks your repo what breaks before an AI coding agent edits it.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {