codex-workflow-v2 2.0.0-beta.12.10 → 2.0.0-beta.12.11

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.
@@ -2,7 +2,7 @@ import { appendFileSync, existsSync, lstatSync, readFileSync, readdirSync } from
2
2
  import { createHash } from 'node:crypto';
3
3
  import path from 'node:path';
4
4
  import { PROTOCOL_VERSION, STATE_SCHEMA_VERSION, } from './contracts.js';
5
- import { inspectDependencyProvenanceRecovery, } from './dependency-provenance.js';
5
+ import { inspectDependencyKnowledgeRefresh, inspectDependencyProvenanceRecovery, } from './dependency-provenance.js';
6
6
  import { inspectHistoricalStepProvenanceRecovery, omittedStepEvidenceCommits, } from './historical-step-provenance.js';
7
7
  import { renderBrief, renderPlan, renderResult } from './artifacts.js';
8
8
  import { assertDelegationCanAuthorize, hashDelegationPolicy, prepareDelegationGrantGate, } from './delegation.js';
@@ -719,6 +719,33 @@ export class WorkflowService {
719
719
  }
720
720
  const now = this.now();
721
721
  const timestamp = now.toISOString();
722
+ const actor = `agent:milestone-remediation:${milestone.id}`;
723
+ const storedKnowledgeMap = this.store.readKnowledgeMap(identity.projectId);
724
+ const scannedKnowledgeMap = scanProjectKnowledge(identity.repositoryRoot, identity.projectId, now);
725
+ const inspectedKnowledgeMap = inspectKnowledgeMap(storedKnowledgeMap, scannedKnowledgeMap);
726
+ let dependencyKnowledgeRefresh = null;
727
+ let refreshedKnowledgeMap = null;
728
+ if (inspectedKnowledgeMap.status !== 'active' || !inspectedKnowledgeMap.approval) {
729
+ dependencyKnowledgeRefresh = inspectDependencyKnowledgeRefresh(identity.repositoryRoot, milestone.baseBranch, storedKnowledgeMap, inspectedKnowledgeMap);
730
+ if (!dependencyKnowledgeRefresh.eligible) {
731
+ throw new WorkflowError('TRANSITION_BLOCKED', 'Audited remediation cannot bypass unrelated or unproven Project Knowledge drift.', { dependencyKnowledgeRefresh });
732
+ }
733
+ const reconciled = reconcileKnowledgeMap(storedKnowledgeMap, scannedKnowledgeMap);
734
+ const approved = applyKnowledgeSelections(reconciled, [], actor, now);
735
+ if (!approved.approval) {
736
+ throw new WorkflowError('STATE_CORRUPT', 'Dependency-only Knowledge refresh did not produce approval evidence.');
737
+ }
738
+ refreshedKnowledgeMap = {
739
+ ...approved,
740
+ revision: storedKnowledgeMap.revision + 2,
741
+ createdAt: storedKnowledgeMap.createdAt,
742
+ updatedAt: timestamp,
743
+ approval: {
744
+ ...approved.approval,
745
+ authorizationMode: 'corrective-derived',
746
+ },
747
+ };
748
+ }
722
749
  const remediationTaskId = createEntityId('TASK', now.getTime());
723
750
  const briefContent = renderBrief(discovery, title);
724
751
  const normalizedBriefContent = briefContent.endsWith('\n') ? briefContent : `${briefContent}\n`;
