@productbrain/mcp 0.0.1-beta.951 → 0.0.1-beta.973
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.
|
@@ -4263,6 +4263,25 @@ function sanitizeEntryData(data) {
|
|
|
4263
4263
|
);
|
|
4264
4264
|
return Object.keys(filtered).length > 0 ? filtered : void 0;
|
|
4265
4265
|
}
|
|
4266
|
+
function renderWhyLine(e) {
|
|
4267
|
+
const why = typeof e.why === "string" ? e.why : "";
|
|
4268
|
+
if (e.whyQuality === "missing") {
|
|
4269
|
+
return { line: `**Why:** \u2014 (no rationale captured)`, why, whySourceKey: null };
|
|
4270
|
+
}
|
|
4271
|
+
if (why.length > 0) {
|
|
4272
|
+
const suffix = e.whyQuality === "restated" ? " (restated)" : "";
|
|
4273
|
+
const d = e.data ?? {};
|
|
4274
|
+
let whySourceKey = null;
|
|
4275
|
+
const kf = e.whyField;
|
|
4276
|
+
if ((kf === "rationale" || kf === "description") && typeof d[kf] === "string" && d[kf].trim().length > 0) {
|
|
4277
|
+
whySourceKey = kf;
|
|
4278
|
+
} else if (typeof d.rationale === "string" && d.rationale.trim().length > 0) {
|
|
4279
|
+
whySourceKey = "rationale";
|
|
4280
|
+
}
|
|
4281
|
+
return { line: `**Why:** ${why}${suffix}`, why, whySourceKey };
|
|
4282
|
+
}
|
|
4283
|
+
return { line: null, why, whySourceKey: null };
|
|
4284
|
+
}
|
|
4266
4285
|
var ENTRIES_ACTIONS = ["list", "get", "batch", "search"];
|
|
4267
4286
|
var entriesSchema = z4.object({
|
|
4268
4287
|
action: z4.enum(ENTRIES_ACTIONS).describe(
|
|
@@ -4291,6 +4310,9 @@ var entriesGetOutputSchema = z4.object({
|
|
|
4291
4310
|
verificationStatus: z4.string().optional(),
|
|
4292
4311
|
sourceRef: z4.string().optional(),
|
|
4293
4312
|
sourceExcerpt: z4.string().optional(),
|
|
4313
|
+
why: z4.string().optional(),
|
|
4314
|
+
// TEN-2191: quality of the captured WHY — 'rationale' | 'missing' | 'restated'.
|
|
4315
|
+
whyQuality: z4.enum(["rationale", "missing", "restated"]).optional(),
|
|
4294
4316
|
data: z4.record(z4.unknown()).optional(),
|
|
4295
4317
|
relations: z4.array(z4.object({
|
|
4296
4318
|
entryId: z4.string().optional(),
|
|
@@ -4299,7 +4321,7 @@ var entriesGetOutputSchema = z4.object({
|
|
|
4299
4321
|
direction: z4.string()
|
|
4300
4322
|
})).optional(),
|
|
4301
4323
|
labels: z4.array(z4.string()).optional()
|
|
4302
|
-
});
|
|
4324
|
+
}).passthrough();
|
|
4303
4325
|
var entriesListOutputSchema = z4.object({
|
|
4304
4326
|
entries: z4.array(z4.object({
|
|
4305
4327
|
entryId: z4.string(),
|
|
@@ -4332,8 +4354,11 @@ var entriesBatchOutputSchema = z4.object({
|
|
|
4332
4354
|
verificationStatus: z4.string().optional(),
|
|
4333
4355
|
sourceRef: z4.string().optional(),
|
|
4334
4356
|
sourceExcerpt: z4.string().optional(),
|
|
4357
|
+
// TEN-2191: mirror entriesGetOutputSchema — batch entries now carry why/whyQuality.
|
|
4358
|
+
why: z4.string().optional(),
|
|
4359
|
+
whyQuality: z4.enum(["rationale", "missing", "restated"]).optional(),
|
|
4335
4360
|
data: z4.record(z4.unknown()).optional()
|
|
4336
|
-
})),
|
|
4361
|
+
}).passthrough()),
|
|
4337
4362
|
total: z4.number()
|
|
4338
4363
|
});
|
|
4339
4364
|
function registerEntriesTools(server) {
|
|
@@ -4419,10 +4444,13 @@ async function handleGet(entryId) {
|
|
|
4419
4444
|
if (epistemic) {
|
|
4420
4445
|
lines.push(formatEpistemicLine(epistemic));
|
|
4421
4446
|
}
|
|
4447
|
+
const { line: whyLine, why, whySourceKey } = renderWhyLine(e);
|
|
4448
|
+
if (whyLine !== null) lines.push(whyLine);
|
|
4422
4449
|
const visibleData = sanitizeEntryData(e.data);
|
|
4423
|
-
|
|
4450
|
+
const filteredData = visibleData && whySourceKey ? Object.keys(visibleData).filter((k) => k !== whySourceKey).length > 0 ? Object.fromEntries(Object.entries(visibleData).filter(([k]) => k !== whySourceKey)) : void 0 : visibleData;
|
|
4451
|
+
if (filteredData) {
|
|
4424
4452
|
lines.push("");
|
|
4425
|
-
for (const [key, val] of Object.entries(
|
|
4453
|
+
for (const [key, val] of Object.entries(filteredData)) {
|
|
4426
4454
|
const display = typeof val === "string" ? val : JSON.stringify(val);
|
|
4427
4455
|
lines.push(`**${key}:** ${display}`);
|
|
4428
4456
|
}
|
|
@@ -4463,8 +4491,17 @@ async function handleGet(entryId) {
|
|
|
4463
4491
|
...e.verificationStatus ? { verificationStatus: String(e.verificationStatus) } : {},
|
|
4464
4492
|
...e.sourceRef ? { sourceRef: String(e.sourceRef) } : {},
|
|
4465
4493
|
...e.sourceExcerpt ? { sourceExcerpt: String(e.sourceExcerpt) } : {},
|
|
4494
|
+
// TEN-2191: surface the WHY and its quality in the structured payload too.
|
|
4495
|
+
...why.length > 0 ? { why } : {},
|
|
4496
|
+
...e.whyQuality ? { whyQuality: String(e.whyQuality) } : {},
|
|
4466
4497
|
entries: [{ entryId: e.entryId, name: e.name, status: e.status, ...e.workflowStatus ? { workflowStatus: e.workflowStatus } : {}, collectionName: String(e.collectionName ?? e.canonicalKey ?? "\u2014") }],
|
|
4467
|
-
|
|
4498
|
+
// Structured payload uses the same filteredData as the text render — the
|
|
4499
|
+
// WHY-source field (rationale or description) is intentionally omitted from
|
|
4500
|
+
// `data` because its full value is carried in the top-level `why` field
|
|
4501
|
+
// (no information loss; `why` is the complete untruncated extractWhy result).
|
|
4502
|
+
// This restores true STD-218 text/structured parity and removes the duplication
|
|
4503
|
+
// that commit 8f3b1664 left in the structured payload. (Codex finding, TEN-2191.)
|
|
4504
|
+
...filteredData ? { data: filteredData } : {},
|
|
4468
4505
|
...Array.isArray(e.relations) && e.relations.length > 0 ? {
|
|
4469
4506
|
relations: e.relations.map((r) => ({
|
|
4470
4507
|
...r.otherEntryId ? { entryId: r.otherEntryId } : {},
|
|
@@ -4521,10 +4558,13 @@ async function handleBatch(entryIds) {
|
|
|
4521
4558
|
if (entry.sourceExcerpt) {
|
|
4522
4559
|
lines.push(`**Source excerpt:** ${entry.sourceExcerpt}`);
|
|
4523
4560
|
}
|
|
4561
|
+
const { line: whyLine, whySourceKey } = renderWhyLine(entry);
|
|
4562
|
+
if (whyLine !== null) lines.push(whyLine);
|
|
4524
4563
|
const visibleData = sanitizeEntryData(entry.data);
|
|
4525
|
-
|
|
4564
|
+
const filteredData = visibleData && whySourceKey ? Object.keys(visibleData).filter((k) => k !== whySourceKey).length > 0 ? Object.fromEntries(Object.entries(visibleData).filter(([k]) => k !== whySourceKey)) : void 0 : visibleData;
|
|
4565
|
+
if (filteredData) {
|
|
4526
4566
|
lines.push("");
|
|
4527
|
-
for (const [key, val] of Object.entries(
|
|
4567
|
+
for (const [key, val] of Object.entries(filteredData)) {
|
|
4528
4568
|
const display = typeof val === "string" ? val : JSON.stringify(val);
|
|
4529
4569
|
lines.push(`**${key}:** ${display}`);
|
|
4530
4570
|
}
|
|
@@ -4555,6 +4595,9 @@ async function handleBatch(entryIds) {
|
|
|
4555
4595
|
}
|
|
4556
4596
|
const structuredEntries = results.filter((r) => !r.error && r.entry).map((r) => {
|
|
4557
4597
|
const entry = r.entry;
|
|
4598
|
+
const { why: entryWhy, whySourceKey: entryWhySourceKey } = renderWhyLine(entry);
|
|
4599
|
+
const entryVisibleData = sanitizeEntryData(entry.data);
|
|
4600
|
+
const entryFilteredData = entryVisibleData && entryWhySourceKey ? Object.keys(entryVisibleData).filter((k) => k !== entryWhySourceKey).length > 0 ? Object.fromEntries(Object.entries(entryVisibleData).filter(([k]) => k !== entryWhySourceKey)) : void 0 : entryVisibleData;
|
|
4558
4601
|
return {
|
|
4559
4602
|
entryId: String(entry.entryId ?? ""),
|
|
4560
4603
|
name: String(entry.name ?? ""),
|
|
@@ -4567,7 +4610,10 @@ async function handleBatch(entryIds) {
|
|
|
4567
4610
|
...entry.sourceRef ? { sourceRef: String(entry.sourceRef) } : {},
|
|
4568
4611
|
...entry.sourceExcerpt ? { sourceExcerpt: String(entry.sourceExcerpt) } : {},
|
|
4569
4612
|
...entry.workflowStatus ? { workflowStatus: String(entry.workflowStatus) } : {},
|
|
4570
|
-
|
|
4613
|
+
// TEN-2191: surface why/whyQuality in structured payload — mirrors handleGet.
|
|
4614
|
+
...entryWhy.length > 0 ? { why: entryWhy } : {},
|
|
4615
|
+
...entry.whyQuality ? { whyQuality: String(entry.whyQuality) } : {},
|
|
4616
|
+
...entryFilteredData ? { data: entryFilteredData } : {}
|
|
4571
4617
|
};
|
|
4572
4618
|
});
|
|
4573
4619
|
const total = structuredEntries.length;
|
|
@@ -12527,11 +12573,16 @@ function replaceVocabTokens(body, workspaceCtx, collectionCtxMap) {
|
|
|
12527
12573
|
|
|
12528
12574
|
// src/tools/orient.ts
|
|
12529
12575
|
var PURPOSE_GAP_PREFIX = "purpose-gap-";
|
|
12530
|
-
|
|
12576
|
+
var NON_MEANINGFUL_TASK_RE = /^[\s]*$/u;
|
|
12577
|
+
function taskIsMeaningful(task) {
|
|
12578
|
+
if (typeof task !== "string") return false;
|
|
12579
|
+
return !NON_MEANINGFUL_TASK_RE.test(task);
|
|
12580
|
+
}
|
|
12581
|
+
function reportOrientWrapperBytes(toolResult, truncated, tier, taskProvided) {
|
|
12531
12582
|
try {
|
|
12532
12583
|
const fullToolOutput = JSON.stringify({ content: toolResult.content ?? [] });
|
|
12533
12584
|
const bytes = Buffer.byteLength(fullToolOutput, "utf8");
|
|
12534
|
-
void kernelMutation("agent.reportOrientMetric", { bytes, truncated }).catch(() => {
|
|
12585
|
+
void kernelMutation("agent.reportOrientMetric", { bytes, truncated, tier, taskProvided }).catch(() => {
|
|
12535
12586
|
});
|
|
12536
12587
|
} catch {
|
|
12537
12588
|
}
|
|
@@ -12584,7 +12635,7 @@ var VALID_TASK_DOMAINS = [
|
|
|
12584
12635
|
var orientSchema = z21.object({
|
|
12585
12636
|
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
12637
|
tier: z21.enum(["summary", "standard", "full"]).optional().describe(
|
|
12587
|
-
"Payload depth. summary
|
|
12638
|
+
"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
12639
|
),
|
|
12589
12640
|
task: z21.string().optional().describe("Natural-language task description for task-scoped context. When provided, orient returns scored, relevant entries for the task."),
|
|
12590
12641
|
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 +12664,725 @@ function registerOrientTool(server) {
|
|
|
12613
12664
|
"orient",
|
|
12614
12665
|
{
|
|
12615
12666
|
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
|
|
12667
|
+
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
12668
|
inputSchema: orientSchema,
|
|
12618
12669
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
12619
12670
|
},
|
|
12620
|
-
thinWrapper(
|
|
12621
|
-
|
|
12622
|
-
|
|
12623
|
-
|
|
12624
|
-
|
|
12625
|
-
|
|
12626
|
-
|
|
12627
|
-
|
|
12628
|
-
|
|
12629
|
-
|
|
12630
|
-
|
|
12631
|
-
|
|
12632
|
-
|
|
12633
|
-
|
|
12634
|
-
|
|
12635
|
-
|
|
12636
|
-
|
|
12637
|
-
|
|
12638
|
-
|
|
12639
|
-
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12671
|
+
thinWrapper(_handleOrient)
|
|
12672
|
+
);
|
|
12673
|
+
}
|
|
12674
|
+
async function _handleOrient({ mode = "full", tier, task, scope }) {
|
|
12675
|
+
const errors = [];
|
|
12676
|
+
const callTier = tier ?? (mode === "brief" ? "summary" : void 0);
|
|
12677
|
+
const resolvedTier = callTier ?? (taskIsMeaningful(task) ? "summary" : "standard");
|
|
12678
|
+
if (scope && !task) {
|
|
12679
|
+
errors.push("--scope requires --task to filter governance. Scope was ignored.");
|
|
12680
|
+
}
|
|
12681
|
+
const agentSessionId = getAgentSessionId();
|
|
12682
|
+
if (isSessionOriented() && mode === "brief" && !task) {
|
|
12683
|
+
return {
|
|
12684
|
+
content: [{
|
|
12685
|
+
type: "text",
|
|
12686
|
+
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."
|
|
12687
|
+
}],
|
|
12688
|
+
structuredContent: success(
|
|
12689
|
+
"Already oriented. Session active, writes unlocked.",
|
|
12690
|
+
{
|
|
12691
|
+
alreadyOriented: true,
|
|
12692
|
+
sessionId: agentSessionId,
|
|
12693
|
+
taskGroundingStatus: "workspace_only",
|
|
12694
|
+
taskGroundingRequired: true,
|
|
12695
|
+
nextStep: 'Run `orient task="describe the work"` before substantive work.'
|
|
12696
|
+
}
|
|
12697
|
+
)
|
|
12698
|
+
};
|
|
12699
|
+
}
|
|
12700
|
+
let wsCtx = null;
|
|
12701
|
+
try {
|
|
12702
|
+
wsCtx = await getWorkspaceContext();
|
|
12703
|
+
} catch (e) {
|
|
12704
|
+
errors.push(`Workspace: ${e instanceof Error ? e.message : String(e)}`);
|
|
12705
|
+
}
|
|
12706
|
+
let priorSessions = [];
|
|
12707
|
+
let recoveryBlock = null;
|
|
12708
|
+
let orientView = null;
|
|
12709
|
+
try {
|
|
12710
|
+
const orientArgs = {};
|
|
12711
|
+
if (task) orientArgs.task = task;
|
|
12712
|
+
if (scope) orientArgs.scope = scope;
|
|
12713
|
+
if (callTier) orientArgs.tier = callTier;
|
|
12714
|
+
orientView = await kernelQuery("chain.getOrientView", orientArgs);
|
|
12715
|
+
} catch {
|
|
12716
|
+
}
|
|
12717
|
+
let vocabCtx;
|
|
12718
|
+
try {
|
|
12719
|
+
const vocab = await kernelQuery("chain.getVocabulary", {});
|
|
12720
|
+
if (vocab?.collectionLabels || vocab?.collectionDefaults) {
|
|
12721
|
+
vocabCtx = {
|
|
12722
|
+
...vocab.collectionLabels ? { collectionLabels: vocab.collectionLabels } : {},
|
|
12723
|
+
...vocab.collectionDefaults ? { collectionDefaults: vocab.collectionDefaults } : {}
|
|
12724
|
+
};
|
|
12725
|
+
}
|
|
12726
|
+
} catch {
|
|
12727
|
+
}
|
|
12728
|
+
if (orientView) {
|
|
12729
|
+
priorSessions = orientView.priorSessions ?? [];
|
|
12730
|
+
recoveryBlock = orientView.recoveryBlock ?? null;
|
|
12731
|
+
}
|
|
12732
|
+
const hasTaskGrounding = Boolean(task && orientView?.taskContext?.context?.length > 0);
|
|
12733
|
+
if (wsCtx && hasTaskGrounding && orientView?.writeBackHints) {
|
|
12734
|
+
const hints = Array.isArray(orientView.writeBackHints) ? orientView.writeBackHints : [];
|
|
12735
|
+
if (hints.length > 0) {
|
|
12736
|
+
trackWriteBackHintServed(wsCtx.workspaceId, {
|
|
12737
|
+
hint_count: hints.length,
|
|
12738
|
+
has_task: !!task
|
|
12739
|
+
});
|
|
12740
|
+
}
|
|
12741
|
+
}
|
|
12742
|
+
let openTensions = [];
|
|
12743
|
+
try {
|
|
12744
|
+
const tensions = await kernelQuery("chain.listEntries", { collectionSlug: "tensions" });
|
|
12745
|
+
openTensions = (tensions ?? []).filter((e) => e.workflowStatus === "open");
|
|
12746
|
+
} catch {
|
|
12747
|
+
}
|
|
12748
|
+
let allCollections = [];
|
|
12749
|
+
try {
|
|
12750
|
+
allCollections = await kernelQuery("chain.listCollections") ?? [];
|
|
12751
|
+
} catch {
|
|
12752
|
+
}
|
|
12753
|
+
let readiness = null;
|
|
12754
|
+
try {
|
|
12755
|
+
readiness = await kernelQuery("chain.workspaceReadiness");
|
|
12756
|
+
} catch (e) {
|
|
12757
|
+
errors.push(`Readiness: ${e instanceof Error ? e.message : String(e)}`);
|
|
12758
|
+
}
|
|
12759
|
+
if (readiness?.stage === "blank") {
|
|
12760
|
+
const scanLines = [
|
|
12761
|
+
`# Welcome to ${wsCtx?.workspaceName ?? "your workspace"}`,
|
|
12762
|
+
"",
|
|
12763
|
+
"Your workspace is fresh \u2014 let's set it up.",
|
|
12764
|
+
"",
|
|
12765
|
+
"**Recommended:** call the `start` tool instead of `orient` for the best first-run experience.",
|
|
12766
|
+
"It will guide you through setting up your workspace \u2014 you can tell me about your product, scan your codebase, or use a preset.",
|
|
12767
|
+
"",
|
|
12768
|
+
"Or tell me about your product and I'll start capturing knowledge directly."
|
|
12769
|
+
];
|
|
12770
|
+
let oriented = false;
|
|
12771
|
+
let orientationStatus2 = "no_session";
|
|
12772
|
+
if (agentSessionId) {
|
|
12654
12773
|
try {
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
orientView = await kernelQuery("chain.getOrientView", orientArgs);
|
|
12774
|
+
await kernelCall("agent.markOriented", { sessionId: agentSessionId });
|
|
12775
|
+
setSessionOriented(true);
|
|
12776
|
+
oriented = true;
|
|
12777
|
+
orientationStatus2 = "complete";
|
|
12660
12778
|
} catch {
|
|
12779
|
+
orientationStatus2 = "failed";
|
|
12661
12780
|
}
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
|
|
12781
|
+
}
|
|
12782
|
+
const blankResult = {
|
|
12783
|
+
content: [{ type: "text", text: scanLines.join("\n") }],
|
|
12784
|
+
structuredContent: success(
|
|
12785
|
+
"Workspace is blank. Use the start_pb tool for guided setup.",
|
|
12786
|
+
{ stage: "blank", readinessScore: readiness?.score ?? 0, oriented, orientationStatus: orientationStatus2, redirectHint: "Use the `start_pb` tool for the full guided setup experience." },
|
|
12787
|
+
[{ tool: "start_pb", description: "Guided workspace setup", parameters: {} }]
|
|
12788
|
+
)
|
|
12789
|
+
};
|
|
12790
|
+
reportOrientWrapperBytes(blankResult, false, resolvedTier, taskIsMeaningful(task));
|
|
12791
|
+
return blankResult;
|
|
12792
|
+
}
|
|
12793
|
+
const lines = [];
|
|
12794
|
+
const isLowReadiness = readiness && readiness.score < 50;
|
|
12795
|
+
if (wsCtx) {
|
|
12796
|
+
lines.push(`# ${wsCtx.workspaceName}`);
|
|
12797
|
+
lines.push(`_Workspace \`${wsCtx.workspaceSlug}\` \u2014 Product Brain is healthy._`);
|
|
12798
|
+
} else {
|
|
12799
|
+
lines.push("# Workspace");
|
|
12800
|
+
lines.push("_Could not resolve workspace._");
|
|
12801
|
+
}
|
|
12802
|
+
lines.push("");
|
|
12803
|
+
lines.push(...taskGroundingWarningLines(task, hasTaskGrounding));
|
|
12804
|
+
if (mode === "brief") {
|
|
12805
|
+
const briefStage = readiness?.stage ?? (readiness?.score != null ? readiness.score < 50 ? "seeded" : "grounded" : "unknown");
|
|
12806
|
+
lines.push(`Brain stage: ${briefStage}`);
|
|
12807
|
+
if (orientView?.strategicContext) {
|
|
12808
|
+
const sc = orientView.strategicContext;
|
|
12809
|
+
if (sc.vision) lines.push(`Vision: ${sc.vision}`);
|
|
12810
|
+
if (sc.purpose) lines.push(`Purpose: ${sc.purpose}`);
|
|
12811
|
+
if (sc.productAreaCount != null && sc.productAreaCount > 0) {
|
|
12812
|
+
lines.push(`Product areas (${sc.productAreaCount}): ${(sc.productAreas ?? []).join(", ")}`);
|
|
12813
|
+
}
|
|
12814
|
+
if (sc.playingFieldCount != null && sc.playingFieldCount > 0) {
|
|
12815
|
+
lines.push(`Playing field (${sc.playingFieldCount}): ${(sc.playingField ?? []).join(", ")}`);
|
|
12816
|
+
}
|
|
12817
|
+
const wpPlural = getCollectionLabel("work_package", "plural", vocabCtx);
|
|
12818
|
+
lines.push(`${sc.activeBetCount} active ${wpPlural}, ${sc.activeTensionCount} tension(s).`);
|
|
12819
|
+
}
|
|
12820
|
+
if (orientView?.taskContext && orientView.taskContext.context.length > 0) {
|
|
12821
|
+
lines.push(`Task context: ${orientView.taskContext.totalFound} relevant entries (${orientView.taskContext.confidence} confidence).`);
|
|
12822
|
+
if (orientView.taskContext.isGroundingStub && orientView.taskContext.groundingNote) {
|
|
12823
|
+
lines.push(`\u26A0\uFE0F ${orientView.taskContext.groundingNote}`);
|
|
12824
|
+
}
|
|
12825
|
+
}
|
|
12826
|
+
if (orientView?.startup?.domainRetrieval) {
|
|
12827
|
+
const retrieval = orientView.startup.domainRetrieval;
|
|
12828
|
+
const scopedTo = retrieval.resolvedDomainSlug ? ` (${retrieval.resolvedDomainSlug})` : "";
|
|
12829
|
+
lines.push(`Domain retrieval: ${retrieval.state}${scopedTo}`);
|
|
12830
|
+
if (retrieval.activeSource) lines.push(`Active source: ${retrieval.activeSource}`);
|
|
12831
|
+
if (retrieval.fallbackReason) lines.push(`Fallback: ${retrieval.fallbackReason}`);
|
|
12832
|
+
if (retrieval.fallbackAction) lines.push(`Action: ${retrieval.fallbackAction}`);
|
|
12833
|
+
if (retrieval.evidenceGap) lines.push(`Evidence gap: ${retrieval.evidenceGap}`);
|
|
12834
|
+
if (retrieval.directRatifiedCount != null || retrieval.inheritedRatifiedCount != null || retrieval.orgFallbackCount != null) {
|
|
12835
|
+
lines.push(`Domain relation evidence: ${retrieval.directRatifiedCount ?? 0} direct, ${retrieval.inheritedRatifiedCount ?? 0} inherited, ${retrieval.orgFallbackCount ?? 0} org fallback`);
|
|
12836
|
+
}
|
|
12837
|
+
}
|
|
12838
|
+
if (orientView?.writeBackHints && orientView.writeBackHints.length > 0) {
|
|
12839
|
+
lines.push("");
|
|
12840
|
+
lines.push("Write-back hints (what to capture this session):");
|
|
12841
|
+
for (const h of orientView.writeBackHints) {
|
|
12842
|
+
lines.push(` ${h.collectionSlug}: ${h.hint}`);
|
|
12672
12843
|
}
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
|
|
12676
|
-
|
|
12677
|
-
|
|
12678
|
-
|
|
12679
|
-
|
|
12680
|
-
if (hints.length > 0) {
|
|
12681
|
-
trackWriteBackHintServed(wsCtx.workspaceId, {
|
|
12682
|
-
hint_count: hints.length,
|
|
12683
|
-
has_task: !!task
|
|
12684
|
-
});
|
|
12685
|
-
}
|
|
12844
|
+
}
|
|
12845
|
+
if (orientView?.activeWorkPackages?.length > 0) {
|
|
12846
|
+
for (const e of orientView.activeWorkPackages) {
|
|
12847
|
+
const tensions = e.linkedTensions;
|
|
12848
|
+
const tensionPart = tensions?.length ? ` \u2014 ${tensions.map((t) => `${t.entryId ?? t.name} (${t.severity ?? "\u2014"})`).join(", ")}` : "";
|
|
12849
|
+
const originPart = e.origin ? ` (origin: ${e.origin})` : "";
|
|
12850
|
+
lines.push(`- \`${e.entryId ?? e._id}\` ${e.name}${originPart}${tensionPart}`);
|
|
12686
12851
|
}
|
|
12687
|
-
|
|
12688
|
-
|
|
12689
|
-
|
|
12690
|
-
|
|
12691
|
-
|
|
12852
|
+
}
|
|
12853
|
+
if (orientView?.trustMetrics) {
|
|
12854
|
+
const tm = orientView.trustMetrics;
|
|
12855
|
+
if (tm.unverified > 0 || tm.verified > 0) {
|
|
12856
|
+
const capNote = tm.scannedCap ? "+" : "";
|
|
12857
|
+
lines.push(`Trust: ${tm.verified} verified, ${tm.unverified} unverified, ${tm.noStatus} no-status (${tm.total}${capNote} scanned).`);
|
|
12692
12858
|
}
|
|
12693
|
-
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
-
|
|
12859
|
+
}
|
|
12860
|
+
const briefWna = formatWhatNeedsAttentionBrief(orientView?.whatNeedsAttention);
|
|
12861
|
+
if (briefWna.length > 0) {
|
|
12862
|
+
lines.push("");
|
|
12863
|
+
lines.push(...briefWna);
|
|
12864
|
+
}
|
|
12865
|
+
const briefGaps = readiness?.gaps ?? [];
|
|
12866
|
+
if (briefGaps.length > 0) {
|
|
12867
|
+
const oneLiner = formatGapOneLiner(briefGaps[0]);
|
|
12868
|
+
if (oneLiner) lines.push(oneLiner);
|
|
12869
|
+
}
|
|
12870
|
+
const briefClassificationGaps = briefGaps.filter((g) => g.id?.startsWith?.(PURPOSE_GAP_PREFIX));
|
|
12871
|
+
if (briefClassificationGaps.length > 0) {
|
|
12872
|
+
lines.push(`${briefClassificationGaps.length} collection(s) with weak purpose \u2014 classification may be inaccurate.`);
|
|
12873
|
+
}
|
|
12874
|
+
if (recoveryBlock) {
|
|
12875
|
+
lines.push("");
|
|
12876
|
+
lines.push(...formatRecoveryBlock(recoveryBlock));
|
|
12877
|
+
} else if (priorSessions.length > 0) {
|
|
12878
|
+
const last = priorSessions[0];
|
|
12879
|
+
const date = last.startedAt ? new Date(last.startedAt).toISOString().split("T")[0] : "unknown";
|
|
12880
|
+
const created = Array.isArray(last.entriesCreated) ? last.entriesCreated.length : last.entriesCreated ?? 0;
|
|
12881
|
+
const modified = Array.isArray(last.entriesModified) ? last.entriesModified.length : last.entriesModified ?? 0;
|
|
12882
|
+
lines.push(`Last session (${date}): ${created} created, ${modified} modified`);
|
|
12883
|
+
}
|
|
12884
|
+
let coherenceSnapshot;
|
|
12885
|
+
const coherence = buildCoherenceSection();
|
|
12886
|
+
if (coherence) {
|
|
12887
|
+
lines.push("");
|
|
12888
|
+
lines.push(...coherence.lines);
|
|
12889
|
+
coherenceSnapshot = coherence.snapshot;
|
|
12890
|
+
}
|
|
12891
|
+
if (allCollections.length > 0) {
|
|
12892
|
+
const docCompleteness = buildDocCompletenessSection(allCollections);
|
|
12893
|
+
if (docCompleteness.errorCount > 0 || docCompleteness.warningCount > 0) {
|
|
12894
|
+
lines.push(...docCompleteness.lines);
|
|
12697
12895
|
}
|
|
12698
|
-
|
|
12699
|
-
|
|
12700
|
-
|
|
12701
|
-
|
|
12702
|
-
|
|
12896
|
+
}
|
|
12897
|
+
if (orientView) {
|
|
12898
|
+
lines.push("");
|
|
12899
|
+
if (task) {
|
|
12900
|
+
const mapGovernanceEntry = (e) => ({
|
|
12901
|
+
entryId: e.entryId,
|
|
12902
|
+
name: e.name,
|
|
12903
|
+
description: typeof e.preview === "string" ? e.preview : void 0,
|
|
12904
|
+
tier: typeof e.tier === "number" ? e.tier : void 0,
|
|
12905
|
+
// Phase 4 (DEC-1141): thread provenance fields to buildOperatingProtocol.
|
|
12906
|
+
provenance: e.provenance,
|
|
12907
|
+
anchoredBy: typeof e.anchoredBy === "string" ? e.anchoredBy : void 0
|
|
12908
|
+
});
|
|
12909
|
+
const gov = orientView.governance ?? { principles: [], standards: [], businessRules: [] };
|
|
12910
|
+
lines.push(...buildOperatingProtocol({
|
|
12911
|
+
principles: (gov.principles ?? []).map(mapGovernanceEntry),
|
|
12912
|
+
standards: (gov.standards ?? []).map(mapGovernanceEntry),
|
|
12913
|
+
businessRules: (gov.businessRules ?? []).map(mapGovernanceEntry)
|
|
12914
|
+
}, task));
|
|
12915
|
+
} else {
|
|
12916
|
+
lines.push(...buildOperatingProtocol());
|
|
12703
12917
|
}
|
|
12704
|
-
|
|
12705
|
-
|
|
12706
|
-
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
12713
|
-
|
|
12714
|
-
|
|
12715
|
-
|
|
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;
|
|
12918
|
+
}
|
|
12919
|
+
let orientationStatus2 = "no_session";
|
|
12920
|
+
if (agentSessionId && hasTaskGrounding) {
|
|
12921
|
+
const orientedOk = await markOrientedWithSnapshotFallback(agentSessionId, coherenceSnapshot);
|
|
12922
|
+
if (orientedOk) {
|
|
12923
|
+
orientationStatus2 = "complete";
|
|
12924
|
+
lines.push("---");
|
|
12925
|
+
lines.push(`Orientation complete. Session ${agentSessionId}. Write tools available.`);
|
|
12926
|
+
} else {
|
|
12927
|
+
orientationStatus2 = "failed";
|
|
12928
|
+
lines.push("---");
|
|
12929
|
+
lines.push("_Warning: Could not mark session as oriented. Write tools may be restricted._");
|
|
12737
12930
|
}
|
|
12738
|
-
|
|
12739
|
-
|
|
12740
|
-
|
|
12741
|
-
|
|
12742
|
-
|
|
12931
|
+
} else if (agentSessionId) {
|
|
12932
|
+
orientationStatus2 = "task_required";
|
|
12933
|
+
lines.push("---");
|
|
12934
|
+
lines.push('Workspace orientation loaded. Write tools stay locked until you run `orient task="describe the work"`.');
|
|
12935
|
+
} else {
|
|
12936
|
+
lines.push("---");
|
|
12937
|
+
lines.push("_No active agent session. Call `session action=start` to begin._");
|
|
12938
|
+
}
|
|
12939
|
+
const briefTruncated = orientView?._budget?.truncated ?? orientView?._truncated ?? false;
|
|
12940
|
+
if (briefTruncated) {
|
|
12941
|
+
const reasons = orientView?._budget?.truncationReasons;
|
|
12942
|
+
lines.push("");
|
|
12943
|
+
if (reasons && reasons.length > 0) {
|
|
12944
|
+
lines.push(`_Context truncated to fit tier budget: ${reasons.join(", ")}. Use tier=full for complete payload._`);
|
|
12743
12945
|
} else {
|
|
12744
|
-
lines.push("
|
|
12745
|
-
lines.push("_Could not resolve workspace._");
|
|
12946
|
+
lines.push("_Context truncated to fit tier budget. Use tier=full for complete payload._");
|
|
12746
12947
|
}
|
|
12948
|
+
}
|
|
12949
|
+
if (errors.length > 0) {
|
|
12950
|
+
lines.push("");
|
|
12951
|
+
for (const err of errors) lines.push(`- ${err}`);
|
|
12952
|
+
}
|
|
12953
|
+
const briefResult = {
|
|
12954
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
12955
|
+
structuredContent: success(
|
|
12956
|
+
`Oriented (brief). Stage: ${readiness?.stage ?? "unknown"}.`,
|
|
12957
|
+
{
|
|
12958
|
+
mode: "brief",
|
|
12959
|
+
stage: readiness?.stage ?? "unknown",
|
|
12960
|
+
oriented: hasTaskGrounding ? isSessionOriented() : false,
|
|
12961
|
+
sessionId: agentSessionId,
|
|
12962
|
+
taskGroundingStatus: hasTaskGrounding ? "task_scoped" : task ? "missing_task_context" : "workspace_only",
|
|
12963
|
+
taskGroundingRequired: !hasTaskGrounding,
|
|
12964
|
+
// STD-219 §4 (DEC-1147): machine-readable stub flag for agent consumers.
|
|
12965
|
+
...orientView?.taskContext?.isGroundingStub ? { groundingStub: true } : {},
|
|
12966
|
+
orientationStatus: orientationStatus2,
|
|
12967
|
+
nextStep: hasTaskGrounding ? void 0 : 'Run `orient task="describe the work"` before substantive work.',
|
|
12968
|
+
...orientView?._budget ? { _budget: orientView._budget } : {}
|
|
12969
|
+
}
|
|
12970
|
+
)
|
|
12971
|
+
};
|
|
12972
|
+
reportOrientWrapperBytes(briefResult, briefTruncated, resolvedTier, taskIsMeaningful(task));
|
|
12973
|
+
return briefResult;
|
|
12974
|
+
}
|
|
12975
|
+
const orientStage = readiness?.stage ?? "seeded";
|
|
12976
|
+
if (isLowReadiness && wsCtx?.createdAt) {
|
|
12977
|
+
const ageDays = Math.floor((Date.now() - wsCtx.createdAt) / (1e3 * 60 * 60 * 24));
|
|
12978
|
+
if (ageDays >= 30) {
|
|
12979
|
+
lines.push(`Your workspace has been around for ${ageDays} days and is still at the **${orientStage}** stage.`);
|
|
12980
|
+
lines.push("Let's close the gaps \u2014 or if the current structure doesn't fit, we can reshape it.");
|
|
12747
12981
|
lines.push("");
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
|
|
12752
|
-
|
|
12753
|
-
|
|
12754
|
-
|
|
12755
|
-
|
|
12756
|
-
|
|
12757
|
-
|
|
12982
|
+
}
|
|
12983
|
+
}
|
|
12984
|
+
let fullCoherenceSnapshot;
|
|
12985
|
+
if (isLowReadiness) {
|
|
12986
|
+
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._";
|
|
12987
|
+
const gaps = readiness.gaps ?? [];
|
|
12988
|
+
if (gaps.length > 0) {
|
|
12989
|
+
const gapCtx = {
|
|
12990
|
+
stage: orientStage,
|
|
12991
|
+
passedChecks: readiness.passedChecks ?? 0,
|
|
12992
|
+
totalChecks: readiness.totalChecks ?? 0,
|
|
12993
|
+
score: readiness.score ?? 0
|
|
12994
|
+
};
|
|
12995
|
+
lines.push(formatTopGapPrompt(gaps[0], gaps.length - 1, gapCtx));
|
|
12996
|
+
lines.push("");
|
|
12997
|
+
lines.push(captureBehaviorNote);
|
|
12998
|
+
lines.push("");
|
|
12999
|
+
const remainingGaps = gaps.length - 1;
|
|
13000
|
+
if (remainingGaps > 0 || openTensions.length > 0) {
|
|
13001
|
+
const parts = [];
|
|
13002
|
+
if (remainingGaps > 0) parts.push(`${remainingGaps} more area${remainingGaps === 1 ? "" : "s"} to cover`);
|
|
13003
|
+
if (openTensions.length > 0) parts.push(`${openTensions.length} open tension${openTensions.length === 1 ? "" : "s"}`);
|
|
13004
|
+
lines.push(`_${parts.join(" and ")} \u2014 ask for full status to see everything._`);
|
|
13005
|
+
lines.push("");
|
|
13006
|
+
}
|
|
13007
|
+
}
|
|
13008
|
+
lines.push("_Need a collection that doesn't exist yet? Just ask \u2014 I'll set it up._");
|
|
13009
|
+
lines.push("");
|
|
13010
|
+
} else if (readiness) {
|
|
13011
|
+
const fmt = (e) => {
|
|
13012
|
+
const type = e.canonicalKey ?? "generic";
|
|
13013
|
+
const stratum = e.stratum ?? "?";
|
|
13014
|
+
const confidencePart = e.confidence ? ` [confidence: ${e.confidence}]` : "";
|
|
13015
|
+
const reviewOverdue = e.reviewAt && new Date(e.reviewAt).getTime() < Date.now();
|
|
13016
|
+
const overduePart = reviewOverdue ? " [review overdue]" : "";
|
|
13017
|
+
const originPart = e.origin ? ` (origin: ${e.origin})` : "";
|
|
13018
|
+
const mark = provenanceMark(e.provenance);
|
|
13019
|
+
const anchorSuffix = e.anchoredBy ? ` (${e.anchoredBy})` : "";
|
|
13020
|
+
return `- ${mark}\`${e.entryId ?? e._id}\` [${type} \xB7 ${stratum}] ${e.name}${anchorSuffix}${originPart}${confidencePart}${overduePart}`;
|
|
13021
|
+
};
|
|
13022
|
+
const fullCoherence = buildCoherenceSection();
|
|
13023
|
+
if (fullCoherence) {
|
|
13024
|
+
fullCoherenceSnapshot = fullCoherence.snapshot;
|
|
13025
|
+
}
|
|
13026
|
+
if (task) {
|
|
13027
|
+
lines.push(`**Brain stage: ${orientStage}.** Working on: **${task}**`);
|
|
13028
|
+
lines.push("");
|
|
13029
|
+
if (orientView?.strategicContext) {
|
|
13030
|
+
const sc = orientView.strategicContext;
|
|
13031
|
+
lines.push("## Strategic Context");
|
|
13032
|
+
if (sc.vision) lines.push(`**Vision:** ${sc.vision}`);
|
|
13033
|
+
if (sc.purpose) lines.push(`**Purpose:** ${sc.purpose}`);
|
|
13034
|
+
if (sc.productAreaCount != null && sc.productAreaCount > 0) {
|
|
13035
|
+
lines.push(`**Product areas (${sc.productAreaCount}):** ${(sc.productAreas ?? []).join(", ")}`);
|
|
13036
|
+
}
|
|
13037
|
+
if (sc.playingFieldCount != null && sc.playingFieldCount > 0) {
|
|
13038
|
+
lines.push(`**Playing field (${sc.playingFieldCount}):** ${(sc.playingField ?? []).join(", ")}`);
|
|
13039
|
+
}
|
|
13040
|
+
const currentWP = sc.currentWorkPackage;
|
|
13041
|
+
const wpSingularFull = getCollectionLabel("work_package", "singular", vocabCtx);
|
|
13042
|
+
const wpPluralFull = getCollectionLabel("work_package", "plural", vocabCtx);
|
|
13043
|
+
const betLine = currentWP ? `**Current ${wpSingularFull}:** ${currentWP}. ${sc.activeBetCount} active ${wpPluralFull}.` : `No active ${wpPluralFull}.`;
|
|
13044
|
+
lines.push(`${betLine} ${sc.activeTensionCount} open tension(s).`);
|
|
13045
|
+
lines.push("");
|
|
13046
|
+
}
|
|
13047
|
+
if (orientView?.continuingFrom && orientView.continuingFrom.length > 0) {
|
|
13048
|
+
lines.push("## Continuing from");
|
|
13049
|
+
lines.push("_Prior-session entries most relevant to your task._");
|
|
13050
|
+
lines.push("");
|
|
13051
|
+
for (const e of orientView.continuingFrom) {
|
|
13052
|
+
const id = e.entryId ?? e.name;
|
|
13053
|
+
const type = e.canonicalKey ?? "generic";
|
|
13054
|
+
const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
|
|
13055
|
+
lines.push(`- \`${id}\` (score ${e.score}) [${type}]${coll} \u2014 ${e.name}`);
|
|
13056
|
+
if (e.reasoning) lines.push(` _${e.reasoning}_`);
|
|
13057
|
+
if ("primer" in e && typeof e.primer === "string" && e.primer.length > 0) {
|
|
13058
|
+
const PRIMER_MAX = 1200;
|
|
13059
|
+
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;
|
|
13060
|
+
lines.push("");
|
|
13061
|
+
lines.push(" **Primer (paste when starting implementation):**");
|
|
13062
|
+
lines.push(" ```");
|
|
13063
|
+
for (const line of primerText.split("\n")) lines.push(" " + line);
|
|
13064
|
+
lines.push(" ```");
|
|
13065
|
+
lines.push("");
|
|
12758
13066
|
}
|
|
12759
|
-
|
|
12760
|
-
|
|
13067
|
+
}
|
|
13068
|
+
lines.push("");
|
|
13069
|
+
}
|
|
13070
|
+
if (orientView?.lastSessionTouched && orientView.lastSessionTouched.length > 0) {
|
|
13071
|
+
lines.push("## Last session touched");
|
|
13072
|
+
lines.push("_Entries created or modified in your most recent session._");
|
|
13073
|
+
lines.push("");
|
|
13074
|
+
for (const e of orientView.lastSessionTouched) {
|
|
13075
|
+
const id = e.entryId ?? e.name;
|
|
13076
|
+
const type = e.canonicalKey ?? "generic";
|
|
13077
|
+
const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
|
|
13078
|
+
lines.push(`- \`${id}\` [${type}]${coll} \u2014 ${e.name}`);
|
|
13079
|
+
if ("primer" in e && typeof e.primer === "string" && e.primer.length > 0) {
|
|
13080
|
+
const PRIMER_MAX = 1200;
|
|
13081
|
+
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;
|
|
13082
|
+
lines.push("");
|
|
13083
|
+
lines.push(" **Primer:**");
|
|
13084
|
+
lines.push(" ```");
|
|
13085
|
+
for (const line of primerText.split("\n")) lines.push(" " + line);
|
|
13086
|
+
lines.push(" ```");
|
|
13087
|
+
lines.push("");
|
|
12761
13088
|
}
|
|
12762
|
-
const wpPlural = getCollectionLabel("work_package", "plural", vocabCtx);
|
|
12763
|
-
lines.push(`${sc.activeBetCount} active ${wpPlural}, ${sc.activeTensionCount} tension(s).`);
|
|
12764
13089
|
}
|
|
12765
|
-
|
|
12766
|
-
|
|
13090
|
+
lines.push("");
|
|
13091
|
+
}
|
|
13092
|
+
if (orientView?.taskContext && orientView.taskContext.context.length > 0) {
|
|
13093
|
+
const tc = orientView.taskContext;
|
|
13094
|
+
lines.push("## Task Context");
|
|
13095
|
+
if (tc.isGroundingStub && tc.groundingNote) {
|
|
13096
|
+
lines.push(`> \u26A0\uFE0F ${tc.groundingNote}`);
|
|
13097
|
+
lines.push("");
|
|
12767
13098
|
}
|
|
12768
|
-
if (orientView
|
|
13099
|
+
if (orientView.startup?.domainRetrieval) {
|
|
12769
13100
|
const retrieval = orientView.startup.domainRetrieval;
|
|
12770
13101
|
const scopedTo = retrieval.resolvedDomainSlug ? ` (${retrieval.resolvedDomainSlug})` : "";
|
|
12771
|
-
lines.push(`
|
|
12772
|
-
if (retrieval.activeSource) lines.push(`
|
|
12773
|
-
if (retrieval.fallbackReason) lines.push(`
|
|
12774
|
-
if (retrieval.fallbackAction) lines.push(`
|
|
12775
|
-
if (retrieval.evidenceGap) lines.push(`
|
|
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) {
|
|
13102
|
+
lines.push(`_Domain retrieval: ${retrieval.state}${scopedTo}_`);
|
|
13103
|
+
if (retrieval.activeSource) lines.push(`_Active source: ${retrieval.activeSource}_`);
|
|
13104
|
+
if (retrieval.fallbackReason) lines.push(`_${retrieval.fallbackReason}_`);
|
|
13105
|
+
if (retrieval.fallbackAction) lines.push(`_${retrieval.fallbackAction}_`);
|
|
13106
|
+
if (retrieval.evidenceGap) lines.push(`_Evidence gap: ${retrieval.evidenceGap}_`);
|
|
12781
13107
|
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
13108
|
}
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
12793
|
-
}
|
|
13109
|
+
lines.push(`_Task-scoped entries (${tc.confidence} confidence, ${tc.totalFound} relevant)`);
|
|
13110
|
+
lines.push("");
|
|
13111
|
+
for (const e of tc.context) {
|
|
13112
|
+
const id = e.entryId ?? e.name;
|
|
13113
|
+
const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
|
|
13114
|
+
const originTag = e.origin ? ` (origin: ${e.origin})` : "";
|
|
13115
|
+
lines.push(`- \`${id}\` (score ${e.score})${coll}${originTag}${e.name !== id ? ` \u2014 ${e.name}` : ""}`);
|
|
13116
|
+
if (e.preview) lines.push(` _${e.preview}_`);
|
|
13117
|
+
}
|
|
13118
|
+
lines.push("");
|
|
13119
|
+
}
|
|
13120
|
+
if (orientView?.taskContext?.constellationEntries && orientView.taskContext.constellationEntries.length > 0) {
|
|
13121
|
+
lines.push(...formatBetConstellationLines(
|
|
13122
|
+
orientView.taskContext.constellationEntries,
|
|
13123
|
+
orientView.taskContext.constellationBetName
|
|
13124
|
+
));
|
|
13125
|
+
}
|
|
13126
|
+
if (orientView?.writeBackHints && orientView.writeBackHints.length > 0) {
|
|
13127
|
+
lines.push("");
|
|
13128
|
+
lines.push("## Write-Back Hints");
|
|
13129
|
+
lines.push("_What to capture this session (derived from task context):_");
|
|
13130
|
+
lines.push("");
|
|
13131
|
+
for (const h of orientView.writeBackHints) {
|
|
13132
|
+
lines.push(`- **${h.collectionSlug}**: ${h.hint}`);
|
|
12794
13133
|
}
|
|
12795
|
-
|
|
13134
|
+
lines.push("");
|
|
13135
|
+
}
|
|
13136
|
+
if (orientView) {
|
|
13137
|
+
const result = await runAlignmentCheck(
|
|
13138
|
+
task,
|
|
13139
|
+
orientView.activeWorkPackages ?? [],
|
|
13140
|
+
orientView.taskContext?.context
|
|
13141
|
+
);
|
|
13142
|
+
lines.push(...buildAlignmentCheckLines(result));
|
|
13143
|
+
lines.push(...formatInitiativeStatusLines(orientView.initiativeStatus));
|
|
13144
|
+
lines.push(...formatWorkstreamHealthLines(orientView.workstreamHealth));
|
|
13145
|
+
lines.push(...formatWhatNeedsAttentionLines(orientView.whatNeedsAttention));
|
|
13146
|
+
if (orientView.trustMetrics) {
|
|
12796
13147
|
const tm = orientView.trustMetrics;
|
|
12797
|
-
if (tm.
|
|
12798
|
-
const capNote = tm.scannedCap ? "
|
|
12799
|
-
lines.push(
|
|
13148
|
+
if (tm.verified > 0 || tm.unverified > 0) {
|
|
13149
|
+
const capNote = tm.scannedCap ? " (capped at 500)" : "";
|
|
13150
|
+
lines.push("## Trust metrics");
|
|
13151
|
+
lines.push(`_Entry verification status across workspace${capNote}._`);
|
|
13152
|
+
lines.push("");
|
|
13153
|
+
lines.push(`- **Verified:** ${tm.verified}`);
|
|
13154
|
+
lines.push(`- **Unverified:** ${tm.unverified}`);
|
|
13155
|
+
lines.push(`- **No status (pre-BET-240):** ${tm.noStatus}`);
|
|
13156
|
+
lines.push(`- **Total scanned:** ${tm.total}`);
|
|
13157
|
+
lines.push("");
|
|
12800
13158
|
}
|
|
12801
13159
|
}
|
|
12802
|
-
|
|
12803
|
-
|
|
12804
|
-
|
|
12805
|
-
|
|
12806
|
-
|
|
12807
|
-
const
|
|
12808
|
-
if (
|
|
12809
|
-
|
|
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.`);
|
|
13160
|
+
}
|
|
13161
|
+
if (fullCoherence) {
|
|
13162
|
+
lines.push(...fullCoherence.lines);
|
|
13163
|
+
}
|
|
13164
|
+
if (allCollections.length > 0) {
|
|
13165
|
+
const docCompleteness = buildDocCompletenessSection(allCollections);
|
|
13166
|
+
if (docCompleteness.errorCount > 0 || docCompleteness.warningCount > 0) {
|
|
13167
|
+
lines.push(...docCompleteness.lines);
|
|
12815
13168
|
}
|
|
12816
|
-
|
|
12817
|
-
|
|
12818
|
-
|
|
12819
|
-
|
|
12820
|
-
|
|
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) {
|
|
13169
|
+
}
|
|
13170
|
+
if (orientView) {
|
|
13171
|
+
if (orientView.activeWorkPackages?.length > 0) {
|
|
13172
|
+
lines.push("## Active work packages \u2014 current scope");
|
|
13173
|
+
lines.push("_Work outside these work packages requires explicit user confirmation._");
|
|
12829
13174
|
lines.push("");
|
|
12830
|
-
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
12835
|
-
|
|
12836
|
-
|
|
13175
|
+
for (const e of orientView.activeWorkPackages) {
|
|
13176
|
+
lines.push(fmt(e));
|
|
13177
|
+
const tensions = e.linkedTensions;
|
|
13178
|
+
if (tensions?.length) {
|
|
13179
|
+
const tensionLines = tensions.map((t) => {
|
|
13180
|
+
const meta = [t.severity, t.priority].filter(Boolean).join(", ");
|
|
13181
|
+
return `\`${t.entryId ?? t.name}\` (${t.name}${meta ? `, ${meta}` : ""})`;
|
|
13182
|
+
});
|
|
13183
|
+
lines.push(` Tensions: ${tensionLines.join("; ")}`);
|
|
13184
|
+
}
|
|
12837
13185
|
}
|
|
12838
|
-
}
|
|
12839
|
-
if (orientView) {
|
|
12840
13186
|
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
13187
|
}
|
|
12881
|
-
|
|
12882
|
-
|
|
12883
|
-
|
|
13188
|
+
if (orientView.activeGoals?.length > 0) {
|
|
13189
|
+
lines.push("## Active goals");
|
|
13190
|
+
orientView.activeGoals.forEach((e) => lines.push(fmt(e)));
|
|
12884
13191
|
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
13192
|
}
|
|
12891
|
-
if (
|
|
13193
|
+
if (orientView.strategyHighlights?.length > 0) {
|
|
13194
|
+
lines.push("## Strategy highlights");
|
|
13195
|
+
lines.push("_One-sentence strategy, positioning, moat, business model, GTM \u2014 high-level strategic context._");
|
|
12892
13196
|
lines.push("");
|
|
12893
|
-
|
|
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.");
|
|
13197
|
+
orientView.strategyHighlights.forEach((e) => lines.push(fmt(e)));
|
|
12921
13198
|
lines.push("");
|
|
12922
13199
|
}
|
|
12923
|
-
|
|
12924
|
-
|
|
12925
|
-
|
|
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));
|
|
13200
|
+
if (orientView.playingField?.length > 0) {
|
|
13201
|
+
lines.push("## Playing field");
|
|
13202
|
+
lines.push("_Products and opportunities in the strategic landscape._");
|
|
12936
13203
|
lines.push("");
|
|
12937
|
-
lines.push(
|
|
13204
|
+
orientView.playingField.forEach((e) => lines.push(fmt(e)));
|
|
12938
13205
|
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
13206
|
}
|
|
12948
|
-
|
|
12949
|
-
|
|
12950
|
-
|
|
12951
|
-
|
|
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;
|
|
13207
|
+
if (orientView.recentDecisions?.length > 0) {
|
|
13208
|
+
lines.push("## Recent decisions");
|
|
13209
|
+
orientView.recentDecisions.forEach((e) => lines.push(fmt(e)));
|
|
13210
|
+
lines.push("");
|
|
12965
13211
|
}
|
|
12966
|
-
if (
|
|
12967
|
-
lines.push(
|
|
13212
|
+
if (orientView.recentlySuperseded?.length > 0) {
|
|
13213
|
+
lines.push("## Recently superseded");
|
|
13214
|
+
orientView.recentlySuperseded.forEach((e) => lines.push(fmt(e)));
|
|
12968
13215
|
lines.push("");
|
|
12969
|
-
|
|
12970
|
-
|
|
12971
|
-
|
|
12972
|
-
|
|
12973
|
-
|
|
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}.**`);
|
|
13216
|
+
}
|
|
13217
|
+
if (orientView.staleEntries?.length > 0) {
|
|
13218
|
+
lines.push("## Needs confirmation");
|
|
13219
|
+
lines.push(`_Domain stratum entries not confirmed in ${orientView.stalenessThresholdDays} days._`);
|
|
13220
|
+
orientView.staleEntries.forEach((e) => lines.push(fmt(e)));
|
|
13193
13221
|
lines.push("");
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
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.");
|
|
13222
|
+
}
|
|
13223
|
+
if (orientView.architectureNotes?.length > 0) {
|
|
13224
|
+
lines.push("## Architecture notes");
|
|
13225
|
+
orientView.architectureNotes.forEach((e) => lines.push(fmt(e)));
|
|
13242
13226
|
lines.push("");
|
|
13243
13227
|
}
|
|
13228
|
+
const mapGovernanceEntry = (e) => ({
|
|
13229
|
+
entryId: e.entryId,
|
|
13230
|
+
name: e.name,
|
|
13231
|
+
description: typeof e.preview === "string" ? e.preview : void 0,
|
|
13232
|
+
tier: typeof e.tier === "number" ? e.tier : void 0,
|
|
13233
|
+
// Phase 4 (DEC-1141): thread provenance fields to buildOperatingProtocol.
|
|
13234
|
+
provenance: e.provenance,
|
|
13235
|
+
anchoredBy: typeof e.anchoredBy === "string" ? e.anchoredBy : void 0
|
|
13236
|
+
});
|
|
13237
|
+
const gov = orientView.governance ?? { principles: [], standards: [], businessRules: [] };
|
|
13238
|
+
lines.push(...buildOperatingProtocol({
|
|
13239
|
+
principles: (gov.principles ?? []).map(mapGovernanceEntry),
|
|
13240
|
+
standards: (gov.standards ?? []).map(mapGovernanceEntry),
|
|
13241
|
+
businessRules: (gov.businessRules ?? []).map(mapGovernanceEntry)
|
|
13242
|
+
}, task));
|
|
13243
|
+
}
|
|
13244
|
+
let allEntries = [];
|
|
13245
|
+
try {
|
|
13246
|
+
allEntries = await kernelQuery("chain.listEntries", {}) ?? [];
|
|
13247
|
+
} catch {
|
|
13248
|
+
}
|
|
13249
|
+
const plannedWork = buildPlannedWork(allEntries);
|
|
13250
|
+
if (hasPlannedWork(plannedWork)) {
|
|
13251
|
+
lines.push(...buildPlannedWorkSection(plannedWork, priorSessions, recoveryBlock));
|
|
13252
|
+
} else if (recoveryBlock) {
|
|
13253
|
+
lines.push(...formatRecoveryBlock(recoveryBlock));
|
|
13244
13254
|
}
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
|
|
13255
|
+
} else {
|
|
13256
|
+
lines.push(`**Brain stage: ${orientStage}.**`);
|
|
13257
|
+
lines.push("");
|
|
13258
|
+
if (orientView?.activeWorkPackages?.length) {
|
|
13259
|
+
lines.push("## Active work packages \u2014 current scope");
|
|
13260
|
+
lines.push("_Work outside these work packages requires explicit user confirmation._");
|
|
13249
13261
|
lines.push("");
|
|
13250
|
-
for (const
|
|
13251
|
-
lines.push(
|
|
13262
|
+
for (const e of orientView.activeWorkPackages) {
|
|
13263
|
+
lines.push(fmt(e));
|
|
13252
13264
|
}
|
|
13253
13265
|
lines.push("");
|
|
13254
13266
|
}
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
|
|
13264
|
-
|
|
13265
|
-
lines.push(
|
|
13266
|
-
lines.push(
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
lines.push("
|
|
13270
|
-
lines.push("_Warning: Could not mark session as oriented. Write tools may be restricted._");
|
|
13267
|
+
lines.push(...formatInitiativeStatusLines(orientView?.initiativeStatus));
|
|
13268
|
+
lines.push(...formatWorkstreamHealthLines(orientView?.workstreamHealth));
|
|
13269
|
+
lines.push(...formatWhatNeedsAttentionLines(orientView?.whatNeedsAttention));
|
|
13270
|
+
if (orientView?.trustMetrics) {
|
|
13271
|
+
const tm = orientView.trustMetrics;
|
|
13272
|
+
if (tm.verified > 0 || tm.unverified > 0) {
|
|
13273
|
+
const capNote = tm.scannedCap ? " (capped at 500)" : "";
|
|
13274
|
+
lines.push("## Trust metrics");
|
|
13275
|
+
lines.push(`_Entry verification status across workspace${capNote}._`);
|
|
13276
|
+
lines.push("");
|
|
13277
|
+
lines.push(`- **Verified:** ${tm.verified}`);
|
|
13278
|
+
lines.push(`- **Unverified:** ${tm.unverified}`);
|
|
13279
|
+
lines.push(`- **No status (pre-BET-240):** ${tm.noStatus}`);
|
|
13280
|
+
lines.push(`- **Total scanned:** ${tm.total}`);
|
|
13281
|
+
lines.push("");
|
|
13271
13282
|
}
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13276
|
-
|
|
13277
|
-
|
|
13278
|
-
|
|
13279
|
-
|
|
13280
|
-
|
|
13283
|
+
}
|
|
13284
|
+
lines.push(...buildOperatingProtocol());
|
|
13285
|
+
if (fullCoherence) {
|
|
13286
|
+
lines.push(...fullCoherence.lines);
|
|
13287
|
+
}
|
|
13288
|
+
if (allCollections.length > 0) {
|
|
13289
|
+
const docCompleteness = buildDocCompletenessSection(allCollections);
|
|
13290
|
+
if (docCompleteness.errorCount > 0 || docCompleteness.warningCount > 0) {
|
|
13291
|
+
lines.push(...docCompleteness.lines);
|
|
13281
13292
|
}
|
|
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
13293
|
}
|
|
13290
|
-
|
|
13291
|
-
|
|
13292
|
-
const
|
|
13294
|
+
if (priorSessions.length > 0 && !recoveryBlock) {
|
|
13295
|
+
const last = priorSessions[0];
|
|
13296
|
+
const date = last.startedAt ? new Date(last.startedAt).toISOString().split("T")[0] : "unknown";
|
|
13297
|
+
const created = Array.isArray(last.entriesCreated) ? last.entriesCreated.length : last.entriesCreated ?? 0;
|
|
13298
|
+
const modified = Array.isArray(last.entriesModified) ? last.entriesModified.length : last.entriesModified ?? 0;
|
|
13299
|
+
lines.push(`_Last session (${date}): ${created} created, ${modified} modified._`);
|
|
13293
13300
|
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
13301
|
}
|
|
13300
|
-
|
|
13301
|
-
|
|
13302
|
-
|
|
13303
|
-
|
|
13304
|
-
|
|
13305
|
-
|
|
13306
|
-
|
|
13307
|
-
|
|
13308
|
-
|
|
13309
|
-
|
|
13310
|
-
|
|
13311
|
-
|
|
13312
|
-
|
|
13313
|
-
|
|
13314
|
-
|
|
13315
|
-
|
|
13316
|
-
|
|
13317
|
-
|
|
13318
|
-
|
|
13319
|
-
|
|
13320
|
-
|
|
13321
|
-
|
|
13302
|
+
if (recoveryBlock) {
|
|
13303
|
+
lines.push(...formatRecoveryBlock(recoveryBlock));
|
|
13304
|
+
}
|
|
13305
|
+
lines.push("**What are you working on?** Tell me and I'll load relevant governance and context.");
|
|
13306
|
+
lines.push("");
|
|
13307
|
+
}
|
|
13308
|
+
}
|
|
13309
|
+
const classificationGaps = readiness?.gaps?.filter((g) => g.id?.startsWith?.(PURPOSE_GAP_PREFIX)) ?? [];
|
|
13310
|
+
if (classificationGaps.length > 0) {
|
|
13311
|
+
lines.push("## Classification gaps");
|
|
13312
|
+
lines.push("_Collections with weak purpose \u2014 entry classification may be inaccurate._");
|
|
13313
|
+
lines.push("");
|
|
13314
|
+
for (const g of classificationGaps) {
|
|
13315
|
+
lines.push(`- ${g.label ?? g.id?.replace?.("purpose-gap-", "") ?? "unknown"}`);
|
|
13316
|
+
}
|
|
13317
|
+
lines.push("");
|
|
13318
|
+
}
|
|
13319
|
+
if (errors.length > 0) {
|
|
13320
|
+
lines.push("## Errors");
|
|
13321
|
+
for (const err of errors) lines.push(`- ${err}`);
|
|
13322
|
+
lines.push("");
|
|
13323
|
+
}
|
|
13324
|
+
let orientationStatus = "no_session";
|
|
13325
|
+
if (agentSessionId && hasTaskGrounding) {
|
|
13326
|
+
const orientedOk = await markOrientedWithSnapshotFallback(agentSessionId, fullCoherenceSnapshot);
|
|
13327
|
+
if (orientedOk) {
|
|
13328
|
+
orientationStatus = "complete";
|
|
13329
|
+
lines.push("---");
|
|
13330
|
+
lines.push(`Orientation complete. Session ${agentSessionId}. Write tools available.`);
|
|
13331
|
+
} else {
|
|
13332
|
+
orientationStatus = "failed";
|
|
13333
|
+
lines.push("---");
|
|
13334
|
+
lines.push("_Warning: Could not mark session as oriented. Write tools may be restricted._");
|
|
13335
|
+
}
|
|
13336
|
+
try {
|
|
13337
|
+
await kernelMutation("chain.recordSessionSignal", {
|
|
13338
|
+
sessionId: agentSessionId,
|
|
13339
|
+
signalType: "immediate_context_load",
|
|
13340
|
+
metadata: { source: "orient" }
|
|
13341
|
+
});
|
|
13342
|
+
} catch (err) {
|
|
13343
|
+
process.stderr.write(`[MCP] recordSessionSignal failed: ${err.message}
|
|
13344
|
+
`);
|
|
13345
|
+
}
|
|
13346
|
+
} else if (agentSessionId) {
|
|
13347
|
+
orientationStatus = "task_required";
|
|
13348
|
+
lines.push("---");
|
|
13349
|
+
lines.push('Workspace orientation loaded. Write tools stay locked until you run `orient task="describe the work"`.');
|
|
13350
|
+
} else {
|
|
13351
|
+
lines.push("---");
|
|
13352
|
+
lines.push("_No active agent session. Call `session action=start` to begin a tracked session._");
|
|
13353
|
+
}
|
|
13354
|
+
const fullTruncated = orientView?._budget?.truncated ?? orientView?._truncated ?? false;
|
|
13355
|
+
if (fullTruncated) {
|
|
13356
|
+
const reasons = orientView?._budget?.truncationReasons;
|
|
13357
|
+
lines.push("");
|
|
13358
|
+
if (reasons && reasons.length > 0) {
|
|
13359
|
+
lines.push(`_Context truncated to fit tier budget: ${reasons.join(", ")}. Use tier=full for complete payload._`);
|
|
13360
|
+
} else {
|
|
13361
|
+
lines.push("_Context truncated to fit tier budget. Use tier=full for complete payload._");
|
|
13362
|
+
}
|
|
13363
|
+
}
|
|
13364
|
+
const fullResult = {
|
|
13365
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
13366
|
+
structuredContent: success(
|
|
13367
|
+
`Oriented (full). Stage: ${orientStage}. ${isLowReadiness ? "Low readiness \u2014 gaps remain." : "Ready."}`,
|
|
13368
|
+
{
|
|
13369
|
+
mode: "full",
|
|
13370
|
+
stage: orientStage,
|
|
13371
|
+
oriented: hasTaskGrounding ? isSessionOriented() : false,
|
|
13372
|
+
sessionId: agentSessionId,
|
|
13373
|
+
taskGroundingStatus: hasTaskGrounding ? "task_scoped" : task ? "missing_task_context" : "workspace_only",
|
|
13374
|
+
taskGroundingRequired: !hasTaskGrounding,
|
|
13375
|
+
// STD-219 §4 (DEC-1147): machine-readable stub flag for agent consumers.
|
|
13376
|
+
...orientView?.taskContext?.isGroundingStub ? { groundingStub: true } : {},
|
|
13377
|
+
domainRetrieval: orientView?.startup?.domainRetrieval,
|
|
13378
|
+
orientationStatus,
|
|
13379
|
+
nextStep: hasTaskGrounding ? void 0 : 'Run `orient task="describe the work"` before substantive work.',
|
|
13380
|
+
...orientView?._budget ? { _budget: orientView._budget } : {}
|
|
13381
|
+
}
|
|
13382
|
+
)
|
|
13383
|
+
};
|
|
13384
|
+
reportOrientWrapperBytes(fullResult, fullTruncated, resolvedTier, taskIsMeaningful(task));
|
|
13385
|
+
return fullResult;
|
|
13322
13386
|
}
|
|
13323
13387
|
|
|
13324
13388
|
// src/tools/health.ts
|
|
@@ -15204,4 +15268,4 @@ export {
|
|
|
15204
15268
|
createProductBrainServer,
|
|
15205
15269
|
initFeatureFlags
|
|
15206
15270
|
};
|
|
15207
|
-
//# sourceMappingURL=chunk-
|
|
15271
|
+
//# sourceMappingURL=chunk-JJJO3SDX.js.map
|