// ../core/src/codeWorkHandoff/types.ts
var CODE_WORK_HANDOFF_SCHEMA_VERSION = 1;
var CODE_WORK_HANDOFF_KIND = "code_work_handoff";
var CODE_WORK_HANDOFF_TOKEN_ESTIMATE_VERSION = "char-div-4-v1";
// ../core/src/codeWorkHandoff/builders.ts
function defaultGeneratedAt() {
  return Date.now();
}
var REPORT_ONLY_GUARDRAILS = {
  reportOnly: true,
  advisoryOnly: true,
  noAuthority: true,
  noProviderCalls: true,
  noNetworkCalls: true,
  noFilesystemSourceScan: true,
  noSessionMutation: true,
  noWrites: true,
  applyRequiresSeparateGatedTool: true
};
function buildCodeWorkHandoffV1(args) {
  const generatedAt = args.generatedAt ?? defaultGeneratedAt();
  const handoffId = args.handoffId ?? `code-work-handoff:${stableSlug(args.workflowPlan.workflowPlanId)}`;
  const sessionId = args.sessionId ?? args.strategyPlan?.sourceRefs.sessionId;
  const workflowFeedback = args.workflowOracleFeedback ?? [];
  const requiredQuestionSummary = summarizeRequiredQuestions(args.workflowPlan.oraclePromptPackets, workflowFeedback);
  const serviceConnectionIds = uniqueStrings([
    ...args.workflowPlan.sourceRefs.serviceConnectionIds ?? [],
    ...args.strategyPlan?.sourceRefs.serviceConnectionIds ?? [],
    ...(args.serviceConnectionRefs ?? []).map((ref) => ref.serviceConnectionId)
  ]);
  const serviceEvidenceRefs = uniqueStrings([
    ...(args.serviceConnectionRefs ?? []).flatMap((ref) => [ref.evidenceRef, ref.contractRef]),
    ...args.workflowPlan.serviceConnectionGates.flatMap((gate) => gate.evidenceRefs)
  ]);
  const receiptRefs = uniqueStrings([
    ...args.receiptRefs ?? [],
    ...args.workflowPlan.receipts.map((receipt) => receipt.receiptId)
  ]);
  const contextRefs = {
    exactRefs: args.workflowPlan.sessionSelect.exactRefs,
    sourceRefs: resolveSourceRefs(args),
    evidenceRefs: resolveEvidenceRefs(args, serviceEvidenceRefs),
    receiptRefs,
    avoidRefs: args.workflowPlan.sessionSelect.avoidRefs,
    pathOnlyRefs: args.workflowPlan.sessionSelect.pathOnlyRefs,
    deferredRefs: args.workflowPlan.sessionSelect.deferredRefs,
    readSliceIds: args.workflowPlan.sessionSelect.readSlices.map((slice) => slice.readSliceId)
  };
  const blockingBeforeWriteGateIds = uniqueStrings([
    ...args.workflowPlan.gates.filter((gate) => gate.blockingBeforeWrite).map((gate) => gate.gateId),
    ...args.workflowPlan.synapseGates.filter((gate) => gate.blockingBeforeWrite).map((gate) => gate.gateId),
    ...args.workflowPlan.serviceConnectionGates.filter((gate) => gate.blockingBeforeWrite).map((gate) => gate.gateId)
  ]);
  const nextAction = selectCodeWorkNextAction({
    serviceGateIdsNeedingEvidence: args.workflowPlan.serviceConnectionGates.filter((gate) => gate.status !== "satisfied_by_input").map((gate) => gate.gateId),
    unansweredRequiredQuestionIds: requiredQuestionSummary.unansweredRequiredQuestionIds,
    failedRequiredQuestionIds: requiredQuestionSummary.failedRequiredQuestionIds,
    sessionId,
    requiredReadSliceIds: contextRefs.readSliceIds,
    completedReadSliceIds: args.completedReadSliceIds ?? []
  });
  return {
    schemaVersion: CODE_WORK_HANDOFF_SCHEMA_VERSION,
    kind: CODE_WORK_HANDOFF_KIND,
    handoffId,
    generatedAt,
    objective: args.objective ?? args.workflowPlan.objective ?? args.strategyPlan?.objective ?? "Code work handoff",
    sourceRefs: {
      strategyId: args.strategyPlan?.strategyId ?? args.workflowPlan.sourceRefs.strategyId,
      workflowPlanId: args.workflowPlan.workflowPlanId,
      contextPacketIds: uniqueStrings([
        ...args.workflowPlan.sourceRefs.contextPacketIds,
        ...args.strategyPlan?.sourceRefs.contextPacketIds ?? []
      ]),
      workstreamPacketIds: uniqueStrings(args.strategyPlan?.sourceRefs.workstreamPacketIds ?? []),
      sessionId,
      serviceConnectionIds
    },
    contextRefs,
    workflowPlan: args.workflowPlan,
    oracle: {
      promptPackets: args.workflowPlan.oraclePromptPackets,
      strategyOracleFeedback: args.strategyOracleFeedback ?? args.strategyPlan?.oracleFeedback ?? [],
      workflowOracleFeedback: workflowFeedback,
      unansweredRequiredQuestionIds: requiredQuestionSummary.unansweredRequiredQuestionIds,
      failedRequiredQuestionIds: requiredQuestionSummary.failedRequiredQuestionIds,
      allRequiredQuestionsAnswered: requiredQuestionSummary.unansweredRequiredQuestionIds.length === 0 && requiredQuestionSummary.failedRequiredQuestionIds.length === 0
    },
    gates: {
      workflowGates: args.workflowPlan.gates,
      synapseGates: args.workflowPlan.synapseGates,
      serviceConnectionGates: args.workflowPlan.serviceConnectionGates,
      blockingBeforeWriteGateIds
    },
    budgets: {
      estimateVersion: CODE_WORK_HANDOFF_TOKEN_ESTIMATE_VERSION,
      sessionSelect: args.workflowPlan.sessionSelect.tokenBudget,
      workflowTokenSummary: args.workflowPlan.tokenSummary
    },
    serviceConnections: {
      ids: serviceConnectionIds,
      refs: args.serviceConnectionRefs ?? [],
      evidenceRefs: serviceEvidenceRefs,
      gateIds: args.workflowPlan.serviceConnectionGates.map((gate) => gate.gateId)
    },
    receipts: {
      refs: receiptRefs,
      expected: args.workflowPlan.receipts,
      requiredBeforeApply: receiptRefs
    },
    delegation: {
      editAgentBriefs: buildEditAgentDelegationBriefs({
        handoffId,
        workflowPlanId: args.workflowPlan.workflowPlanId,
        workflowSteps: args.workflowPlan.workflowSteps,
        readSlices: args.workflowPlan.sessionSelect.readSlices,
        serviceConnectionGates: args.workflowPlan.serviceConnectionGates,
        serviceConnectionIds
      })
    },
    nextAction,
    warnings: uniqueStrings([
      ...args.warnings ?? [],
      ...args.workflowPlan.warnings,
      ...(args.strategyPlan?.warnings ?? []).map((warning) => `strategy:${warning}`)
    ]),
    guardrails: REPORT_ONLY_GUARDRAILS
  };
}
function summarizeRequiredQuestions(packets, feedback) {
  const unansweredRequiredQuestionIds = [];
  const failedRequiredQuestionIds = [];
  for (const packet of packets) {
    for (const question of packet.questions.filter((item) => item.requiredBeforeWrite)) {
      const answer = feedback.find((item) => feedbackMatchesQuestion(item, packet.packetId, question.questionId, question.questionKind));
      if (!answer) {
        unansweredRequiredQuestionIds.push(question.questionId);
      } else if (!answer.answer) {
        failedRequiredQuestionIds.push(question.questionId);
      }
    }
  }
  return {
    unansweredRequiredQuestionIds: uniqueStrings(unansweredRequiredQuestionIds),
    failedRequiredQuestionIds: uniqueStrings(failedRequiredQuestionIds)
  };
}
function feedbackMatchesQuestion(feedback, packetId, questionId, questionKind) {
  if (feedback.packetId && feedback.packetId !== packetId)
    return false;
  if (feedback.questionId)
    return feedback.questionId === questionId;
  if (feedback.answer)
    return false;
  return feedback.questionKind === questionKind;
}
function selectCodeWorkNextAction(args) {
  if (args.serviceGateIdsNeedingEvidence.length > 0) {
    return nextAction({
      kind: "provide_service_connection_evidence",
      targetTool: "rhei_code_prepare_work",
      reason: "One or more service connection gates still need compact IDs or external evidence before edit planning.",
      blockingGateIds: args.serviceGateIdsNeedingEvidence
    });
  }
  if (args.failedRequiredQuestionIds.length > 0) {
    return nextAction({
      kind: "revise_context_or_scope",
      reason: "A required workflow oracle question was answered false, so context or scope should be revised before edit planning.",
      requiredQuestionIds: args.failedRequiredQuestionIds
    });
  }
  if (args.unansweredRequiredQuestionIds.length > 0) {
    return nextAction({
      kind: "answer_oracle_prompt_packets",
      reason: "Required workflow oracle prompt-packet questions must be answered before edit planning.",
      requiredQuestionIds: args.unansweredRequiredQuestionIds
    });
  }
  if (!args.sessionId) {
    return nextAction({
      kind: "start_code_session_from_handoff",
      targetTool: "rhei_code_session_start",
      reason: "No Code Session ID is attached; start a bounded Code Session from this report-only handoff."
    });
  }
  const completed = new Set(args.completedReadSliceIds);
  const unread = args.requiredReadSliceIds.filter((readSliceId) => !completed.has(readSliceId));
  if (unread.length > 0) {
    return nextAction({
      kind: "read_session_select_slices",
      targetTool: "rhei_code_read",
      reason: "Read the selected session slices before preparing any bounded edit proposal.",
      requiredReadSliceIds: unread
    });
  }
  return nextAction({
    kind: "plan_edits_with_handoff",
    targetTool: "rhei_code_plan_edits",
    reason: "All required report-only gates available to this handoff are satisfied; prepare an edit proposal through a separate planning tool, not apply."
  });
}
function nextAction(args) {
  return {
    ...args,
    availableNow: false,
    reportOnly: true,
    advisoryOnly: true,
    noAuthority: true
  };
}
function resolveSourceRefs(args) {
  if (!args.strategyPlan)
    return args.workflowPlan.sessionSelect.exactRefs;
  return uniqueStrings(args.strategyPlan.connectedFileGroups.filter((group) => ["source", "config"].includes(group.role)).flatMap((group) => group.paths));
}
function resolveEvidenceRefs(args, serviceEvidenceRefs) {
  const strategyEvidenceRefs = args.strategyPlan?.connectedFileGroups.filter((group) => ["test", "doc", "service_connection_evidence"].includes(group.role)).flatMap((group) => group.paths) ?? [];
  return uniqueStrings([
    ...strategyEvidenceRefs,
    ...serviceEvidenceRefs,
    ...args.workflowPlan.serviceConnectionGates.flatMap((gate) => gate.evidenceRefs)
  ]);
}
function buildEditAgentDelegationBriefs(args) {
  const slicesById = new Map(args.readSlices.map((slice) => [slice.readSliceId, slice]));
  const serviceConnectionIdsByGateId = new Map(args.serviceConnectionGates.map((gate) => [gate.gateId, gate.serviceConnectionId]));
  return args.workflowSteps.map((step) => {
    const stepSlices = step.requiredReadSliceIds.map((readSliceId) => slicesById.get(readSliceId)).filter(isDefined);
    const stepServiceConnectionIds = uniqueStrings([
      ...step.gateIds.map((gateId) => serviceConnectionIdsByGateId.get(gateId)),
      ...stepSlices.flatMap((slice) => slice.serviceConnectionGateIds.map((gateId) => serviceConnectionIdsByGateId.get(gateId)))
    ]);
    return {
      briefId: `edit-brief:${stableSlug(args.handoffId)}:${stableSlug(step.stepId)}`,
      handoffId: args.handoffId,
      workflowPlanId: args.workflowPlanId,
      stepId: step.stepId,
      title: step.title,
      purpose: step.purpose,
      exactRefs: uniqueStrings(stepSlices.map((slice) => slice.path)),
      requiredReadSliceIds: step.requiredReadSliceIds,
      editableRefs: uniqueStrings(stepSlices.filter((slice) => slice.role === "edit").map((slice) => slice.path)),
      validationRefs: uniqueStrings(stepSlices.filter((slice) => ["test", "doc"].includes(slice.role)).map((slice) => slice.path)),
      serviceConnectionIds: stepServiceConnectionIds.length > 0 ? stepServiceConnectionIds : args.serviceConnectionIds,
      requiredGateIds: step.gateIds,
      instructions: [
        "Use this brief as report-only context; it grants no write authority.",
        "Read only the requiredReadSliceIds/exactRefs before proposing changes.",
        "Do not apply changes from this handoff; apply remains a separate gated tool path."
      ],
      reportOnly: true,
      advisoryOnly: true,
      noAuthority: true
    };
  });
}
function isDefined(value) {
  return value !== undefined;
}
function stableSlug(value) {
  return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 96) || "handoff";
}
function uniqueStrings(values) {
  const output = [];
  const seen = new Set;
  for (const value of values) {
    const text = typeof value === "string" ? value.trim() : "";
    if (!text || seen.has(text))
      continue;
    seen.add(text);
    output.push(text);
  }
  return output;
}
export {
  buildCodeWorkHandoffV1,
  CODE_WORK_HANDOFF_TOKEN_ESTIMATE_VERSION,
  CODE_WORK_HANDOFF_SCHEMA_VERSION,
  CODE_WORK_HANDOFF_KIND
};