@@ -804,7 +831,6 @@ export class WorkflowService {
804
831
  const readCandidateTask = (taskId) => taskId === remediationTaskId
805
832
  ? remediationTask
806
833
  : this.store.readTask(identity.projectId, taskId);
807
- const actor = `agent:milestone-remediation:${milestone.id}`;
808
834
  const preparedCandidate = prepareMilestoneScopeChangeCandidate({
809
835
  milestone,
810
836
  plan,
@@ -856,6 +882,12 @@ export class WorkflowService {
856
882
  kind: 'audited-remediation-materialization',
857
883
  now,
858
884
  targets: [
885
+ ...(refreshedKnowledgeMap
886
+ ? [{
887
+ path: relative(path.join(projectRoot, 'knowledge-map.json')),
888
+ content: `${JSON.stringify(refreshedKnowledgeMap, null, 2)}\n`,
889
+ }]
890
+ : []),
859
891
  {
860
892
  path: relative(path.join(this.store.discoveryRoot(identity.projectId, discovery.id), 'state.json')),
861
893
  content: `${JSON.stringify(consumedDiscovery, null, 2)}\n`,
@@ -892,12 +924,17 @@ export class WorkflowService {
892
924
  const savedAuthorization = [...savedMilestone.authorizations]
893
925
  .reverse()
894
926
  .find((authorization) => authorization.kind === 'execution' && authorization.decision === 'approved');
927
+ const savedKnowledgeMap = this.store.readKnowledgeMap(identity.projectId);
895
928
  if (savedDiscovery.materializedEntityId !== remediationTaskId
896
929
  || savedRemediationTask.milestoneId !== milestone.id
897
930
  || !savedBlockedMembership?.dependsOnTaskIds?.includes(remediationTaskId)
898
931
  || savedRemediationMembership?.disposition !== 'required'
899
932
  || savedAuthorization?.authorizationMode !== 'corrective-derived'
900
933
  || savedMilestone.status !== 'active'
934
+ || (refreshedKnowledgeMap !== null
935
+ && (savedKnowledgeMap.revision !== refreshedKnowledgeMap.revision
936
+ || savedKnowledgeMap.status !== 'active'
937
+ || savedKnowledgeMap.approval?.authorizationMode !== 'corrective-derived'))
901
938
  || locks.inspect(blockedTask.id) !== null) {
902
939
  throw new WorkflowError('STATE_CORRUPT', 'Audited remediation transaction readback failed.');
903
940
  }
@@ -4394,6 +4431,37 @@ export class WorkflowService {
4394
4431
  ? this.nextForTaskWithDelegation(status.projectId, repositoryRoot, activeTask, null)
4395
4432
  : planRiskAuditRecovery
4396
4433
  ?? this.nextForTaskWithDelegation(status.projectId, repositoryRoot, activeTask, activePlanRiskAudit);
4434
+ const auditedRemediationNavigation = taskNext?.auditedRemediation;
4435
+ let auditedDependencyKnowledgeRefreshBlocked = null;
4436
+ if (auditedRemediationNavigation
4437
+ && activeTaskMilestone
4438
+ && ['discovery start', 'discovery update', 'milestone remediation-materialize'].includes(String(taskNext?.action))) {
4439
+ try {
4440
+ const storedKnowledgeMap = this.store.readKnowledgeMap(status.projectId);
4441
+ const inspectedKnowledgeMap = inspectCurrentKnowledgeMap();
4442
+ if (inspectedKnowledgeMap.status !== 'active' || !inspectedKnowledgeMap.approval) {
4443
+ const dependencyKnowledgeRefresh = inspectDependencyKnowledgeRefresh(repositoryRoot, activeTaskMilestone.baseBranch, storedKnowledgeMap, inspectedKnowledgeMap);
4444
+ if (dependencyKnowledgeRefresh.eligible) {
4445
+ return withAdoption(withMilestoneCancellation({
4446
+ ...taskNext,
4447
+ auditedRemediation: {
4448
+ ...auditedRemediationNavigation,
4449
+ dependencyKnowledgeRefresh: {
4450
+ ...dependencyKnowledgeRefresh,
4451
+ humanApprovalRequired: false,
4452
+ application: 'atomic-with-remediation-materialization',
4453
+ },
4454
+ },
4455
+ }));
4456
+ }
4457
+ auditedDependencyKnowledgeRefreshBlocked = dependencyKnowledgeRefresh;
4458
+ }
4459
+ }
4460
+ catch (error) {
4461
+ if (!(error instanceof WorkflowError) || error.code !== 'NOT_FOUND')
4462
+ throw error;
4463
+ }
4464
+ }
4397
4465
  // Active Step work must outrank Project Knowledge refresh/rebind. Both completion and
4398
4466
  // strict review are executable while context refresh correctly remains forbidden.
4399
4467
  const hardStop = taskNext?.action === 'task corrective-decision'
@@ -4488,6 +4556,15 @@ export class WorkflowService {
4488
4556
  },
4489
4557
  }
4490
4558
  : {}),
4559
+ ...(auditedDependencyKnowledgeRefreshBlocked
4560
+ ? {
4561
+ auditedDependencyKnowledgeRefreshBlocked: {
4562
+ ...auditedDependencyKnowledgeRefreshBlocked,
4563
+ humanApprovalRequired: true,
4564
+ requiredAction: 'Resolve or explicitly approve the non-dependency Project Knowledge drift.',
4565
+ },
4566
+ }
4567
+ : {}),
4491
4568
  }));
4492
4569
  }
4493
4570
  const knowledgeMapHash = hashKnowledgeMap(knowledgeMap);
@@ -5485,7 +5562,20 @@ export class WorkflowService {
5485
5562
  return readValidatedStopOverrideContextRebindIfApplicable(this.store, task, stepId, repositoryRoot)?.stopDecision.eventId ?? null;
5486
5563
  }
5487
5564
  taskHasTerminalCorrectiveDecision(task) {
5488
- return this.taskTerminalCorrectivePosture(task) !== null;
5565
+ try {
5566
+ return this.taskTerminalCorrectivePosture(task) !== null;
5567
+ }
5568
+ catch (error) {
5569
+ if (error instanceof WorkflowError
5570
+ && error.code === 'TRANSITION_BLOCKED'
5571
+ && (error.details.decision === 'stop-escalate' || error.details.decision === 'split-required')) {
5572
+ // A blocking Plan Risk Audit is not a guarded-Step terminal decision, but it
5573
+ // equally cannot own an atomic delegated context refresh. Treat it as
5574
+ // ineligible here so standalone Knowledge reconciliation remains executable.
5575
+ return true;
5576
+ }
5577
+ throw error;
5578
+ }
5489
5579
  }
5490
5580
  taskTerminalCorrectivePosture(task) {
5491
5581
  if (!task.planHash)