@productbrain/mcp 0.0.1-beta.951 → 0.0.1-beta.958

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.
@@ -12527,11 +12527,16 @@ function replaceVocabTokens(body, workspaceCtx, collectionCtxMap) {
12527
12527
 
12528
12528
  // src/tools/orient.ts
12529
12529
  var PURPOSE_GAP_PREFIX = "purpose-gap-";
12530
- function reportOrientWrapperBytes(toolResult, truncated) {
12530
+ var NON_MEANINGFUL_TASK_RE = /^[\s​‌‍⁠]*$/u;
12531
+ function taskIsMeaningful(task) {
12532
+ if (typeof task !== "string") return false;
12533
+ return !NON_MEANINGFUL_TASK_RE.test(task);
12534
+ }
12535
+ function reportOrientWrapperBytes(toolResult, truncated, tier, taskProvided) {
12531
12536
  try {
12532
12537
  const fullToolOutput = JSON.stringify({ content: toolResult.content ?? [] });
12533
12538
  const bytes = Buffer.byteLength(fullToolOutput, "utf8");
12534
- void kernelMutation("agent.reportOrientMetric", { bytes, truncated }).catch(() => {
12539
+ void kernelMutation("agent.reportOrientMetric", { bytes, truncated, tier, taskProvided }).catch(() => {
12535
12540
  });
12536
12541
  } catch {
12537
12542
  }
@@ -12584,7 +12589,7 @@ var VALID_TASK_DOMAINS = [
12584
12589
  var orientSchema = z21.object({
12585
12590
  mode: z21.enum(["full", "brief"]).optional().default("full").describe("full = full context (default). brief = compact summary for mid-session re-orientation. Prefer using the `tier` param for depth control."),
12586
12591
  tier: z21.enum(["summary", "standard", "full"]).optional().describe(
12587
- "Payload depth. summary = ~10 KB compact. standard = ~256 KB default. full = complete payload (large). Defaults to standard."
12592
+ "Payload depth. Defaults to summary (~10 KB) when task is provided; standard (~256 KB) when task is absent. Pass summary, standard, or full to override."
12588
12593
  ),
12589
12594
  task: z21.string().optional().describe("Natural-language task description for task-scoped context. When provided, orient returns scored, relevant entries for the task."),
12590
12595
  scope: z21.enum(VALID_TASK_DOMAINS).optional().describe(`Optional domain scope to filter governance to entries relevant for this domain. Valid values: ${VALID_TASK_DOMAINS.join(", ")}.`)
@@ -12613,712 +12618,725 @@ function registerOrientTool(server) {
12613
12618
  "orient",
12614
12619
  {
12615
12620
  title: "Orient \u2014 Task Grounding",
12616
- description: "Task-grounded context loader. Use AFTER `start_pb` (the canonical session opener) to load governance and context for a specific task. Returns workspace context with a single recommended next action for low-readiness workspaces, or a standup-style briefing for established workspaces.\n\n**Not the session opener.** For 'how do I begin a session' or 'Start PB', call `start_pb` instead. `orient` is for refreshing or scoping context once a session is already underway.\n\nCompleting orientation unlocks write tools for the active session.\n\n**tier:** Controls payload depth. `standard` (default, ~256 KB) is the recommended default. `summary` (~10 KB) for quick mid-session re-orientation. `full` for complete payload when deep context is needed.\n\n**mode:** `full` (default) returns full context. `brief` returns compact summary \u2014 mapped to tier=summary internally. Prefer `tier` for explicit depth control.\n\n**task:** Optional natural-language task description. When provided, returns task-scoped context (scored, relevant entries) in addition to standard orient sections.\n\n**scope:** Optional domain scope. Filters governance entries to those relevant for the specified domain. Authority roots include strategy, product, product-design, engineering, architecture, data, governance, and go-to-market. Child scopes such as product-design/ux, engineering/frontend, data/analytics, and governance/principles are accepted. Legacy internal scopes remain accepted.",
12621
+ description: "Task-grounded context loader. Use AFTER `start_pb` (the canonical session opener) to load governance and context for a specific task. Returns workspace context with a single recommended next action for low-readiness workspaces, or a standup-style briefing for established workspaces.\n\n**Not the session opener.** For 'how do I begin a session' or 'Start PB', call `start_pb` instead. `orient` is for refreshing or scoping context once a session is already underway.\n\nCompleting orientation unlocks write tools for the active session.\n\n**tier:** Controls payload depth.\n- `summary` (~10 KB) \u2014 compact, calibrated for task-scoped retrieval.\n- `standard` (~256 KB) \u2014 rich, suited to workspace standups.\n- `full` \u2014 complete payload, no cap (use with deliberation).\n\nDefaults: `summary` when `task` is provided; `standard` when `task` is absent. Explicit `tier` always wins. Pair with `mode='brief'` for compact formatting (orthogonal to depth).\n\n**mode:** `full` (default) returns full context. `brief` returns compact summary \u2014 mapped to tier=summary internally. Prefer `tier` for explicit depth control.\n\n**task:** Optional natural-language task description. When provided, returns task-scoped context (scored, relevant entries) in addition to standard orient sections.\n\n**scope:** Optional domain scope. Filters governance entries to those relevant for the specified domain. Authority roots include strategy, product, product-design, engineering, architecture, data, governance, and go-to-market. Child scopes such as product-design/ux, engineering/frontend, data/analytics, and governance/principles are accepted. Legacy internal scopes remain accepted.",
12617
12622
  inputSchema: orientSchema,
12618
12623
  annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
12619
12624
  },
12620
- thinWrapper(async ({ mode = "full", tier, task, scope }) => {
12621
- const errors = [];
12622
- const effectiveTier = tier ?? (mode === "brief" ? "summary" : "standard");
12623
- if (scope && !task) {
12624
- errors.push("--scope requires --task to filter governance. Scope was ignored.");
12625
- }
12626
- const agentSessionId = getAgentSessionId();
12627
- if (isSessionOriented() && mode === "brief" && !task) {
12628
- return {
12629
- content: [{
12630
- type: "text",
12631
- text: "Already oriented. Session active, writes unlocked.\n\n" + taskGroundingWarningLines().join("\n") + "Use `orient mode='full'` for workspace context or `orient task='...'` before substantive work."
12632
- }],
12633
- structuredContent: success(
12634
- "Already oriented. Session active, writes unlocked.",
12635
- {
12636
- alreadyOriented: true,
12637
- sessionId: agentSessionId,
12638
- taskGroundingStatus: "workspace_only",
12639
- taskGroundingRequired: true,
12640
- nextStep: 'Run `orient task="describe the work"` before substantive work.'
12641
- }
12642
- )
12643
- };
12644
- }
12645
- let wsCtx = null;
12646
- try {
12647
- wsCtx = await getWorkspaceContext();
12648
- } catch (e) {
12649
- errors.push(`Workspace: ${e instanceof Error ? e.message : String(e)}`);
12650
- }
12651
- let priorSessions = [];
12652
- let recoveryBlock = null;
12653
- let orientView = null;
12625
+ thinWrapper(_handleOrient)
12626
+ );
12627
+ }
12628
+ async function _handleOrient({ mode = "full", tier, task, scope }) {
12629
+ const errors = [];
12630
+ const callTier = tier ?? (mode === "brief" ? "summary" : void 0);
12631
+ const resolvedTier = callTier ?? (taskIsMeaningful(task) ? "summary" : "standard");
12632
+ if (scope && !task) {
12633
+ errors.push("--scope requires --task to filter governance. Scope was ignored.");
12634
+ }
12635
+ const agentSessionId = getAgentSessionId();
12636
+ if (isSessionOriented() && mode === "brief" && !task) {
12637
+ return {
12638
+ content: [{
12639
+ type: "text",
12640
+ text: "Already oriented. Session active, writes unlocked.\n\n" + taskGroundingWarningLines().join("\n") + "Use `orient mode='full'` for workspace context or `orient task='...'` before substantive work."
12641
+ }],
12642
+ structuredContent: success(
12643
+ "Already oriented. Session active, writes unlocked.",
12644
+ {
12645
+ alreadyOriented: true,
12646
+ sessionId: agentSessionId,
12647
+ taskGroundingStatus: "workspace_only",
12648
+ taskGroundingRequired: true,
12649
+ nextStep: 'Run `orient task="describe the work"` before substantive work.'
12650
+ }
12651
+ )
12652
+ };
12653
+ }
12654
+ let wsCtx = null;
12655
+ try {
12656
+ wsCtx = await getWorkspaceContext();
12657
+ } catch (e) {
12658
+ errors.push(`Workspace: ${e instanceof Error ? e.message : String(e)}`);
12659
+ }
12660
+ let priorSessions = [];
12661
+ let recoveryBlock = null;
12662
+ let orientView = null;
12663
+ try {
12664
+ const orientArgs = {};
12665
+ if (task) orientArgs.task = task;
12666
+ if (scope) orientArgs.scope = scope;
12667
+ if (callTier) orientArgs.tier = callTier;
12668
+ orientView = await kernelQuery("chain.getOrientView", orientArgs);
12669
+ } catch {
12670
+ }
12671
+ let vocabCtx;
12672
+ try {
12673
+ const vocab = await kernelQuery("chain.getVocabulary", {});
12674
+ if (vocab?.collectionLabels || vocab?.collectionDefaults) {
12675
+ vocabCtx = {
12676
+ ...vocab.collectionLabels ? { collectionLabels: vocab.collectionLabels } : {},
12677
+ ...vocab.collectionDefaults ? { collectionDefaults: vocab.collectionDefaults } : {}
12678
+ };
12679
+ }
12680
+ } catch {
12681
+ }
12682
+ if (orientView) {
12683
+ priorSessions = orientView.priorSessions ?? [];
12684
+ recoveryBlock = orientView.recoveryBlock ?? null;
12685
+ }
12686
+ const hasTaskGrounding = Boolean(task && orientView?.taskContext?.context?.length > 0);
12687
+ if (wsCtx && hasTaskGrounding && orientView?.writeBackHints) {
12688
+ const hints = Array.isArray(orientView.writeBackHints) ? orientView.writeBackHints : [];
12689
+ if (hints.length > 0) {
12690
+ trackWriteBackHintServed(wsCtx.workspaceId, {
12691
+ hint_count: hints.length,
12692
+ has_task: !!task
12693
+ });
12694
+ }
12695
+ }
12696
+ let openTensions = [];
12697
+ try {
12698
+ const tensions = await kernelQuery("chain.listEntries", { collectionSlug: "tensions" });
12699
+ openTensions = (tensions ?? []).filter((e) => e.workflowStatus === "open");
12700
+ } catch {
12701
+ }
12702
+ let allCollections = [];
12703
+ try {
12704
+ allCollections = await kernelQuery("chain.listCollections") ?? [];
12705
+ } catch {
12706
+ }
12707
+ let readiness = null;
12708
+ try {
12709
+ readiness = await kernelQuery("chain.workspaceReadiness");
12710
+ } catch (e) {
12711
+ errors.push(`Readiness: ${e instanceof Error ? e.message : String(e)}`);
12712
+ }
12713
+ if (readiness?.stage === "blank") {
12714
+ const scanLines = [
12715
+ `# Welcome to ${wsCtx?.workspaceName ?? "your workspace"}`,
12716
+ "",
12717
+ "Your workspace is fresh \u2014 let's set it up.",
12718
+ "",
12719
+ "**Recommended:** call the `start` tool instead of `orient` for the best first-run experience.",
12720
+ "It will guide you through setting up your workspace \u2014 you can tell me about your product, scan your codebase, or use a preset.",
12721
+ "",
12722
+ "Or tell me about your product and I'll start capturing knowledge directly."
12723
+ ];
12724
+ let oriented = false;
12725
+ let orientationStatus2 = "no_session";
12726
+ if (agentSessionId) {
12654
12727
  try {
12655
- const orientArgs = {};
12656
- if (task) orientArgs.task = task;
12657
- if (scope) orientArgs.scope = scope;
12658
- orientArgs.tier = effectiveTier;
12659
- orientView = await kernelQuery("chain.getOrientView", orientArgs);
12728
+ await kernelCall("agent.markOriented", { sessionId: agentSessionId });
12729
+ setSessionOriented(true);
12730
+ oriented = true;
12731
+ orientationStatus2 = "complete";
12660
12732
  } catch {
12733
+ orientationStatus2 = "failed";
12661
12734
  }
12662
- let vocabCtx;
12663
- try {
12664
- const vocab = await kernelQuery("chain.getVocabulary", {});
12665
- if (vocab?.collectionLabels || vocab?.collectionDefaults) {
12666
- vocabCtx = {
12667
- ...vocab.collectionLabels ? { collectionLabels: vocab.collectionLabels } : {},
12668
- ...vocab.collectionDefaults ? { collectionDefaults: vocab.collectionDefaults } : {}
12669
- };
12670
- }
12671
- } catch {
12735
+ }
12736
+ const blankResult = {
12737
+ content: [{ type: "text", text: scanLines.join("\n") }],
12738
+ structuredContent: success(
12739
+ "Workspace is blank. Use the start_pb tool for guided setup.",
12740
+ { stage: "blank", readinessScore: readiness?.score ?? 0, oriented, orientationStatus: orientationStatus2, redirectHint: "Use the `start_pb` tool for the full guided setup experience." },
12741
+ [{ tool: "start_pb", description: "Guided workspace setup", parameters: {} }]
12742
+ )
12743
+ };
12744
+ reportOrientWrapperBytes(blankResult, false, resolvedTier, taskIsMeaningful(task));
12745
+ return blankResult;
12746
+ }
12747
+ const lines = [];
12748
+ const isLowReadiness = readiness && readiness.score < 50;
12749
+ if (wsCtx) {
12750
+ lines.push(`# ${wsCtx.workspaceName}`);
12751
+ lines.push(`_Workspace \`${wsCtx.workspaceSlug}\` \u2014 Product Brain is healthy._`);
12752
+ } else {
12753
+ lines.push("# Workspace");
12754
+ lines.push("_Could not resolve workspace._");
12755
+ }
12756
+ lines.push("");
12757
+ lines.push(...taskGroundingWarningLines(task, hasTaskGrounding));
12758
+ if (mode === "brief") {
12759
+ const briefStage = readiness?.stage ?? (readiness?.score != null ? readiness.score < 50 ? "seeded" : "grounded" : "unknown");
12760
+ lines.push(`Brain stage: ${briefStage}`);
12761
+ if (orientView?.strategicContext) {
12762
+ const sc = orientView.strategicContext;
12763
+ if (sc.vision) lines.push(`Vision: ${sc.vision}`);
12764
+ if (sc.purpose) lines.push(`Purpose: ${sc.purpose}`);
12765
+ if (sc.productAreaCount != null && sc.productAreaCount > 0) {
12766
+ lines.push(`Product areas (${sc.productAreaCount}): ${(sc.productAreas ?? []).join(", ")}`);
12767
+ }
12768
+ if (sc.playingFieldCount != null && sc.playingFieldCount > 0) {
12769
+ lines.push(`Playing field (${sc.playingFieldCount}): ${(sc.playingField ?? []).join(", ")}`);
12770
+ }
12771
+ const wpPlural = getCollectionLabel("work_package", "plural", vocabCtx);
12772
+ lines.push(`${sc.activeBetCount} active ${wpPlural}, ${sc.activeTensionCount} tension(s).`);
12773
+ }
12774
+ if (orientView?.taskContext && orientView.taskContext.context.length > 0) {
12775
+ lines.push(`Task context: ${orientView.taskContext.totalFound} relevant entries (${orientView.taskContext.confidence} confidence).`);
12776
+ if (orientView.taskContext.isGroundingStub && orientView.taskContext.groundingNote) {
12777
+ lines.push(`\u26A0\uFE0F ${orientView.taskContext.groundingNote}`);
12778
+ }
12779
+ }
12780
+ if (orientView?.startup?.domainRetrieval) {
12781
+ const retrieval = orientView.startup.domainRetrieval;
12782
+ const scopedTo = retrieval.resolvedDomainSlug ? ` (${retrieval.resolvedDomainSlug})` : "";
12783
+ lines.push(`Domain retrieval: ${retrieval.state}${scopedTo}`);
12784
+ if (retrieval.activeSource) lines.push(`Active source: ${retrieval.activeSource}`);
12785
+ if (retrieval.fallbackReason) lines.push(`Fallback: ${retrieval.fallbackReason}`);
12786
+ if (retrieval.fallbackAction) lines.push(`Action: ${retrieval.fallbackAction}`);
12787
+ if (retrieval.evidenceGap) lines.push(`Evidence gap: ${retrieval.evidenceGap}`);
12788
+ if (retrieval.directRatifiedCount != null || retrieval.inheritedRatifiedCount != null || retrieval.orgFallbackCount != null) {
12789
+ lines.push(`Domain relation evidence: ${retrieval.directRatifiedCount ?? 0} direct, ${retrieval.inheritedRatifiedCount ?? 0} inherited, ${retrieval.orgFallbackCount ?? 0} org fallback`);
12790
+ }
12791
+ }
12792
+ if (orientView?.writeBackHints && orientView.writeBackHints.length > 0) {
12793
+ lines.push("");
12794
+ lines.push("Write-back hints (what to capture this session):");
12795
+ for (const h of orientView.writeBackHints) {
12796
+ lines.push(` ${h.collectionSlug}: ${h.hint}`);
12672
12797
  }
12673
- if (orientView) {
12674
- priorSessions = orientView.priorSessions ?? [];
12675
- recoveryBlock = orientView.recoveryBlock ?? null;
12676
- }
12677
- const hasTaskGrounding = Boolean(task && orientView?.taskContext?.context?.length > 0);
12678
- if (wsCtx && hasTaskGrounding && orientView?.writeBackHints) {
12679
- const hints = Array.isArray(orientView.writeBackHints) ? orientView.writeBackHints : [];
12680
- if (hints.length > 0) {
12681
- trackWriteBackHintServed(wsCtx.workspaceId, {
12682
- hint_count: hints.length,
12683
- has_task: !!task
12684
- });
12685
- }
12798
+ }
12799
+ if (orientView?.activeWorkPackages?.length > 0) {
12800
+ for (const e of orientView.activeWorkPackages) {
12801
+ const tensions = e.linkedTensions;
12802
+ const tensionPart = tensions?.length ? ` \u2014 ${tensions.map((t) => `${t.entryId ?? t.name} (${t.severity ?? "\u2014"})`).join(", ")}` : "";
12803
+ const originPart = e.origin ? ` (origin: ${e.origin})` : "";
12804
+ lines.push(`- \`${e.entryId ?? e._id}\` ${e.name}${originPart}${tensionPart}`);
12686
12805
  }
12687
- let openTensions = [];
12688
- try {
12689
- const tensions = await kernelQuery("chain.listEntries", { collectionSlug: "tensions" });
12690
- openTensions = (tensions ?? []).filter((e) => e.workflowStatus === "open");
12691
- } catch {
12806
+ }
12807
+ if (orientView?.trustMetrics) {
12808
+ const tm = orientView.trustMetrics;
12809
+ if (tm.unverified > 0 || tm.verified > 0) {
12810
+ const capNote = tm.scannedCap ? "+" : "";
12811
+ lines.push(`Trust: ${tm.verified} verified, ${tm.unverified} unverified, ${tm.noStatus} no-status (${tm.total}${capNote} scanned).`);
12692
12812
  }
12693
- let allCollections = [];
12694
- try {
12695
- allCollections = await kernelQuery("chain.listCollections") ?? [];
12696
- } catch {
12813
+ }
12814
+ const briefWna = formatWhatNeedsAttentionBrief(orientView?.whatNeedsAttention);
12815
+ if (briefWna.length > 0) {
12816
+ lines.push("");
12817
+ lines.push(...briefWna);
12818
+ }
12819
+ const briefGaps = readiness?.gaps ?? [];
12820
+ if (briefGaps.length > 0) {
12821
+ const oneLiner = formatGapOneLiner(briefGaps[0]);
12822
+ if (oneLiner) lines.push(oneLiner);
12823
+ }
12824
+ const briefClassificationGaps = briefGaps.filter((g) => g.id?.startsWith?.(PURPOSE_GAP_PREFIX));
12825
+ if (briefClassificationGaps.length > 0) {
12826
+ lines.push(`${briefClassificationGaps.length} collection(s) with weak purpose \u2014 classification may be inaccurate.`);
12827
+ }
12828
+ if (recoveryBlock) {
12829
+ lines.push("");
12830
+ lines.push(...formatRecoveryBlock(recoveryBlock));
12831
+ } else if (priorSessions.length > 0) {
12832
+ const last = priorSessions[0];
12833
+ const date = last.startedAt ? new Date(last.startedAt).toISOString().split("T")[0] : "unknown";
12834
+ const created = Array.isArray(last.entriesCreated) ? last.entriesCreated.length : last.entriesCreated ?? 0;
12835
+ const modified = Array.isArray(last.entriesModified) ? last.entriesModified.length : last.entriesModified ?? 0;
12836
+ lines.push(`Last session (${date}): ${created} created, ${modified} modified`);
12837
+ }
12838
+ let coherenceSnapshot;
12839
+ const coherence = buildCoherenceSection();
12840
+ if (coherence) {
12841
+ lines.push("");
12842
+ lines.push(...coherence.lines);
12843
+ coherenceSnapshot = coherence.snapshot;
12844
+ }
12845
+ if (allCollections.length > 0) {
12846
+ const docCompleteness = buildDocCompletenessSection(allCollections);
12847
+ if (docCompleteness.errorCount > 0 || docCompleteness.warningCount > 0) {
12848
+ lines.push(...docCompleteness.lines);
12697
12849
  }
12698
- let readiness = null;
12699
- try {
12700
- readiness = await kernelQuery("chain.workspaceReadiness");
12701
- } catch (e) {
12702
- errors.push(`Readiness: ${e instanceof Error ? e.message : String(e)}`);
12850
+ }
12851
+ if (orientView) {
12852
+ lines.push("");
12853
+ if (task) {
12854
+ const mapGovernanceEntry = (e) => ({
12855
+ entryId: e.entryId,
12856
+ name: e.name,
12857
+ description: typeof e.preview === "string" ? e.preview : void 0,
12858
+ tier: typeof e.tier === "number" ? e.tier : void 0,
12859
+ // Phase 4 (DEC-1141): thread provenance fields to buildOperatingProtocol.
12860
+ provenance: e.provenance,
12861
+ anchoredBy: typeof e.anchoredBy === "string" ? e.anchoredBy : void 0
12862
+ });
12863
+ const gov = orientView.governance ?? { principles: [], standards: [], businessRules: [] };
12864
+ lines.push(...buildOperatingProtocol({
12865
+ principles: (gov.principles ?? []).map(mapGovernanceEntry),
12866
+ standards: (gov.standards ?? []).map(mapGovernanceEntry),
12867
+ businessRules: (gov.businessRules ?? []).map(mapGovernanceEntry)
12868
+ }, task));
12869
+ } else {
12870
+ lines.push(...buildOperatingProtocol());
12703
12871
  }
12704
- if (readiness?.stage === "blank") {
12705
- const scanLines = [
12706
- `# Welcome to ${wsCtx?.workspaceName ?? "your workspace"}`,
12707
- "",
12708
- "Your workspace is fresh \u2014 let's set it up.",
12709
- "",
12710
- "**Recommended:** call the `start` tool instead of `orient` for the best first-run experience.",
12711
- "It will guide you through setting up your workspace \u2014 you can tell me about your product, scan your codebase, or use a preset.",
12712
- "",
12713
- "Or tell me about your product and I'll start capturing knowledge directly."
12714
- ];
12715
- let oriented = false;
12716
- let orientationStatus2 = "no_session";
12717
- if (agentSessionId) {
12718
- try {
12719
- await kernelCall("agent.markOriented", { sessionId: agentSessionId });
12720
- setSessionOriented(true);
12721
- oriented = true;
12722
- orientationStatus2 = "complete";
12723
- } catch {
12724
- orientationStatus2 = "failed";
12725
- }
12726
- }
12727
- const blankResult = {
12728
- content: [{ type: "text", text: scanLines.join("\n") }],
12729
- structuredContent: success(
12730
- "Workspace is blank. Use the start_pb tool for guided setup.",
12731
- { stage: "blank", readinessScore: readiness?.score ?? 0, oriented, orientationStatus: orientationStatus2, redirectHint: "Use the `start_pb` tool for the full guided setup experience." },
12732
- [{ tool: "start_pb", description: "Guided workspace setup", parameters: {} }]
12733
- )
12734
- };
12735
- reportOrientWrapperBytes(blankResult, false);
12736
- return blankResult;
12872
+ }
12873
+ let orientationStatus2 = "no_session";
12874
+ if (agentSessionId && hasTaskGrounding) {
12875
+ const orientedOk = await markOrientedWithSnapshotFallback(agentSessionId, coherenceSnapshot);
12876
+ if (orientedOk) {
12877
+ orientationStatus2 = "complete";
12878
+ lines.push("---");
12879
+ lines.push(`Orientation complete. Session ${agentSessionId}. Write tools available.`);
12880
+ } else {
12881
+ orientationStatus2 = "failed";
12882
+ lines.push("---");
12883
+ lines.push("_Warning: Could not mark session as oriented. Write tools may be restricted._");
12737
12884
  }
12738
- const lines = [];
12739
- const isLowReadiness = readiness && readiness.score < 50;
12740
- if (wsCtx) {
12741
- lines.push(`# ${wsCtx.workspaceName}`);
12742
- lines.push(`_Workspace \`${wsCtx.workspaceSlug}\` \u2014 Product Brain is healthy._`);
12885
+ } else if (agentSessionId) {
12886
+ orientationStatus2 = "task_required";
12887
+ lines.push("---");
12888
+ lines.push('Workspace orientation loaded. Write tools stay locked until you run `orient task="describe the work"`.');
12889
+ } else {
12890
+ lines.push("---");
12891
+ lines.push("_No active agent session. Call `session action=start` to begin._");
12892
+ }
12893
+ const briefTruncated = orientView?._budget?.truncated ?? orientView?._truncated ?? false;
12894
+ if (briefTruncated) {
12895
+ const reasons = orientView?._budget?.truncationReasons;
12896
+ lines.push("");
12897
+ if (reasons && reasons.length > 0) {
12898
+ lines.push(`_Context truncated to fit tier budget: ${reasons.join(", ")}. Use tier=full for complete payload._`);
12743
12899
  } else {
12744
- lines.push("# Workspace");
12745
- lines.push("_Could not resolve workspace._");
12900
+ lines.push("_Context truncated to fit tier budget. Use tier=full for complete payload._");
12901
+ }
12902
+ }
12903
+ if (errors.length > 0) {
12904
+ lines.push("");
12905
+ for (const err of errors) lines.push(`- ${err}`);
12906
+ }
12907
+ const briefResult = {
12908
+ content: [{ type: "text", text: lines.join("\n") }],
12909
+ structuredContent: success(
12910
+ `Oriented (brief). Stage: ${readiness?.stage ?? "unknown"}.`,
12911
+ {
12912
+ mode: "brief",
12913
+ stage: readiness?.stage ?? "unknown",
12914
+ oriented: hasTaskGrounding ? isSessionOriented() : false,
12915
+ sessionId: agentSessionId,
12916
+ taskGroundingStatus: hasTaskGrounding ? "task_scoped" : task ? "missing_task_context" : "workspace_only",
12917
+ taskGroundingRequired: !hasTaskGrounding,
12918
+ // STD-219 §4 (DEC-1147): machine-readable stub flag for agent consumers.
12919
+ ...orientView?.taskContext?.isGroundingStub ? { groundingStub: true } : {},
12920
+ orientationStatus: orientationStatus2,
12921
+ nextStep: hasTaskGrounding ? void 0 : 'Run `orient task="describe the work"` before substantive work.',
12922
+ ...orientView?._budget ? { _budget: orientView._budget } : {}
12923
+ }
12924
+ )
12925
+ };
12926
+ reportOrientWrapperBytes(briefResult, briefTruncated, resolvedTier, taskIsMeaningful(task));
12927
+ return briefResult;
12928
+ }
12929
+ const orientStage = readiness?.stage ?? "seeded";
12930
+ if (isLowReadiness && wsCtx?.createdAt) {
12931
+ const ageDays = Math.floor((Date.now() - wsCtx.createdAt) / (1e3 * 60 * 60 * 24));
12932
+ if (ageDays >= 30) {
12933
+ lines.push(`Your workspace has been around for ${ageDays} days and is still at the **${orientStage}** stage.`);
12934
+ lines.push("Let's close the gaps \u2014 or if the current structure doesn't fit, we can reshape it.");
12935
+ lines.push("");
12936
+ }
12937
+ }
12938
+ let fullCoherenceSnapshot;
12939
+ if (isLowReadiness) {
12940
+ const captureBehaviorNote = (readiness?.governanceMode ?? wsCtx?.governanceMode ?? "open") === "open" ? "_In Open mode, captures commit automatically unless you ask me to keep them as drafts._" : "_Everything stays as a draft until you confirm._";
12941
+ const gaps = readiness.gaps ?? [];
12942
+ if (gaps.length > 0) {
12943
+ const gapCtx = {
12944
+ stage: orientStage,
12945
+ passedChecks: readiness.passedChecks ?? 0,
12946
+ totalChecks: readiness.totalChecks ?? 0,
12947
+ score: readiness.score ?? 0
12948
+ };
12949
+ lines.push(formatTopGapPrompt(gaps[0], gaps.length - 1, gapCtx));
12950
+ lines.push("");
12951
+ lines.push(captureBehaviorNote);
12952
+ lines.push("");
12953
+ const remainingGaps = gaps.length - 1;
12954
+ if (remainingGaps > 0 || openTensions.length > 0) {
12955
+ const parts = [];
12956
+ if (remainingGaps > 0) parts.push(`${remainingGaps} more area${remainingGaps === 1 ? "" : "s"} to cover`);
12957
+ if (openTensions.length > 0) parts.push(`${openTensions.length} open tension${openTensions.length === 1 ? "" : "s"}`);
12958
+ lines.push(`_${parts.join(" and ")} \u2014 ask for full status to see everything._`);
12959
+ lines.push("");
12746
12960
  }
12961
+ }
12962
+ lines.push("_Need a collection that doesn't exist yet? Just ask \u2014 I'll set it up._");
12963
+ lines.push("");
12964
+ } else if (readiness) {
12965
+ const fmt = (e) => {
12966
+ const type = e.canonicalKey ?? "generic";
12967
+ const stratum = e.stratum ?? "?";
12968
+ const confidencePart = e.confidence ? ` [confidence: ${e.confidence}]` : "";
12969
+ const reviewOverdue = e.reviewAt && new Date(e.reviewAt).getTime() < Date.now();
12970
+ const overduePart = reviewOverdue ? " [review overdue]" : "";
12971
+ const originPart = e.origin ? ` (origin: ${e.origin})` : "";
12972
+ const mark = provenanceMark(e.provenance);
12973
+ const anchorSuffix = e.anchoredBy ? ` (${e.anchoredBy})` : "";
12974
+ return `- ${mark}\`${e.entryId ?? e._id}\` [${type} \xB7 ${stratum}] ${e.name}${anchorSuffix}${originPart}${confidencePart}${overduePart}`;
12975
+ };
12976
+ const fullCoherence = buildCoherenceSection();
12977
+ if (fullCoherence) {
12978
+ fullCoherenceSnapshot = fullCoherence.snapshot;
12979
+ }
12980
+ if (task) {
12981
+ lines.push(`**Brain stage: ${orientStage}.** Working on: **${task}**`);
12747
12982
  lines.push("");
12748
- lines.push(...taskGroundingWarningLines(task, hasTaskGrounding));
12749
- if (mode === "brief") {
12750
- const briefStage = readiness?.stage ?? (readiness?.score != null ? readiness.score < 50 ? "seeded" : "grounded" : "unknown");
12751
- lines.push(`Brain stage: ${briefStage}`);
12752
- if (orientView?.strategicContext) {
12753
- const sc = orientView.strategicContext;
12754
- if (sc.vision) lines.push(`Vision: ${sc.vision}`);
12755
- if (sc.purpose) lines.push(`Purpose: ${sc.purpose}`);
12756
- if (sc.productAreaCount != null && sc.productAreaCount > 0) {
12757
- lines.push(`Product areas (${sc.productAreaCount}): ${(sc.productAreas ?? []).join(", ")}`);
12983
+ if (orientView?.strategicContext) {
12984
+ const sc = orientView.strategicContext;
12985
+ lines.push("## Strategic Context");
12986
+ if (sc.vision) lines.push(`**Vision:** ${sc.vision}`);
12987
+ if (sc.purpose) lines.push(`**Purpose:** ${sc.purpose}`);
12988
+ if (sc.productAreaCount != null && sc.productAreaCount > 0) {
12989
+ lines.push(`**Product areas (${sc.productAreaCount}):** ${(sc.productAreas ?? []).join(", ")}`);
12990
+ }
12991
+ if (sc.playingFieldCount != null && sc.playingFieldCount > 0) {
12992
+ lines.push(`**Playing field (${sc.playingFieldCount}):** ${(sc.playingField ?? []).join(", ")}`);
12993
+ }
12994
+ const currentWP = sc.currentWorkPackage;
12995
+ const wpSingularFull = getCollectionLabel("work_package", "singular", vocabCtx);
12996
+ const wpPluralFull = getCollectionLabel("work_package", "plural", vocabCtx);
12997
+ const betLine = currentWP ? `**Current ${wpSingularFull}:** ${currentWP}. ${sc.activeBetCount} active ${wpPluralFull}.` : `No active ${wpPluralFull}.`;
12998
+ lines.push(`${betLine} ${sc.activeTensionCount} open tension(s).`);
12999
+ lines.push("");
13000
+ }
13001
+ if (orientView?.continuingFrom && orientView.continuingFrom.length > 0) {
13002
+ lines.push("## Continuing from");
13003
+ lines.push("_Prior-session entries most relevant to your task._");
13004
+ lines.push("");
13005
+ for (const e of orientView.continuingFrom) {
13006
+ const id = e.entryId ?? e.name;
13007
+ const type = e.canonicalKey ?? "generic";
13008
+ const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
13009
+ lines.push(`- \`${id}\` (score ${e.score}) [${type}]${coll} \u2014 ${e.name}`);
13010
+ if (e.reasoning) lines.push(` _${e.reasoning}_`);
13011
+ if ("primer" in e && typeof e.primer === "string" && e.primer.length > 0) {
13012
+ const PRIMER_MAX = 1200;
13013
+ const primerText = e.primer.length > PRIMER_MAX ? e.primer.slice(0, PRIMER_MAX) + "\n\u2026 (truncated \u2014 use entries action=get for full primer)" : e.primer;
13014
+ lines.push("");
13015
+ lines.push(" **Primer (paste when starting implementation):**");
13016
+ lines.push(" ```");
13017
+ for (const line of primerText.split("\n")) lines.push(" " + line);
13018
+ lines.push(" ```");
13019
+ lines.push("");
12758
13020
  }
12759
- if (sc.playingFieldCount != null && sc.playingFieldCount > 0) {
12760
- lines.push(`Playing field (${sc.playingFieldCount}): ${(sc.playingField ?? []).join(", ")}`);
13021
+ }
13022
+ lines.push("");
13023
+ }
13024
+ if (orientView?.lastSessionTouched && orientView.lastSessionTouched.length > 0) {
13025
+ lines.push("## Last session touched");
13026
+ lines.push("_Entries created or modified in your most recent session._");
13027
+ lines.push("");
13028
+ for (const e of orientView.lastSessionTouched) {
13029
+ const id = e.entryId ?? e.name;
13030
+ const type = e.canonicalKey ?? "generic";
13031
+ const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
13032
+ lines.push(`- \`${id}\` [${type}]${coll} \u2014 ${e.name}`);
13033
+ if ("primer" in e && typeof e.primer === "string" && e.primer.length > 0) {
13034
+ const PRIMER_MAX = 1200;
13035
+ const primerText = e.primer.length > PRIMER_MAX ? e.primer.slice(0, PRIMER_MAX) + "\n\u2026 (truncated \u2014 use entries action=get for full primer)" : e.primer;
13036
+ lines.push("");
13037
+ lines.push(" **Primer:**");
13038
+ lines.push(" ```");
13039
+ for (const line of primerText.split("\n")) lines.push(" " + line);
13040
+ lines.push(" ```");
13041
+ lines.push("");
12761
13042
  }
12762
- const wpPlural = getCollectionLabel("work_package", "plural", vocabCtx);
12763
- lines.push(`${sc.activeBetCount} active ${wpPlural}, ${sc.activeTensionCount} tension(s).`);
12764
13043
  }
12765
- if (orientView?.taskContext && orientView.taskContext.context.length > 0) {
12766
- lines.push(`Task context: ${orientView.taskContext.totalFound} relevant entries (${orientView.taskContext.confidence} confidence).`);
13044
+ lines.push("");
13045
+ }
13046
+ if (orientView?.taskContext && orientView.taskContext.context.length > 0) {
13047
+ const tc = orientView.taskContext;
13048
+ lines.push("## Task Context");
13049
+ if (tc.isGroundingStub && tc.groundingNote) {
13050
+ lines.push(`> \u26A0\uFE0F ${tc.groundingNote}`);
13051
+ lines.push("");
12767
13052
  }
12768
- if (orientView?.startup?.domainRetrieval) {
13053
+ if (orientView.startup?.domainRetrieval) {
12769
13054
  const retrieval = orientView.startup.domainRetrieval;
12770
13055
  const scopedTo = retrieval.resolvedDomainSlug ? ` (${retrieval.resolvedDomainSlug})` : "";
12771
- lines.push(`Domain retrieval: ${retrieval.state}${scopedTo}`);
12772
- if (retrieval.activeSource) lines.push(`Active source: ${retrieval.activeSource}`);
12773
- if (retrieval.fallbackReason) lines.push(`Fallback: ${retrieval.fallbackReason}`);
12774
- if (retrieval.fallbackAction) lines.push(`Action: ${retrieval.fallbackAction}`);
12775
- if (retrieval.evidenceGap) lines.push(`Evidence gap: ${retrieval.evidenceGap}`);
12776
- if (retrieval.directRatifiedCount != null || retrieval.inheritedRatifiedCount != null || retrieval.orgFallbackCount != null) {
12777
- lines.push(`Domain relation evidence: ${retrieval.directRatifiedCount ?? 0} direct, ${retrieval.inheritedRatifiedCount ?? 0} inherited, ${retrieval.orgFallbackCount ?? 0} org fallback`);
12778
- }
12779
- }
12780
- if (orientView?.writeBackHints && orientView.writeBackHints.length > 0) {
13056
+ lines.push(`_Domain retrieval: ${retrieval.state}${scopedTo}_`);
13057
+ if (retrieval.activeSource) lines.push(`_Active source: ${retrieval.activeSource}_`);
13058
+ if (retrieval.fallbackReason) lines.push(`_${retrieval.fallbackReason}_`);
13059
+ if (retrieval.fallbackAction) lines.push(`_${retrieval.fallbackAction}_`);
13060
+ if (retrieval.evidenceGap) lines.push(`_Evidence gap: ${retrieval.evidenceGap}_`);
12781
13061
  lines.push("");
12782
- lines.push("Write-back hints (what to capture this session):");
12783
- for (const h of orientView.writeBackHints) {
12784
- lines.push(` ${h.collectionSlug}: ${h.hint}`);
12785
- }
12786
13062
  }
12787
- if (orientView?.activeWorkPackages?.length > 0) {
12788
- for (const e of orientView.activeWorkPackages) {
12789
- const tensions = e.linkedTensions;
12790
- const tensionPart = tensions?.length ? ` \u2014 ${tensions.map((t) => `${t.entryId ?? t.name} (${t.severity ?? "\u2014"})`).join(", ")}` : "";
12791
- const originPart = e.origin ? ` (origin: ${e.origin})` : "";
12792
- lines.push(`- \`${e.entryId ?? e._id}\` ${e.name}${originPart}${tensionPart}`);
12793
- }
13063
+ lines.push(`_Task-scoped entries (${tc.confidence} confidence, ${tc.totalFound} relevant)`);
13064
+ lines.push("");
13065
+ for (const e of tc.context) {
13066
+ const id = e.entryId ?? e.name;
13067
+ const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
13068
+ const originTag = e.origin ? ` (origin: ${e.origin})` : "";
13069
+ lines.push(`- \`${id}\` (score ${e.score})${coll}${originTag}${e.name !== id ? ` \u2014 ${e.name}` : ""}`);
13070
+ if (e.preview) lines.push(` _${e.preview}_`);
13071
+ }
13072
+ lines.push("");
13073
+ }
13074
+ if (orientView?.taskContext?.constellationEntries && orientView.taskContext.constellationEntries.length > 0) {
13075
+ lines.push(...formatBetConstellationLines(
13076
+ orientView.taskContext.constellationEntries,
13077
+ orientView.taskContext.constellationBetName
13078
+ ));
13079
+ }
13080
+ if (orientView?.writeBackHints && orientView.writeBackHints.length > 0) {
13081
+ lines.push("");
13082
+ lines.push("## Write-Back Hints");
13083
+ lines.push("_What to capture this session (derived from task context):_");
13084
+ lines.push("");
13085
+ for (const h of orientView.writeBackHints) {
13086
+ lines.push(`- **${h.collectionSlug}**: ${h.hint}`);
12794
13087
  }
12795
- if (orientView?.trustMetrics) {
13088
+ lines.push("");
13089
+ }
13090
+ if (orientView) {
13091
+ const result = await runAlignmentCheck(
13092
+ task,
13093
+ orientView.activeWorkPackages ?? [],
13094
+ orientView.taskContext?.context
13095
+ );
13096
+ lines.push(...buildAlignmentCheckLines(result));
13097
+ lines.push(...formatInitiativeStatusLines(orientView.initiativeStatus));
13098
+ lines.push(...formatWorkstreamHealthLines(orientView.workstreamHealth));
13099
+ lines.push(...formatWhatNeedsAttentionLines(orientView.whatNeedsAttention));
13100
+ if (orientView.trustMetrics) {
12796
13101
  const tm = orientView.trustMetrics;
12797
- if (tm.unverified > 0 || tm.verified > 0) {
12798
- const capNote = tm.scannedCap ? "+" : "";
12799
- lines.push(`Trust: ${tm.verified} verified, ${tm.unverified} unverified, ${tm.noStatus} no-status (${tm.total}${capNote} scanned).`);
13102
+ if (tm.verified > 0 || tm.unverified > 0) {
13103
+ const capNote = tm.scannedCap ? " (capped at 500)" : "";
13104
+ lines.push("## Trust metrics");
13105
+ lines.push(`_Entry verification status across workspace${capNote}._`);
13106
+ lines.push("");
13107
+ lines.push(`- **Verified:** ${tm.verified}`);
13108
+ lines.push(`- **Unverified:** ${tm.unverified}`);
13109
+ lines.push(`- **No status (pre-BET-240):** ${tm.noStatus}`);
13110
+ lines.push(`- **Total scanned:** ${tm.total}`);
13111
+ lines.push("");
12800
13112
  }
12801
13113
  }
12802
- const briefWna = formatWhatNeedsAttentionBrief(orientView?.whatNeedsAttention);
12803
- if (briefWna.length > 0) {
12804
- lines.push("");
12805
- lines.push(...briefWna);
12806
- }
12807
- const briefGaps = readiness?.gaps ?? [];
12808
- if (briefGaps.length > 0) {
12809
- const oneLiner = formatGapOneLiner(briefGaps[0]);
12810
- if (oneLiner) lines.push(oneLiner);
12811
- }
12812
- const briefClassificationGaps = briefGaps.filter((g) => g.id?.startsWith?.(PURPOSE_GAP_PREFIX));
12813
- if (briefClassificationGaps.length > 0) {
12814
- lines.push(`${briefClassificationGaps.length} collection(s) with weak purpose \u2014 classification may be inaccurate.`);
13114
+ }
13115
+ if (fullCoherence) {
13116
+ lines.push(...fullCoherence.lines);
13117
+ }
13118
+ if (allCollections.length > 0) {
13119
+ const docCompleteness = buildDocCompletenessSection(allCollections);
13120
+ if (docCompleteness.errorCount > 0 || docCompleteness.warningCount > 0) {
13121
+ lines.push(...docCompleteness.lines);
12815
13122
  }
12816
- if (recoveryBlock) {
12817
- lines.push("");
12818
- lines.push(...formatRecoveryBlock(recoveryBlock));
12819
- } else if (priorSessions.length > 0) {
12820
- const last = priorSessions[0];
12821
- const date = last.startedAt ? new Date(last.startedAt).toISOString().split("T")[0] : "unknown";
12822
- const created = Array.isArray(last.entriesCreated) ? last.entriesCreated.length : last.entriesCreated ?? 0;
12823
- const modified = Array.isArray(last.entriesModified) ? last.entriesModified.length : last.entriesModified ?? 0;
12824
- lines.push(`Last session (${date}): ${created} created, ${modified} modified`);
12825
- }
12826
- let coherenceSnapshot;
12827
- const coherence = buildCoherenceSection();
12828
- if (coherence) {
13123
+ }
13124
+ if (orientView) {
13125
+ if (orientView.activeWorkPackages?.length > 0) {
13126
+ lines.push("## Active work packages \u2014 current scope");
13127
+ lines.push("_Work outside these work packages requires explicit user confirmation._");
12829
13128
  lines.push("");
12830
- lines.push(...coherence.lines);
12831
- coherenceSnapshot = coherence.snapshot;
12832
- }
12833
- if (allCollections.length > 0) {
12834
- const docCompleteness = buildDocCompletenessSection(allCollections);
12835
- if (docCompleteness.errorCount > 0 || docCompleteness.warningCount > 0) {
12836
- lines.push(...docCompleteness.lines);
13129
+ for (const e of orientView.activeWorkPackages) {
13130
+ lines.push(fmt(e));
13131
+ const tensions = e.linkedTensions;
13132
+ if (tensions?.length) {
13133
+ const tensionLines = tensions.map((t) => {
13134
+ const meta = [t.severity, t.priority].filter(Boolean).join(", ");
13135
+ return `\`${t.entryId ?? t.name}\` (${t.name}${meta ? `, ${meta}` : ""})`;
13136
+ });
13137
+ lines.push(` Tensions: ${tensionLines.join("; ")}`);
13138
+ }
12837
13139
  }
12838
- }
12839
- if (orientView) {
12840
13140
  lines.push("");
12841
- if (task) {
12842
- const mapGovernanceEntry = (e) => ({
12843
- entryId: e.entryId,
12844
- name: e.name,
12845
- description: typeof e.preview === "string" ? e.preview : void 0,
12846
- tier: typeof e.tier === "number" ? e.tier : void 0,
12847
- // Phase 4 (DEC-1141): thread provenance fields to buildOperatingProtocol.
12848
- provenance: e.provenance,
12849
- anchoredBy: typeof e.anchoredBy === "string" ? e.anchoredBy : void 0
12850
- });
12851
- const gov = orientView.governance ?? { principles: [], standards: [], businessRules: [] };
12852
- lines.push(...buildOperatingProtocol({
12853
- principles: (gov.principles ?? []).map(mapGovernanceEntry),
12854
- standards: (gov.standards ?? []).map(mapGovernanceEntry),
12855
- businessRules: (gov.businessRules ?? []).map(mapGovernanceEntry)
12856
- }, task));
12857
- } else {
12858
- lines.push(...buildOperatingProtocol());
12859
- }
12860
- }
12861
- let orientationStatus2 = "no_session";
12862
- if (agentSessionId && hasTaskGrounding) {
12863
- const orientedOk = await markOrientedWithSnapshotFallback(agentSessionId, coherenceSnapshot);
12864
- if (orientedOk) {
12865
- orientationStatus2 = "complete";
12866
- lines.push("---");
12867
- lines.push(`Orientation complete. Session ${agentSessionId}. Write tools available.`);
12868
- } else {
12869
- orientationStatus2 = "failed";
12870
- lines.push("---");
12871
- lines.push("_Warning: Could not mark session as oriented. Write tools may be restricted._");
12872
- }
12873
- } else if (agentSessionId) {
12874
- orientationStatus2 = "task_required";
12875
- lines.push("---");
12876
- lines.push('Workspace orientation loaded. Write tools stay locked until you run `orient task="describe the work"`.');
12877
- } else {
12878
- lines.push("---");
12879
- lines.push("_No active agent session. Call `session action=start` to begin._");
12880
13141
  }
12881
- const briefTruncated = orientView?._budget?.truncated ?? orientView?._truncated ?? false;
12882
- if (briefTruncated) {
12883
- const reasons = orientView?._budget?.truncationReasons;
13142
+ if (orientView.activeGoals?.length > 0) {
13143
+ lines.push("## Active goals");
13144
+ orientView.activeGoals.forEach((e) => lines.push(fmt(e)));
12884
13145
  lines.push("");
12885
- if (reasons && reasons.length > 0) {
12886
- lines.push(`_Context truncated to fit tier budget: ${reasons.join(", ")}. Use tier=full for complete payload._`);
12887
- } else {
12888
- lines.push("_Context truncated to fit tier budget. Use tier=full for complete payload._");
12889
- }
12890
13146
  }
12891
- if (errors.length > 0) {
13147
+ if (orientView.strategyHighlights?.length > 0) {
13148
+ lines.push("## Strategy highlights");
13149
+ lines.push("_One-sentence strategy, positioning, moat, business model, GTM \u2014 high-level strategic context._");
12892
13150
  lines.push("");
12893
- for (const err of errors) lines.push(`- ${err}`);
12894
- }
12895
- const briefResult = {
12896
- content: [{ type: "text", text: lines.join("\n") }],
12897
- structuredContent: success(
12898
- `Oriented (brief). Stage: ${readiness?.stage ?? "unknown"}.`,
12899
- {
12900
- mode: "brief",
12901
- stage: readiness?.stage ?? "unknown",
12902
- oriented: hasTaskGrounding ? isSessionOriented() : false,
12903
- sessionId: agentSessionId,
12904
- taskGroundingStatus: hasTaskGrounding ? "task_scoped" : task ? "missing_task_context" : "workspace_only",
12905
- taskGroundingRequired: !hasTaskGrounding,
12906
- orientationStatus: orientationStatus2,
12907
- nextStep: hasTaskGrounding ? void 0 : 'Run `orient task="describe the work"` before substantive work.',
12908
- ...orientView?._budget ? { _budget: orientView._budget } : {}
12909
- }
12910
- )
12911
- };
12912
- reportOrientWrapperBytes(briefResult, briefTruncated);
12913
- return briefResult;
12914
- }
12915
- const orientStage = readiness?.stage ?? "seeded";
12916
- if (isLowReadiness && wsCtx?.createdAt) {
12917
- const ageDays = Math.floor((Date.now() - wsCtx.createdAt) / (1e3 * 60 * 60 * 24));
12918
- if (ageDays >= 30) {
12919
- lines.push(`Your workspace has been around for ${ageDays} days and is still at the **${orientStage}** stage.`);
12920
- lines.push("Let's close the gaps \u2014 or if the current structure doesn't fit, we can reshape it.");
13151
+ orientView.strategyHighlights.forEach((e) => lines.push(fmt(e)));
12921
13152
  lines.push("");
12922
13153
  }
12923
- }
12924
- let fullCoherenceSnapshot;
12925
- if (isLowReadiness) {
12926
- const captureBehaviorNote = (readiness?.governanceMode ?? wsCtx?.governanceMode ?? "open") === "open" ? "_In Open mode, captures commit automatically unless you ask me to keep them as drafts._" : "_Everything stays as a draft until you confirm._";
12927
- const gaps = readiness.gaps ?? [];
12928
- if (gaps.length > 0) {
12929
- const gapCtx = {
12930
- stage: orientStage,
12931
- passedChecks: readiness.passedChecks ?? 0,
12932
- totalChecks: readiness.totalChecks ?? 0,
12933
- score: readiness.score ?? 0
12934
- };
12935
- lines.push(formatTopGapPrompt(gaps[0], gaps.length - 1, gapCtx));
13154
+ if (orientView.playingField?.length > 0) {
13155
+ lines.push("## Playing field");
13156
+ lines.push("_Products and opportunities in the strategic landscape._");
12936
13157
  lines.push("");
12937
- lines.push(captureBehaviorNote);
13158
+ orientView.playingField.forEach((e) => lines.push(fmt(e)));
12938
13159
  lines.push("");
12939
- const remainingGaps = gaps.length - 1;
12940
- if (remainingGaps > 0 || openTensions.length > 0) {
12941
- const parts = [];
12942
- if (remainingGaps > 0) parts.push(`${remainingGaps} more area${remainingGaps === 1 ? "" : "s"} to cover`);
12943
- if (openTensions.length > 0) parts.push(`${openTensions.length} open tension${openTensions.length === 1 ? "" : "s"}`);
12944
- lines.push(`_${parts.join(" and ")} \u2014 ask for full status to see everything._`);
12945
- lines.push("");
12946
- }
12947
13160
  }
12948
- lines.push("_Need a collection that doesn't exist yet? Just ask \u2014 I'll set it up._");
12949
- lines.push("");
12950
- } else if (readiness) {
12951
- const fmt = (e) => {
12952
- const type = e.canonicalKey ?? "generic";
12953
- const stratum = e.stratum ?? "?";
12954
- const confidencePart = e.confidence ? ` [confidence: ${e.confidence}]` : "";
12955
- const reviewOverdue = e.reviewAt && new Date(e.reviewAt).getTime() < Date.now();
12956
- const overduePart = reviewOverdue ? " [review overdue]" : "";
12957
- const originPart = e.origin ? ` (origin: ${e.origin})` : "";
12958
- const mark = provenanceMark(e.provenance);
12959
- const anchorSuffix = e.anchoredBy ? ` (${e.anchoredBy})` : "";
12960
- return `- ${mark}\`${e.entryId ?? e._id}\` [${type} \xB7 ${stratum}] ${e.name}${anchorSuffix}${originPart}${confidencePart}${overduePart}`;
12961
- };
12962
- const fullCoherence = buildCoherenceSection();
12963
- if (fullCoherence) {
12964
- fullCoherenceSnapshot = fullCoherence.snapshot;
13161
+ if (orientView.recentDecisions?.length > 0) {
13162
+ lines.push("## Recent decisions");
13163
+ orientView.recentDecisions.forEach((e) => lines.push(fmt(e)));
13164
+ lines.push("");
12965
13165
  }
12966
- if (task) {
12967
- lines.push(`**Brain stage: ${orientStage}.** Working on: **${task}**`);
13166
+ if (orientView.recentlySuperseded?.length > 0) {
13167
+ lines.push("## Recently superseded");
13168
+ orientView.recentlySuperseded.forEach((e) => lines.push(fmt(e)));
12968
13169
  lines.push("");
12969
- if (orientView?.strategicContext) {
12970
- const sc = orientView.strategicContext;
12971
- lines.push("## Strategic Context");
12972
- if (sc.vision) lines.push(`**Vision:** ${sc.vision}`);
12973
- if (sc.purpose) lines.push(`**Purpose:** ${sc.purpose}`);
12974
- if (sc.productAreaCount != null && sc.productAreaCount > 0) {
12975
- lines.push(`**Product areas (${sc.productAreaCount}):** ${(sc.productAreas ?? []).join(", ")}`);
12976
- }
12977
- if (sc.playingFieldCount != null && sc.playingFieldCount > 0) {
12978
- lines.push(`**Playing field (${sc.playingFieldCount}):** ${(sc.playingField ?? []).join(", ")}`);
12979
- }
12980
- const currentWP = sc.currentWorkPackage;
12981
- const wpSingularFull = getCollectionLabel("work_package", "singular", vocabCtx);
12982
- const wpPluralFull = getCollectionLabel("work_package", "plural", vocabCtx);
12983
- const betLine = currentWP ? `**Current ${wpSingularFull}:** ${currentWP}. ${sc.activeBetCount} active ${wpPluralFull}.` : `No active ${wpPluralFull}.`;
12984
- lines.push(`${betLine} ${sc.activeTensionCount} open tension(s).`);
12985
- lines.push("");
12986
- }
12987
- if (orientView?.continuingFrom && orientView.continuingFrom.length > 0) {
12988
- lines.push("## Continuing from");
12989
- lines.push("_Prior-session entries most relevant to your task._");
12990
- lines.push("");
12991
- for (const e of orientView.continuingFrom) {
12992
- const id = e.entryId ?? e.name;
12993
- const type = e.canonicalKey ?? "generic";
12994
- const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
12995
- lines.push(`- \`${id}\` (score ${e.score}) [${type}]${coll} \u2014 ${e.name}`);
12996
- if (e.reasoning) lines.push(` _${e.reasoning}_`);
12997
- if ("primer" in e && typeof e.primer === "string" && e.primer.length > 0) {
12998
- const PRIMER_MAX = 1200;
12999
- const primerText = e.primer.length > PRIMER_MAX ? e.primer.slice(0, PRIMER_MAX) + "\n\u2026 (truncated \u2014 use entries action=get for full primer)" : e.primer;
13000
- lines.push("");
13001
- lines.push(" **Primer (paste when starting implementation):**");
13002
- lines.push(" ```");
13003
- for (const line of primerText.split("\n")) lines.push(" " + line);
13004
- lines.push(" ```");
13005
- lines.push("");
13006
- }
13007
- }
13008
- lines.push("");
13009
- }
13010
- if (orientView?.lastSessionTouched && orientView.lastSessionTouched.length > 0) {
13011
- lines.push("## Last session touched");
13012
- lines.push("_Entries created or modified in your most recent session._");
13013
- lines.push("");
13014
- for (const e of orientView.lastSessionTouched) {
13015
- const id = e.entryId ?? e.name;
13016
- const type = e.canonicalKey ?? "generic";
13017
- const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
13018
- lines.push(`- \`${id}\` [${type}]${coll} \u2014 ${e.name}`);
13019
- if ("primer" in e && typeof e.primer === "string" && e.primer.length > 0) {
13020
- const PRIMER_MAX = 1200;
13021
- const primerText = e.primer.length > PRIMER_MAX ? e.primer.slice(0, PRIMER_MAX) + "\n\u2026 (truncated \u2014 use entries action=get for full primer)" : e.primer;
13022
- lines.push("");
13023
- lines.push(" **Primer:**");
13024
- lines.push(" ```");
13025
- for (const line of primerText.split("\n")) lines.push(" " + line);
13026
- lines.push(" ```");
13027
- lines.push("");
13028
- }
13029
- }
13030
- lines.push("");
13031
- }
13032
- if (orientView?.taskContext && orientView.taskContext.context.length > 0) {
13033
- const tc = orientView.taskContext;
13034
- lines.push("## Task Context");
13035
- if (orientView.startup?.domainRetrieval) {
13036
- const retrieval = orientView.startup.domainRetrieval;
13037
- const scopedTo = retrieval.resolvedDomainSlug ? ` (${retrieval.resolvedDomainSlug})` : "";
13038
- lines.push(`_Domain retrieval: ${retrieval.state}${scopedTo}_`);
13039
- if (retrieval.activeSource) lines.push(`_Active source: ${retrieval.activeSource}_`);
13040
- if (retrieval.fallbackReason) lines.push(`_${retrieval.fallbackReason}_`);
13041
- if (retrieval.fallbackAction) lines.push(`_${retrieval.fallbackAction}_`);
13042
- if (retrieval.evidenceGap) lines.push(`_Evidence gap: ${retrieval.evidenceGap}_`);
13043
- lines.push("");
13044
- }
13045
- lines.push(`_Task-scoped entries (${tc.confidence} confidence, ${tc.totalFound} relevant)`);
13046
- lines.push("");
13047
- for (const e of tc.context) {
13048
- const id = e.entryId ?? e.name;
13049
- const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
13050
- const originTag = e.origin ? ` (origin: ${e.origin})` : "";
13051
- lines.push(`- \`${id}\` (score ${e.score})${coll}${originTag}${e.name !== id ? ` \u2014 ${e.name}` : ""}`);
13052
- if (e.preview) lines.push(` _${e.preview}_`);
13053
- }
13054
- lines.push("");
13055
- }
13056
- if (orientView?.taskContext?.constellationEntries && orientView.taskContext.constellationEntries.length > 0) {
13057
- lines.push(...formatBetConstellationLines(
13058
- orientView.taskContext.constellationEntries,
13059
- orientView.taskContext.constellationBetName
13060
- ));
13061
- }
13062
- if (orientView?.writeBackHints && orientView.writeBackHints.length > 0) {
13063
- lines.push("");
13064
- lines.push("## Write-Back Hints");
13065
- lines.push("_What to capture this session (derived from task context):_");
13066
- lines.push("");
13067
- for (const h of orientView.writeBackHints) {
13068
- lines.push(`- **${h.collectionSlug}**: ${h.hint}`);
13069
- }
13070
- lines.push("");
13071
- }
13072
- if (orientView) {
13073
- const result = await runAlignmentCheck(
13074
- task,
13075
- orientView.activeWorkPackages ?? [],
13076
- orientView.taskContext?.context
13077
- );
13078
- lines.push(...buildAlignmentCheckLines(result));
13079
- lines.push(...formatInitiativeStatusLines(orientView.initiativeStatus));
13080
- lines.push(...formatWorkstreamHealthLines(orientView.workstreamHealth));
13081
- lines.push(...formatWhatNeedsAttentionLines(orientView.whatNeedsAttention));
13082
- if (orientView.trustMetrics) {
13083
- const tm = orientView.trustMetrics;
13084
- if (tm.verified > 0 || tm.unverified > 0) {
13085
- const capNote = tm.scannedCap ? " (capped at 500)" : "";
13086
- lines.push("## Trust metrics");
13087
- lines.push(`_Entry verification status across workspace${capNote}._`);
13088
- lines.push("");
13089
- lines.push(`- **Verified:** ${tm.verified}`);
13090
- lines.push(`- **Unverified:** ${tm.unverified}`);
13091
- lines.push(`- **No status (pre-BET-240):** ${tm.noStatus}`);
13092
- lines.push(`- **Total scanned:** ${tm.total}`);
13093
- lines.push("");
13094
- }
13095
- }
13096
- }
13097
- if (fullCoherence) {
13098
- lines.push(...fullCoherence.lines);
13099
- }
13100
- if (allCollections.length > 0) {
13101
- const docCompleteness = buildDocCompletenessSection(allCollections);
13102
- if (docCompleteness.errorCount > 0 || docCompleteness.warningCount > 0) {
13103
- lines.push(...docCompleteness.lines);
13104
- }
13105
- }
13106
- if (orientView) {
13107
- if (orientView.activeWorkPackages?.length > 0) {
13108
- lines.push("## Active work packages \u2014 current scope");
13109
- lines.push("_Work outside these work packages requires explicit user confirmation._");
13110
- lines.push("");
13111
- for (const e of orientView.activeWorkPackages) {
13112
- lines.push(fmt(e));
13113
- const tensions = e.linkedTensions;
13114
- if (tensions?.length) {
13115
- const tensionLines = tensions.map((t) => {
13116
- const meta = [t.severity, t.priority].filter(Boolean).join(", ");
13117
- return `\`${t.entryId ?? t.name}\` (${t.name}${meta ? `, ${meta}` : ""})`;
13118
- });
13119
- lines.push(` Tensions: ${tensionLines.join("; ")}`);
13120
- }
13121
- }
13122
- lines.push("");
13123
- }
13124
- if (orientView.activeGoals?.length > 0) {
13125
- lines.push("## Active goals");
13126
- orientView.activeGoals.forEach((e) => lines.push(fmt(e)));
13127
- lines.push("");
13128
- }
13129
- if (orientView.strategyHighlights?.length > 0) {
13130
- lines.push("## Strategy highlights");
13131
- lines.push("_One-sentence strategy, positioning, moat, business model, GTM \u2014 high-level strategic context._");
13132
- lines.push("");
13133
- orientView.strategyHighlights.forEach((e) => lines.push(fmt(e)));
13134
- lines.push("");
13135
- }
13136
- if (orientView.playingField?.length > 0) {
13137
- lines.push("## Playing field");
13138
- lines.push("_Products and opportunities in the strategic landscape._");
13139
- lines.push("");
13140
- orientView.playingField.forEach((e) => lines.push(fmt(e)));
13141
- lines.push("");
13142
- }
13143
- if (orientView.recentDecisions?.length > 0) {
13144
- lines.push("## Recent decisions");
13145
- orientView.recentDecisions.forEach((e) => lines.push(fmt(e)));
13146
- lines.push("");
13147
- }
13148
- if (orientView.recentlySuperseded?.length > 0) {
13149
- lines.push("## Recently superseded");
13150
- orientView.recentlySuperseded.forEach((e) => lines.push(fmt(e)));
13151
- lines.push("");
13152
- }
13153
- if (orientView.staleEntries?.length > 0) {
13154
- lines.push("## Needs confirmation");
13155
- lines.push(`_Domain stratum entries not confirmed in ${orientView.stalenessThresholdDays} days._`);
13156
- orientView.staleEntries.forEach((e) => lines.push(fmt(e)));
13157
- lines.push("");
13158
- }
13159
- if (orientView.architectureNotes?.length > 0) {
13160
- lines.push("## Architecture notes");
13161
- orientView.architectureNotes.forEach((e) => lines.push(fmt(e)));
13162
- lines.push("");
13163
- }
13164
- const mapGovernanceEntry = (e) => ({
13165
- entryId: e.entryId,
13166
- name: e.name,
13167
- description: typeof e.preview === "string" ? e.preview : void 0,
13168
- tier: typeof e.tier === "number" ? e.tier : void 0,
13169
- // Phase 4 (DEC-1141): thread provenance fields to buildOperatingProtocol.
13170
- provenance: e.provenance,
13171
- anchoredBy: typeof e.anchoredBy === "string" ? e.anchoredBy : void 0
13172
- });
13173
- const gov = orientView.governance ?? { principles: [], standards: [], businessRules: [] };
13174
- lines.push(...buildOperatingProtocol({
13175
- principles: (gov.principles ?? []).map(mapGovernanceEntry),
13176
- standards: (gov.standards ?? []).map(mapGovernanceEntry),
13177
- businessRules: (gov.businessRules ?? []).map(mapGovernanceEntry)
13178
- }, task));
13179
- }
13180
- let allEntries = [];
13181
- try {
13182
- allEntries = await kernelQuery("chain.listEntries", {}) ?? [];
13183
- } catch {
13184
- }
13185
- const plannedWork = buildPlannedWork(allEntries);
13186
- if (hasPlannedWork(plannedWork)) {
13187
- lines.push(...buildPlannedWorkSection(plannedWork, priorSessions, recoveryBlock));
13188
- } else if (recoveryBlock) {
13189
- lines.push(...formatRecoveryBlock(recoveryBlock));
13190
- }
13191
- } else {
13192
- lines.push(`**Brain stage: ${orientStage}.**`);
13170
+ }
13171
+ if (orientView.staleEntries?.length > 0) {
13172
+ lines.push("## Needs confirmation");
13173
+ lines.push(`_Domain stratum entries not confirmed in ${orientView.stalenessThresholdDays} days._`);
13174
+ orientView.staleEntries.forEach((e) => lines.push(fmt(e)));
13193
13175
  lines.push("");
13194
- if (orientView?.activeWorkPackages?.length) {
13195
- lines.push("## Active work packages \u2014 current scope");
13196
- lines.push("_Work outside these work packages requires explicit user confirmation._");
13197
- lines.push("");
13198
- for (const e of orientView.activeWorkPackages) {
13199
- lines.push(fmt(e));
13200
- }
13201
- lines.push("");
13202
- }
13203
- lines.push(...formatInitiativeStatusLines(orientView?.initiativeStatus));
13204
- lines.push(...formatWorkstreamHealthLines(orientView?.workstreamHealth));
13205
- lines.push(...formatWhatNeedsAttentionLines(orientView?.whatNeedsAttention));
13206
- if (orientView?.trustMetrics) {
13207
- const tm = orientView.trustMetrics;
13208
- if (tm.verified > 0 || tm.unverified > 0) {
13209
- const capNote = tm.scannedCap ? " (capped at 500)" : "";
13210
- lines.push("## Trust metrics");
13211
- lines.push(`_Entry verification status across workspace${capNote}._`);
13212
- lines.push("");
13213
- lines.push(`- **Verified:** ${tm.verified}`);
13214
- lines.push(`- **Unverified:** ${tm.unverified}`);
13215
- lines.push(`- **No status (pre-BET-240):** ${tm.noStatus}`);
13216
- lines.push(`- **Total scanned:** ${tm.total}`);
13217
- lines.push("");
13218
- }
13219
- }
13220
- lines.push(...buildOperatingProtocol());
13221
- if (fullCoherence) {
13222
- lines.push(...fullCoherence.lines);
13223
- }
13224
- if (allCollections.length > 0) {
13225
- const docCompleteness = buildDocCompletenessSection(allCollections);
13226
- if (docCompleteness.errorCount > 0 || docCompleteness.warningCount > 0) {
13227
- lines.push(...docCompleteness.lines);
13228
- }
13229
- }
13230
- if (priorSessions.length > 0 && !recoveryBlock) {
13231
- const last = priorSessions[0];
13232
- const date = last.startedAt ? new Date(last.startedAt).toISOString().split("T")[0] : "unknown";
13233
- const created = Array.isArray(last.entriesCreated) ? last.entriesCreated.length : last.entriesCreated ?? 0;
13234
- const modified = Array.isArray(last.entriesModified) ? last.entriesModified.length : last.entriesModified ?? 0;
13235
- lines.push(`_Last session (${date}): ${created} created, ${modified} modified._`);
13236
- lines.push("");
13237
- }
13238
- if (recoveryBlock) {
13239
- lines.push(...formatRecoveryBlock(recoveryBlock));
13240
- }
13241
- lines.push("**What are you working on?** Tell me and I'll load relevant governance and context.");
13176
+ }
13177
+ if (orientView.architectureNotes?.length > 0) {
13178
+ lines.push("## Architecture notes");
13179
+ orientView.architectureNotes.forEach((e) => lines.push(fmt(e)));
13242
13180
  lines.push("");
13243
13181
  }
13182
+ const mapGovernanceEntry = (e) => ({
13183
+ entryId: e.entryId,
13184
+ name: e.name,
13185
+ description: typeof e.preview === "string" ? e.preview : void 0,
13186
+ tier: typeof e.tier === "number" ? e.tier : void 0,
13187
+ // Phase 4 (DEC-1141): thread provenance fields to buildOperatingProtocol.
13188
+ provenance: e.provenance,
13189
+ anchoredBy: typeof e.anchoredBy === "string" ? e.anchoredBy : void 0
13190
+ });
13191
+ const gov = orientView.governance ?? { principles: [], standards: [], businessRules: [] };
13192
+ lines.push(...buildOperatingProtocol({
13193
+ principles: (gov.principles ?? []).map(mapGovernanceEntry),
13194
+ standards: (gov.standards ?? []).map(mapGovernanceEntry),
13195
+ businessRules: (gov.businessRules ?? []).map(mapGovernanceEntry)
13196
+ }, task));
13197
+ }
13198
+ let allEntries = [];
13199
+ try {
13200
+ allEntries = await kernelQuery("chain.listEntries", {}) ?? [];
13201
+ } catch {
13244
13202
  }
13245
- const classificationGaps = readiness?.gaps?.filter((g) => g.id?.startsWith?.(PURPOSE_GAP_PREFIX)) ?? [];
13246
- if (classificationGaps.length > 0) {
13247
- lines.push("## Classification gaps");
13248
- lines.push("_Collections with weak purpose \u2014 entry classification may be inaccurate._");
13203
+ const plannedWork = buildPlannedWork(allEntries);
13204
+ if (hasPlannedWork(plannedWork)) {
13205
+ lines.push(...buildPlannedWorkSection(plannedWork, priorSessions, recoveryBlock));
13206
+ } else if (recoveryBlock) {
13207
+ lines.push(...formatRecoveryBlock(recoveryBlock));
13208
+ }
13209
+ } else {
13210
+ lines.push(`**Brain stage: ${orientStage}.**`);
13211
+ lines.push("");
13212
+ if (orientView?.activeWorkPackages?.length) {
13213
+ lines.push("## Active work packages \u2014 current scope");
13214
+ lines.push("_Work outside these work packages requires explicit user confirmation._");
13249
13215
  lines.push("");
13250
- for (const g of classificationGaps) {
13251
- lines.push(`- ${g.label ?? g.id?.replace?.("purpose-gap-", "") ?? "unknown"}`);
13216
+ for (const e of orientView.activeWorkPackages) {
13217
+ lines.push(fmt(e));
13252
13218
  }
13253
13219
  lines.push("");
13254
13220
  }
13255
- if (errors.length > 0) {
13256
- lines.push("## Errors");
13257
- for (const err of errors) lines.push(`- ${err}`);
13258
- lines.push("");
13259
- }
13260
- let orientationStatus = "no_session";
13261
- if (agentSessionId && hasTaskGrounding) {
13262
- const orientedOk = await markOrientedWithSnapshotFallback(agentSessionId, fullCoherenceSnapshot);
13263
- if (orientedOk) {
13264
- orientationStatus = "complete";
13265
- lines.push("---");
13266
- lines.push(`Orientation complete. Session ${agentSessionId}. Write tools available.`);
13267
- } else {
13268
- orientationStatus = "failed";
13269
- lines.push("---");
13270
- lines.push("_Warning: Could not mark session as oriented. Write tools may be restricted._");
13221
+ lines.push(...formatInitiativeStatusLines(orientView?.initiativeStatus));
13222
+ lines.push(...formatWorkstreamHealthLines(orientView?.workstreamHealth));
13223
+ lines.push(...formatWhatNeedsAttentionLines(orientView?.whatNeedsAttention));
13224
+ if (orientView?.trustMetrics) {
13225
+ const tm = orientView.trustMetrics;
13226
+ if (tm.verified > 0 || tm.unverified > 0) {
13227
+ const capNote = tm.scannedCap ? " (capped at 500)" : "";
13228
+ lines.push("## Trust metrics");
13229
+ lines.push(`_Entry verification status across workspace${capNote}._`);
13230
+ lines.push("");
13231
+ lines.push(`- **Verified:** ${tm.verified}`);
13232
+ lines.push(`- **Unverified:** ${tm.unverified}`);
13233
+ lines.push(`- **No status (pre-BET-240):** ${tm.noStatus}`);
13234
+ lines.push(`- **Total scanned:** ${tm.total}`);
13235
+ lines.push("");
13271
13236
  }
13272
- try {
13273
- await kernelMutation("chain.recordSessionSignal", {
13274
- sessionId: agentSessionId,
13275
- signalType: "immediate_context_load",
13276
- metadata: { source: "orient" }
13277
- });
13278
- } catch (err) {
13279
- process.stderr.write(`[MCP] recordSessionSignal failed: ${err.message}
13280
- `);
13237
+ }
13238
+ lines.push(...buildOperatingProtocol());
13239
+ if (fullCoherence) {
13240
+ lines.push(...fullCoherence.lines);
13241
+ }
13242
+ if (allCollections.length > 0) {
13243
+ const docCompleteness = buildDocCompletenessSection(allCollections);
13244
+ if (docCompleteness.errorCount > 0 || docCompleteness.warningCount > 0) {
13245
+ lines.push(...docCompleteness.lines);
13281
13246
  }
13282
- } else if (agentSessionId) {
13283
- orientationStatus = "task_required";
13284
- lines.push("---");
13285
- lines.push('Workspace orientation loaded. Write tools stay locked until you run `orient task="describe the work"`.');
13286
- } else {
13287
- lines.push("---");
13288
- lines.push("_No active agent session. Call `session action=start` to begin a tracked session._");
13289
13247
  }
13290
- const fullTruncated = orientView?._budget?.truncated ?? orientView?._truncated ?? false;
13291
- if (fullTruncated) {
13292
- const reasons = orientView?._budget?.truncationReasons;
13248
+ if (priorSessions.length > 0 && !recoveryBlock) {
13249
+ const last = priorSessions[0];
13250
+ const date = last.startedAt ? new Date(last.startedAt).toISOString().split("T")[0] : "unknown";
13251
+ const created = Array.isArray(last.entriesCreated) ? last.entriesCreated.length : last.entriesCreated ?? 0;
13252
+ const modified = Array.isArray(last.entriesModified) ? last.entriesModified.length : last.entriesModified ?? 0;
13253
+ lines.push(`_Last session (${date}): ${created} created, ${modified} modified._`);
13293
13254
  lines.push("");
13294
- if (reasons && reasons.length > 0) {
13295
- lines.push(`_Context truncated to fit tier budget: ${reasons.join(", ")}. Use tier=full for complete payload._`);
13296
- } else {
13297
- lines.push("_Context truncated to fit tier budget. Use tier=full for complete payload._");
13298
- }
13299
13255
  }
13300
- const fullResult = {
13301
- content: [{ type: "text", text: lines.join("\n") }],
13302
- structuredContent: success(
13303
- `Oriented (full). Stage: ${orientStage}. ${isLowReadiness ? "Low readiness \u2014 gaps remain." : "Ready."}`,
13304
- {
13305
- mode: "full",
13306
- stage: orientStage,
13307
- oriented: hasTaskGrounding ? isSessionOriented() : false,
13308
- sessionId: agentSessionId,
13309
- taskGroundingStatus: hasTaskGrounding ? "task_scoped" : task ? "missing_task_context" : "workspace_only",
13310
- taskGroundingRequired: !hasTaskGrounding,
13311
- domainRetrieval: orientView?.startup?.domainRetrieval,
13312
- orientationStatus,
13313
- nextStep: hasTaskGrounding ? void 0 : 'Run `orient task="describe the work"` before substantive work.',
13314
- ...orientView?._budget ? { _budget: orientView._budget } : {}
13315
- }
13316
- )
13317
- };
13318
- reportOrientWrapperBytes(fullResult, fullTruncated);
13319
- return fullResult;
13320
- })
13321
- );
13256
+ if (recoveryBlock) {
13257
+ lines.push(...formatRecoveryBlock(recoveryBlock));
13258
+ }
13259
+ lines.push("**What are you working on?** Tell me and I'll load relevant governance and context.");
13260
+ lines.push("");
13261
+ }
13262
+ }
13263
+ const classificationGaps = readiness?.gaps?.filter((g) => g.id?.startsWith?.(PURPOSE_GAP_PREFIX)) ?? [];
13264
+ if (classificationGaps.length > 0) {
13265
+ lines.push("## Classification gaps");
13266
+ lines.push("_Collections with weak purpose \u2014 entry classification may be inaccurate._");
13267
+ lines.push("");
13268
+ for (const g of classificationGaps) {
13269
+ lines.push(`- ${g.label ?? g.id?.replace?.("purpose-gap-", "") ?? "unknown"}`);
13270
+ }
13271
+ lines.push("");
13272
+ }
13273
+ if (errors.length > 0) {
13274
+ lines.push("## Errors");
13275
+ for (const err of errors) lines.push(`- ${err}`);
13276
+ lines.push("");
13277
+ }
13278
+ let orientationStatus = "no_session";
13279
+ if (agentSessionId && hasTaskGrounding) {
13280
+ const orientedOk = await markOrientedWithSnapshotFallback(agentSessionId, fullCoherenceSnapshot);
13281
+ if (orientedOk) {
13282
+ orientationStatus = "complete";
13283
+ lines.push("---");
13284
+ lines.push(`Orientation complete. Session ${agentSessionId}. Write tools available.`);
13285
+ } else {
13286
+ orientationStatus = "failed";
13287
+ lines.push("---");
13288
+ lines.push("_Warning: Could not mark session as oriented. Write tools may be restricted._");
13289
+ }
13290
+ try {
13291
+ await kernelMutation("chain.recordSessionSignal", {
13292
+ sessionId: agentSessionId,
13293
+ signalType: "immediate_context_load",
13294
+ metadata: { source: "orient" }
13295
+ });
13296
+ } catch (err) {
13297
+ process.stderr.write(`[MCP] recordSessionSignal failed: ${err.message}
13298
+ `);
13299
+ }
13300
+ } else if (agentSessionId) {
13301
+ orientationStatus = "task_required";
13302
+ lines.push("---");
13303
+ lines.push('Workspace orientation loaded. Write tools stay locked until you run `orient task="describe the work"`.');
13304
+ } else {
13305
+ lines.push("---");
13306
+ lines.push("_No active agent session. Call `session action=start` to begin a tracked session._");
13307
+ }
13308
+ const fullTruncated = orientView?._budget?.truncated ?? orientView?._truncated ?? false;
13309
+ if (fullTruncated) {
13310
+ const reasons = orientView?._budget?.truncationReasons;
13311
+ lines.push("");
13312
+ if (reasons && reasons.length > 0) {
13313
+ lines.push(`_Context truncated to fit tier budget: ${reasons.join(", ")}. Use tier=full for complete payload._`);
13314
+ } else {
13315
+ lines.push("_Context truncated to fit tier budget. Use tier=full for complete payload._");
13316
+ }
13317
+ }
13318
+ const fullResult = {
13319
+ content: [{ type: "text", text: lines.join("\n") }],
13320
+ structuredContent: success(
13321
+ `Oriented (full). Stage: ${orientStage}. ${isLowReadiness ? "Low readiness \u2014 gaps remain." : "Ready."}`,
13322
+ {
13323
+ mode: "full",
13324
+ stage: orientStage,
13325
+ oriented: hasTaskGrounding ? isSessionOriented() : false,
13326
+ sessionId: agentSessionId,
13327
+ taskGroundingStatus: hasTaskGrounding ? "task_scoped" : task ? "missing_task_context" : "workspace_only",
13328
+ taskGroundingRequired: !hasTaskGrounding,
13329
+ // STD-219 §4 (DEC-1147): machine-readable stub flag for agent consumers.
13330
+ ...orientView?.taskContext?.isGroundingStub ? { groundingStub: true } : {},
13331
+ domainRetrieval: orientView?.startup?.domainRetrieval,
13332
+ orientationStatus,
13333
+ nextStep: hasTaskGrounding ? void 0 : 'Run `orient task="describe the work"` before substantive work.',
13334
+ ...orientView?._budget ? { _budget: orientView._budget } : {}
13335
+ }
13336
+ )
13337
+ };
13338
+ reportOrientWrapperBytes(fullResult, fullTruncated, resolvedTier, taskIsMeaningful(task));
13339
+ return fullResult;
13322
13340
  }
13323
13341
 
13324
13342
  // src/tools/health.ts
@@ -15204,4 +15222,4 @@ export {
15204
15222
  createProductBrainServer,
15205
15223
  initFeatureFlags
15206
15224
  };
15207
- //# sourceMappingURL=chunk-ZPK5CSCQ.js.map
15225
+ //# sourceMappingURL=chunk-7BKN47NY.js.map