@productbrain/mcp 0.0.1-beta.8643 → 0.0.1-beta.8652
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.
|
@@ -7675,20 +7675,6 @@ function formatBriefingLines(view) {
|
|
|
7675
7675
|
|
|
7676
7676
|
// src/tools/orient-rituals.ts
|
|
7677
7677
|
var RULE_LISTS_EVERYONE_ONLY_LABEL = "Rules (everyone list only; run `orient mode=full` for your team and role lists):";
|
|
7678
|
-
var RULE_LISTS_UNAVAILABLE_LINE = "Rules: unavailable \u2014 rule list fetch failed, retry `orient mode=full`";
|
|
7679
|
-
function buildEveryoneOnlyRuleListsLines(ruleLists) {
|
|
7680
|
-
if (!ruleLists) return [];
|
|
7681
|
-
const everyoneOnly = {
|
|
7682
|
-
everyone: ruleLists.everyone,
|
|
7683
|
-
team: null,
|
|
7684
|
-
role: { rows: [], overCap: 0 },
|
|
7685
|
-
unassigned: ruleLists.unassigned,
|
|
7686
|
-
truncated: ruleLists.truncated,
|
|
7687
|
-
...ruleLists.namesTruncated ? { namesTruncated: true } : {}
|
|
7688
|
-
};
|
|
7689
|
-
const bucketLines = formatRuleListsLines(everyoneOnly);
|
|
7690
|
-
return [RULE_LISTS_EVERYONE_ONLY_LABEL, bucketLines.length > 0 ? bucketLines.join("\n") : "(none currently served)"];
|
|
7691
|
-
}
|
|
7692
7678
|
var SPINE_UNAVAILABLE_LINE = "Spine check: unavailable \u2014 orient fetch failed, retry `orient`";
|
|
7693
7679
|
function buildRitualsSurfaceLines(view, opts) {
|
|
7694
7680
|
const lines = [""];
|
|
@@ -7703,81 +7689,15 @@ function buildRitualsSurfaceLines(view, opts) {
|
|
|
7703
7689
|
if (view?.atCapLine) lines.push(view.atCapLine);
|
|
7704
7690
|
return lines;
|
|
7705
7691
|
}
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
function buildKeyResultLine(kr, objName) {
|
|
7716
|
-
const idPart = kr.entryId ? `${toSafeCodeSpan(sanitizeSingleLineField(kr.entryId))} ` : "";
|
|
7717
|
-
const unresolvedTag = kr.readingUnresolved ? " [reading unresolved]" : "";
|
|
7718
|
-
const values = `${krValue(kr.currentValue)} / ${krValue(kr.targetValue)} [${kr.staleness}]${unresolvedTag}`;
|
|
7719
|
-
const suffix = objName ? ` (${sanitizeSingleLineField(objName)})` : "";
|
|
7720
|
-
return `**Key result:** ${idPart}${sanitizeSingleLineField(kr.name)}${suffix}: ${values}`;
|
|
7721
|
-
}
|
|
7722
|
-
function toSafeCodeSpan(text) {
|
|
7723
|
-
const longestBacktickRun = (text.match(/`+/g) ?? []).reduce((max, run) => Math.max(max, run.length), 0);
|
|
7724
|
-
const fence = "`".repeat(longestBacktickRun + 1);
|
|
7725
|
-
const pad = text.startsWith("`") || text.endsWith("`") ? " " : "";
|
|
7726
|
-
return `${fence}${pad}${text}${pad}${fence}`;
|
|
7727
|
-
}
|
|
7728
|
-
function buildDirectionLines(view) {
|
|
7729
|
-
const purpose = view?.strategicContext?.purpose;
|
|
7730
|
-
const vision = view?.strategicContext?.vision;
|
|
7731
|
-
const productAreas = view?.strategicContext?.productAreas ?? [];
|
|
7732
|
-
const spine = view?.strategicSpine;
|
|
7733
|
-
const objectives = spine?.objectives ?? [];
|
|
7734
|
-
const orphanKeyResults = spine?.orphanKeyResults ?? [];
|
|
7735
|
-
const truncationReasons = spine?.truncationReasons ?? [];
|
|
7736
|
-
const fetchFailed = spine?.fetchFailed ?? false;
|
|
7737
|
-
const krRows = objectives.flatMap((o) => o.keyResults.map((kr) => ({ o, kr })));
|
|
7738
|
-
const strategy = (view?.strategyHighlights ?? []).filter(
|
|
7739
|
-
(e) => typeof e === "object" && e != null && typeof e.name === "string" && e.name.length > 0
|
|
7740
|
-
);
|
|
7741
|
-
const hasSomething = purpose || vision || strategy.length > 0 || productAreas.length > 0 || objectives.length > 0 || orphanKeyResults.length > 0 || truncationReasons.length > 0 || fetchFailed;
|
|
7742
|
-
if (!hasSomething) return [];
|
|
7743
|
-
const lines = ["## Strategic Context"];
|
|
7744
|
-
for (const section of spine?.order ?? DEFAULT_SPINE_ORDER) {
|
|
7745
|
-
if (section === "purpose") {
|
|
7746
|
-
if (purpose) lines.push(`**Purpose:** ${stripControlChars(purpose)}`);
|
|
7747
|
-
} else if (section === "vision") {
|
|
7748
|
-
if (vision) lines.push(`**Vision:** ${stripControlChars(vision)}`);
|
|
7749
|
-
} else if (section === "strategy") lines.push(...buildStrategyRowLines(strategy));
|
|
7750
|
-
else if (section === "product") {
|
|
7751
|
-
if (productAreas.length > 0) lines.push(`**Product areas:** ${productAreas.join(", ")}`);
|
|
7752
|
-
} else if (section === "objectives") {
|
|
7753
|
-
if (fetchFailed) lines.push("**Strategic spine:** unavailable \u2014 orient fetch failed, retry `orient`.");
|
|
7754
|
-
else if (objectives.length > 0) {
|
|
7755
|
-
for (const obj of objectives) {
|
|
7756
|
-
const idPart = obj.entryId ? `${toSafeCodeSpan(sanitizeSingleLineField(obj.entryId))} ` : "";
|
|
7757
|
-
lines.push(`**Objective:** ${idPart}${sanitizeSingleLineField(obj.name)}`);
|
|
7758
|
-
}
|
|
7759
|
-
}
|
|
7760
|
-
} else if (section === "keyResults" && !fetchFailed && (krRows.length > 0 || orphanKeyResults.length > 0 || truncationReasons.length > 0)) {
|
|
7761
|
-
for (const { o, kr } of krRows) lines.push(buildKeyResultLine(kr, o.name));
|
|
7762
|
-
if (orphanKeyResults.length > 0) {
|
|
7763
|
-
lines.push("**Key results without an objective:**");
|
|
7764
|
-
for (const kr of orphanKeyResults) lines.push(buildKeyResultLine(kr, null));
|
|
7765
|
-
}
|
|
7766
|
-
for (const reason of truncationReasons) lines.push(TRUNCATION_MESSAGES[reason]);
|
|
7767
|
-
}
|
|
7768
|
-
}
|
|
7769
|
-
return lines;
|
|
7770
|
-
}
|
|
7771
|
-
function buildStrategyRowLines(strategy) {
|
|
7772
|
-
const lines = [];
|
|
7773
|
-
for (const row of strategy) {
|
|
7774
|
-
const mark = provenanceMark(row.provenance);
|
|
7775
|
-
const rawId = row.entryId ?? row._id;
|
|
7776
|
-
const idPart = typeof rawId === "string" && rawId ? `${toSafeCodeSpan(sanitizeSingleLineField(rawId))} ` : "";
|
|
7777
|
-
const anchorSuffix = row.anchoredBy ? ` (${sanitizeSingleLineField(row.anchoredBy)})` : "";
|
|
7778
|
-
const preview = typeof row.preview === "string" && row.preview ? ` \u2014 ${stripControlChars(row.preview)}` : "";
|
|
7779
|
-
lines.push(`**Strategy:** ${mark}${idPart}${sanitizeSingleLineField(row.name)}${anchorSuffix}${preview}`);
|
|
7780
|
-
}
|
|
7692
|
+
function buildOrientBriefingLines(view, opts) {
|
|
7693
|
+
if (!view) return [];
|
|
7694
|
+
const rl = view.ruleLists ?? void 0;
|
|
7695
|
+
const ruleLists = rl && opts?.everyoneOnly ? { everyone: rl.everyone, team: null, role: { rows: [], overCap: 0 }, unassigned: rl.unassigned, truncated: rl.truncated, ...rl.namesTruncated ? { namesTruncated: true } : {} } : rl;
|
|
7696
|
+
const lines = formatBriefingLines({ facts: view.briefing ?? void 0, ruleLists, surface: "mcp" });
|
|
7697
|
+
if (!opts?.everyoneOnly || !rl) return lines;
|
|
7698
|
+
if (lines.includes("Rules:")) return lines.map((l) => l === "Rules:" ? RULE_LISTS_EVERYONE_ONLY_LABEL : l);
|
|
7699
|
+
const pull = lines.findIndex((l) => l.startsWith("Pull more:"));
|
|
7700
|
+
lines.splice(pull < 0 ? lines.length : pull, 0, RULE_LISTS_EVERYONE_ONLY_LABEL, "(none currently served)", "");
|
|
7781
7701
|
return lines;
|
|
7782
7702
|
}
|
|
7783
7703
|
async function fetchAndRenderOpenerDirection(kernelQuery2, errors, session) {
|
|
@@ -7786,7 +7706,7 @@ async function fetchAndRenderOpenerDirection(kernelQuery2, errors, session) {
|
|
|
7786
7706
|
try {
|
|
7787
7707
|
view = await kernelQuery2("chain.getOrientView", {
|
|
7788
7708
|
tier: "standard",
|
|
7789
|
-
invocationPath: "session-start",
|
|
7709
|
+
invocationPath: session?.invocationPath ?? "session-start",
|
|
7790
7710
|
// Stamps this call onto the current session/conversation/task (same as every other
|
|
7791
7711
|
// chain.getOrientView caller) so recordOrientMetric's orientCallCount/billing rollup sees it.
|
|
7792
7712
|
...session?.agentSessionId ? { sessionId: session.agentSessionId } : {},
|
|
@@ -7797,32 +7717,15 @@ async function fetchAndRenderOpenerDirection(kernelQuery2, errors, session) {
|
|
|
7797
7717
|
fetchFailed = true;
|
|
7798
7718
|
errors.push(`Direction unavailable: ${e instanceof Error ? e.message : String(e)}`);
|
|
7799
7719
|
}
|
|
7800
|
-
return [...
|
|
7720
|
+
return { lines: [...buildOrientBriefingLines(view), ...buildRitualsSurfaceLines(view, { fetchFailed: fetchFailed || view?.fetchFailed === true })], view };
|
|
7801
7721
|
}
|
|
7802
7722
|
async function buildAlreadyOrientedResult(kernelQuery2, agentSessionId, taskGroundingWarningLines2) {
|
|
7803
|
-
const
|
|
7804
|
-
|
|
7805
|
-
// conflictQueue.ts's minute-bucket convention — forces a fresh reactive result once a snooze
|
|
7806
|
-
// expires on wall-clock time alone, with no corresponding DB write to bust the cache.
|
|
7807
|
-
kernelQuery2("chain.getRitualsSurface", {
|
|
7808
|
-
now: Math.floor(Date.now() / 6e4) * 6e4
|
|
7809
|
-
}),
|
|
7810
|
-
kernelQuery2("chain.getBindingGovernanceView", {})
|
|
7811
|
-
]);
|
|
7812
|
-
const ritualsFetchFailed = ritualsSettled.status === "rejected";
|
|
7813
|
-
const rituals = ritualsSettled.status === "fulfilled" ? ritualsSettled.value : null;
|
|
7814
|
-
const ruleListsFetchFailed = bindingGovernanceSettled.status === "rejected";
|
|
7815
|
-
const ruleLists = bindingGovernanceSettled.status === "fulfilled" ? bindingGovernanceSettled.value?.ruleLists : void 0;
|
|
7816
|
-
const ritualsLines = buildRitualsSurfaceLines(rituals, { fetchFailed: ritualsFetchFailed });
|
|
7817
|
-
const ruleListsBlock = ruleListsFetchFailed ? `${RULE_LISTS_UNAVAILABLE_LINE}
|
|
7818
|
-
|
|
7819
|
-
` : ruleLists !== void 0 ? `${buildEveryoneOnlyRuleListsLines(ruleLists).join("\n")}
|
|
7820
|
-
|
|
7821
|
-
` : "";
|
|
7723
|
+
const errors = [];
|
|
7724
|
+
const { lines, view } = await fetchAndRenderOpenerDirection(kernelQuery2, errors, { agentSessionId, invocationPath: "manual-orient" });
|
|
7822
7725
|
return {
|
|
7823
7726
|
content: [{
|
|
7824
7727
|
type: "text",
|
|
7825
|
-
text: "Already oriented. Session active, writes unlocked.\n" +
|
|
7728
|
+
text: "Already oriented. Session active, writes unlocked.\n" + [...errors, ...lines].join("\n") + "\n\n" + taskGroundingWarningLines2.join("\n") + "Use `orient mode='full'` for workspace context or `orient task='...'` before substantive work."
|
|
7826
7729
|
}],
|
|
7827
7730
|
structuredContent: success(
|
|
7828
7731
|
"Already oriented. Session active, writes unlocked.",
|
|
@@ -7832,35 +7735,15 @@ async function buildAlreadyOrientedResult(kernelQuery2, agentSessionId, taskGrou
|
|
|
7832
7735
|
taskGroundingStatus: "workspace_only",
|
|
7833
7736
|
taskGroundingRequired: true,
|
|
7834
7737
|
nextStep: 'Run `orient task="describe the work"` before substantive work.',
|
|
7835
|
-
// T1's undefined-vs-null distinction: omit the key on a fetch failure, keep an explicit
|
|
7836
|
-
|
|
7837
|
-
...
|
|
7838
|
-
...
|
|
7839
|
-
...
|
|
7840
|
-
// PR #538
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
...rituals?.atCapLine !== void 0 ? { atCapLine: rituals.atCapLine } : {},
|
|
7845
|
-
// Pre-review fix 1 (TEN-3912): team/role dropped from THIS path's payload — they are
|
|
7846
|
-
// always trivial here (see the doc comment above), never this session's real rules —
|
|
7847
|
-
// and `ruleListsScope` says explicitly why, rather than shipping a shape a consumer could
|
|
7848
|
-
// misread as "this session has no team/role rules".
|
|
7849
|
-
...ruleLists ? {
|
|
7850
|
-
ruleLists: {
|
|
7851
|
-
everyone: ruleLists.everyone,
|
|
7852
|
-
unassigned: ruleLists.unassigned,
|
|
7853
|
-
truncated: ruleLists.truncated,
|
|
7854
|
-
...ruleLists.namesTruncated ? { namesTruncated: true } : {}
|
|
7855
|
-
},
|
|
7856
|
-
ruleListsScope: "everyone-only"
|
|
7857
|
-
} : {},
|
|
7858
|
-
// Round 1 review (PRRT_kwDORS4ils6mOeU8, TEN-3912): explicit `true` only on the rejection
|
|
7859
|
-
// above, mirroring the existing `fetchFailed`/`groundingStub`-style boolean flags on this
|
|
7860
|
-
// same payload (present-and-true means "this happened", omitted means "it didn't") — never
|
|
7861
|
-
// a bare `false`, never inferred from `ruleLists` being absent (a genuine no-row read also
|
|
7862
|
-
// leaves it undefined).
|
|
7863
|
-
...ruleListsFetchFailed ? { ruleListsFetchFailed: true } : {}
|
|
7738
|
+
// T1's undefined-vs-null distinction: omit the key on a fetch failure, keep an explicit null for a genuine no-row arm.
|
|
7739
|
+
...view?.directionLine !== void 0 ? { directionLine: view.directionLine } : {},
|
|
7740
|
+
...view?.verdictAskLine !== void 0 ? { verdictAskLine: view.verdictAskLine } : {},
|
|
7741
|
+
...view?.spineLine !== void 0 ? { spineLine: view.spineLine } : {},
|
|
7742
|
+
...view?.atCapLine !== void 0 ? { atCapLine: view.atCapLine } : {},
|
|
7743
|
+
// PR #538: text and structure carry the same at-cap disclosure
|
|
7744
|
+
...view?.briefing ? { briefing: view.briefing } : {},
|
|
7745
|
+
...view?.ruleLists ? { ruleLists: view.ruleLists } : {},
|
|
7746
|
+
...view ? {} : { fetchFailed: true }
|
|
7864
7747
|
}
|
|
7865
7748
|
)
|
|
7866
7749
|
};
|
|
@@ -8131,7 +8014,8 @@ async function buildOrientResponse(wsCtx, agentSessionId, errors, task) {
|
|
|
8131
8014
|
lines.push("");
|
|
8132
8015
|
const startShapeLine = formatShapeAdvisorySummaryLine(shapeAdvisorySummary);
|
|
8133
8016
|
if (startShapeLine) lines.push(startShapeLine, "");
|
|
8134
|
-
|
|
8017
|
+
const opener = await fetchAndRenderOpenerDirection(kernelQuery, errors, { agentSessionId, conversationId: getConversationId(), task });
|
|
8018
|
+
lines.push(...opener.lines);
|
|
8135
8019
|
lines.push("_Need a collection that doesn't exist yet? Creating one is not available through this tool. Ask a platform admin to provision it, or enable the module ontology pack that owns it._");
|
|
8136
8020
|
lines.push("");
|
|
8137
8021
|
let activeBets = [];
|
|
@@ -8141,11 +8025,10 @@ async function buildOrientResponse(wsCtx, agentSessionId, errors, task) {
|
|
|
8141
8025
|
} catch {
|
|
8142
8026
|
}
|
|
8143
8027
|
let governanceEntries = { principles: [], standards: [], businessRules: [] };
|
|
8144
|
-
|
|
8028
|
+
const ruleListsView = opener.view?.ruleLists ?? void 0;
|
|
8145
8029
|
let bindingGovernanceView;
|
|
8146
8030
|
try {
|
|
8147
8031
|
bindingGovernanceView = await kernelQuery("chain.getBindingGovernanceView", { task });
|
|
8148
|
-
ruleListsView = bindingGovernanceView?.ruleLists;
|
|
8149
8032
|
} catch {
|
|
8150
8033
|
}
|
|
8151
8034
|
if (task) {
|
|
@@ -8179,8 +8062,6 @@ async function buildOrientResponse(wsCtx, agentSessionId, errors, task) {
|
|
|
8179
8062
|
lines.push("");
|
|
8180
8063
|
}
|
|
8181
8064
|
lines.push(...buildOperatingProtocol(governanceEntries, task));
|
|
8182
|
-
const ruleLines = formatRuleListsLines(ruleListsView);
|
|
8183
|
-
if (ruleLines.length > 0) lines.push("", "Rules:", ...ruleLines);
|
|
8184
8065
|
if (coherence) {
|
|
8185
8066
|
lines.push(...coherence.lines);
|
|
8186
8067
|
}
|
|
@@ -8228,8 +8109,6 @@ async function buildOrientResponse(wsCtx, agentSessionId, errors, task) {
|
|
|
8228
8109
|
lines.push(
|
|
8229
8110
|
...buildOperatingProtocol({ truncated: bindingGovernanceView?._budget?.truncated === true })
|
|
8230
8111
|
);
|
|
8231
|
-
const noTaskRuleLines = formatRuleListsLines(ruleListsView);
|
|
8232
|
-
if (noTaskRuleLines.length > 0) lines.push("", "Rules:", ...noTaskRuleLines);
|
|
8233
8112
|
if (coherence) {
|
|
8234
8113
|
lines.push(...coherence.lines);
|
|
8235
8114
|
}
|
|
@@ -8546,8 +8425,7 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
|
|
|
8546
8425
|
"Full onboarding is optional: call `orient action=start` if you want guided workspace setup. If you already ran setup, continue your task without restarting it."
|
|
8547
8426
|
];
|
|
8548
8427
|
scanLines.push(...buildRitualsSurfaceLines(orientView, { fetchFailed: orientFetchFailed || orientView?.fetchFailed === true }));
|
|
8549
|
-
|
|
8550
|
-
if (blankRuleLines.length > 0) scanLines.push("", "Rules:", ...blankRuleLines);
|
|
8428
|
+
scanLines.push("", ...buildOrientBriefingLines(orientView));
|
|
8551
8429
|
let oriented = false;
|
|
8552
8430
|
let orientationStatus2 = "no_session";
|
|
8553
8431
|
if (agentSessionId && taskAsked) {
|
|
@@ -8584,7 +8462,7 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
|
|
|
8584
8462
|
lines.push("");
|
|
8585
8463
|
}
|
|
8586
8464
|
if (mode === "brief") {
|
|
8587
|
-
lines.push(...
|
|
8465
|
+
lines.push(...buildOrientBriefingLines(orientView));
|
|
8588
8466
|
if (orientView?.strategicContext) {
|
|
8589
8467
|
const sc = orientView.strategicContext;
|
|
8590
8468
|
if (sc.playingFieldCount != null && sc.playingFieldCount > 0) {
|
|
@@ -8672,8 +8550,6 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
|
|
|
8672
8550
|
} else {
|
|
8673
8551
|
lines.push(...buildOperatingProtocol());
|
|
8674
8552
|
}
|
|
8675
|
-
const ruleLines = formatRuleListsLines(orientView.ruleLists);
|
|
8676
|
-
if (ruleLines.length > 0) lines.push("", "Rules:", ...ruleLines);
|
|
8677
8553
|
}
|
|
8678
8554
|
let orientationStatus2 = "no_session";
|
|
8679
8555
|
if (agentSessionId && taskAsked) {
|
|
@@ -8755,6 +8631,7 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
|
|
|
8755
8631
|
}
|
|
8756
8632
|
lines.push("_Need a collection that doesn't exist yet? Creating one is not available through this tool. Ask a platform admin to provision it, or enable the module ontology pack that owns it._");
|
|
8757
8633
|
lines.push("");
|
|
8634
|
+
lines.push(...buildOrientBriefingLines(orientView), "");
|
|
8758
8635
|
let fullCoherenceSnapshot;
|
|
8759
8636
|
if (readiness) {
|
|
8760
8637
|
if (!sampleTruncated && readiness.gaps.length > 0) {
|
|
@@ -8779,16 +8656,10 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
|
|
|
8779
8656
|
if (task) {
|
|
8780
8657
|
lines.push(`Working on: **${task}**`);
|
|
8781
8658
|
lines.push("");
|
|
8782
|
-
lines.push(...buildDirectionLines(orientView));
|
|
8783
8659
|
if (orientView?.strategicContext) {
|
|
8784
8660
|
const sc = orientView.strategicContext;
|
|
8785
8661
|
if (sc.playingFieldCount != null && sc.playingFieldCount > 0) lines.push(`**Playing field (${sc.playingFieldCount}):** ${(sc.playingField ?? []).join(", ")}`);
|
|
8786
|
-
|
|
8787
|
-
const wpSingularFull = getCollectionLabel("work_package", "singular", vocabCtx);
|
|
8788
|
-
const wpPluralFull = getCollectionLabel("work_package", "plural", vocabCtx);
|
|
8789
|
-
const betLine = currentWP ? `**Current ${wpSingularFull}:** ${currentWP}. ${sc.activeWorkPackageCount} active ${wpPluralFull}.` : `No active ${wpPluralFull}.`;
|
|
8790
|
-
lines.push(`${betLine} ${sc.activeTensionCount} open tension(s).`);
|
|
8791
|
-
lines.push("");
|
|
8662
|
+
lines.push(`${sc.activeWorkPackageCount} active ${getCollectionLabel("work_package", "plural", vocabCtx)}, ${sc.activeTensionCount} open tension(s).`, "");
|
|
8792
8663
|
}
|
|
8793
8664
|
if (orientView?.continuingFrom && orientView.continuingFrom.length > 0) {
|
|
8794
8665
|
lines.push("## Continuing from");
|
|
@@ -8977,8 +8848,6 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
|
|
|
8977
8848
|
lines.push(...formatRecoveryBlock(recoveryBlock));
|
|
8978
8849
|
}
|
|
8979
8850
|
} else {
|
|
8980
|
-
const scNoTaskLines = buildDirectionLines(orientView);
|
|
8981
|
-
if (scNoTaskLines.length > 0) lines.push(...scNoTaskLines, "");
|
|
8982
8851
|
lines.push(...buildRitualsSurfaceLines(orientView, { fetchFailed: orientFetchFailed || orientView?.fetchFailed === true }));
|
|
8983
8852
|
if (orientView?.activeWorkPackages?.length) {
|
|
8984
8853
|
lines.push("## Active work packages \u2014 current scope");
|
|
@@ -9033,8 +8902,6 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
|
|
|
9033
8902
|
lines.push("");
|
|
9034
8903
|
}
|
|
9035
8904
|
}
|
|
9036
|
-
const ruleLinesFull = formatRuleListsLines(orientView?.ruleLists);
|
|
9037
|
-
if (ruleLinesFull.length > 0) lines.push("", "Rules:", ...ruleLinesFull);
|
|
9038
8905
|
const classificationGaps = readiness?.gaps?.filter((g) => g.id?.startsWith?.(PURPOSE_GAP_PREFIX)) ?? [];
|
|
9039
8906
|
if (classificationGaps.length > 0) {
|
|
9040
8907
|
lines.push("## Classification gaps");
|
|
@@ -13851,47 +13718,16 @@ Write via \`update\`: \`draft\` | \`archived\` (\`accepted\` via \`commit\`, nev
|
|
|
13851
13718
|
`;
|
|
13852
13719
|
|
|
13853
13720
|
// src/resources/orientationMarkdown.ts
|
|
13854
|
-
function buildOrientationMarkdown(collections,
|
|
13855
|
-
|
|
13856
|
-
|
|
13857
|
-
sections.push(directionLines.join("\n"));
|
|
13858
|
-
}
|
|
13859
|
-
if (ruleLines && ruleLines.length > 0) {
|
|
13860
|
-
sections.push(
|
|
13861
|
-
"## Rules (delivered lists)\nEveryone/team/role rules currently served to this workspace and role (DEC-1774) \u2014 distinct from the collection-listing section below.\n\n" + ruleLines.join("\n")
|
|
13862
|
-
);
|
|
13721
|
+
function buildOrientationMarkdown(collections, briefingLines) {
|
|
13722
|
+
if (briefingLines.length === 0) {
|
|
13723
|
+
throw new Error("buildOrientationMarkdown: briefingLines is empty \u2014 pass the rendered briefing or the read-failed marker line");
|
|
13863
13724
|
}
|
|
13725
|
+
const sections = ["# Product Brain \u2014 Orientation", briefingLines.join("\n")];
|
|
13864
13726
|
sections.push(
|
|
13865
13727
|
"## About Product Brain (PB)\nPB is a knowledge management system used by many product teams. This section describes how PB works \u2014 not your product.\n\n### How PB Organizes Its Tools\n- **Tools** = actions with side-effects or dynamic computation (capture, accept, search).\n- **Resources** = stable, read-only data (orientation, terminology, collection schemas).\n- **Prompts** = multi-step choreography (workflows, guided capture, deep dives).\n- Every tool, resource, and prompt works for ANY workspace \u2014 no bespoke logic.\n- Resource templates (URI params) serve workspace-specific data through generic patterns.\n- Compound tools with `action` enums keep the tool count minimal.\n\n" + DATA_HANDLING_SECTION
|
|
13866
13728
|
);
|
|
13867
|
-
const wsRules = [];
|
|
13868
|
-
for (const p of principles ?? []) {
|
|
13869
|
-
wsRules.push({ id: p.entryId ?? "", name: p.name, severity: p.data?.severity ?? void 0, source: "principles" });
|
|
13870
|
-
}
|
|
13871
|
-
for (const s of standards ?? []) {
|
|
13872
|
-
wsRules.push({ id: s.entryId ?? "", name: s.name, severity: s.data?.severity ?? void 0, source: "standards" });
|
|
13873
|
-
}
|
|
13874
|
-
for (const r of businessRules ?? []) {
|
|
13875
|
-
wsRules.push({ id: r.entryId ?? "", name: r.name, severity: r.data?.severity ?? void 0, source: "rules" });
|
|
13876
|
-
}
|
|
13877
|
-
if (wsRules.length > 0) {
|
|
13878
|
-
const ruleLines2 = wsRules.map((r) => {
|
|
13879
|
-
const sev = r.severity ? ` [${r.severity}]` : "";
|
|
13880
|
-
return `- **${r.id}**: ${r.name}${sev}`;
|
|
13881
|
-
}).join("\n");
|
|
13882
|
-
sections.push(
|
|
13883
|
-
`## Your Workspace Principles & Rules (${wsRules.length} active)
|
|
13884
|
-
These are principles, standards, and rules your team has accepted onto the Chain. Respect them during implementation.
|
|
13885
|
-
|
|
13886
|
-
` + ruleLines2 + '\n\nUse `entries action=get entryId="<ID>"` to drill into any rule before making changes in that area.'
|
|
13887
|
-
);
|
|
13888
|
-
} else {
|
|
13889
|
-
sections.push(
|
|
13890
|
-
"## Your Workspace Principles & Rules\nNo active principles, standards, or rules on the Chain yet.\nUse `capture` with collection `principles`, `standards`, or `rules` to add your team's guardrails.\nOnce accepted, they appear here at orient time \u2014 so every agent session starts with your rules visible."
|
|
13891
|
-
);
|
|
13892
|
-
}
|
|
13893
13729
|
sections.push(
|
|
13894
|
-
"## Core Product Architecture\nThe Chain is a versioned, connected, compounding knowledge base \u2014 the SSOT for a product team.\nEverything on the Chain is one of **two primitives**:\n\n- **Entry** (atom) \u2014 a discrete knowledge unit: target audience,
|
|
13730
|
+
"## Core Product Architecture\nThe Chain is a versioned, connected, compounding knowledge base \u2014 the SSOT for a product team.\nEverything on the Chain is one of **two primitives**:\n\n- **Entry** (atom) \u2014 a discrete knowledge unit: target audience, rule, glossary term, metric, tension. Lives in a collection.\n- **Process** (authored) \u2014 a narrative chain with named links (Strategy Coherence, IDM Proposal). Content is inline text. Collection: `chains`.\n\nEntries are atoms. Processes author narrative from atoms.\nBoth share the same versioning, branching, gating, and relation system.\n\nThe Chain compounds: each new relation makes entries discoverable from more starting points \u2192 context gathering returns richer results \u2192 AI processes have more context \u2192 quality scores improve \u2192 next accept is smarter than the last."
|
|
13895
13731
|
);
|
|
13896
13732
|
sections.push(
|
|
13897
13733
|
"## Architecture\n```\nCursor (stdio) \u2192 MCP Server (mcp-server/src/index.ts)\n \u2192 POST /api/aki with Bearer token\n \u2192 Convex HTTP Action (convex/http.ts)\n \u2192 internalQuery / internalMutation (convex/agentKnowledge/*)\n \u2192 Convex DB (workspace-scoped)\n```\nSecurity: API key auth on every request, workspace-scoped data, internal functions blocked from external clients.\nKey files: `packages/mcp-server/src/client.ts` (HTTP client + audit), `convex/schema.ts` (schema)."
|
|
@@ -13914,13 +13750,8 @@ Tags for filtering (e.g. \`severity:high\`), relations via \`entryRelations\`, v
|
|
|
13914
13750
|
"## Data Model\nCould not load collections \u2014 use `collections action=list` to browse manually."
|
|
13915
13751
|
);
|
|
13916
13752
|
}
|
|
13917
|
-
const rulesCount = businessRules ? `${businessRules.length} entries` : "not loaded \u2014 collection may not exist yet";
|
|
13918
13753
|
sections.push(
|
|
13919
|
-
|
|
13920
|
-
Collection: \`rules\` (${rulesCount}).
|
|
13921
|
-
Find rules: \`entries action=search\` for text search, \`entries action=list collection=rules\` to browse.
|
|
13922
|
-
Check compliance: use the \`review-against-rules\` prompt (pass a domain).
|
|
13923
|
-
Draft a new rule: use the \`draft-rule-from-context\` prompt.`
|
|
13754
|
+
'## Rules\nThe rules that bind you are in the briefing above, each with its why. A rule on no list binds nobody.\nOpen one: `entries action=get entryId="<ID>"`. Find one: `entries action=search query="<noun>"`.\nDraft a new rule: use the `draft-rule-from-context` prompt.'
|
|
13924
13755
|
);
|
|
13925
13756
|
sections.push(
|
|
13926
13757
|
"## Knowledge Graph\nEntries are connected via typed relations (`entryRelations` table). Relations are bidirectional and collection-agnostic \u2014 any entry can link to any other entry.\n\n**Recommended relation types** (extensible \u2014 any string accepted):\n- `governs` \u2014 a rule constrains behavior of a feature\n- `defines_term_for` \u2014 a glossary term is canonical vocabulary for a feature/area\n- `belongs_to` \u2014 a feature belongs to a product area or parent concept (typed successor: `anchored_to`)\n- `informs` \u2014 a decision or insight informs a feature\n- `surfaces_tension_in` \u2014 a tension exists within a feature area\n- `related_to`, `depends_on`, `replaces`, `conflicts_with`, `references`, `confused_with`\n\nEach relation type is defined as a glossary entry (prefix `GT-REL-*`) to prevent terminology drift.\n\n**Tools:**\n- `context action=gather` \u2014 get the full context around any entry (multi-hop graph traversal)\n- `relations action=suggest` \u2014 discover potential connections for an entry\n- `relations action=create` \u2014 create a typed link between two entries\n- `relations action=find` \u2014 list direct relations for an entry\n\n**Convention:** When creating or updating entries in governed collections, always use `relations action=suggest` to discover and create relevant relations."
|
|
@@ -13940,8 +13771,7 @@ All other collections use the \`ENT-{random}\` fallback profile.
|
|
|
13940
13771
|
**Prompts** (invoke via MCP prompt protocol):
|
|
13941
13772
|
- \`name-check\` \u2014 verify a name against glossary conventions
|
|
13942
13773
|
- \`draft-decision-record\` \u2014 scaffold a decision entry
|
|
13943
|
-
- \`
|
|
13944
|
-
- \`draft-rule-from-context\` \u2014 create a new business rule from context
|
|
13774
|
+
- \`draft-rule-from-context\` \u2014 create a new rule from context
|
|
13945
13775
|
|
|
13946
13776
|
Use \`quality action=check\` to score existing entries retroactively.
|
|
13947
13777
|
Use \`entries action=update\` for post-creation adjustments (status changes, field updates, deprecation).`
|
|
@@ -13952,11 +13782,8 @@ Use \`entries action=update\` for post-creation adjustments (status changes, fie
|
|
|
13952
13782
|
return sections.join("\n\n---\n\n");
|
|
13953
13783
|
}
|
|
13954
13784
|
async function buildOrientationResourceText(kernelQuery2, agentSessionId) {
|
|
13955
|
-
const [collectionsResult,
|
|
13785
|
+
const [collectionsResult, orientViewResult] = await Promise.allSettled([
|
|
13956
13786
|
kernelQuery2("chain.listCollections"),
|
|
13957
|
-
kernelQuery2("chain.listEntries", { collectionSlug: "standards" }),
|
|
13958
|
-
kernelQuery2("chain.listEntries", { collectionSlug: "rules" }),
|
|
13959
|
-
kernelQuery2("chain.listEntries", { collectionSlug: "principles" }),
|
|
13960
13787
|
kernelQuery2("chain.getOrientView", {
|
|
13961
13788
|
tier: "summary",
|
|
13962
13789
|
invocationPath: "unknown",
|
|
@@ -13964,22 +13791,17 @@ async function buildOrientationResourceText(kernelQuery2, agentSessionId) {
|
|
|
13964
13791
|
})
|
|
13965
13792
|
]);
|
|
13966
13793
|
const collections = collectionsResult.status === "fulfilled" ? collectionsResult.value : null;
|
|
13967
|
-
|
|
13968
|
-
const businessRules = rulesResult.status === "fulfilled" ? rulesResult.value : null;
|
|
13969
|
-
const principles = principlesResult.status === "fulfilled" ? principlesResult.value : null;
|
|
13970
|
-
let directionLines;
|
|
13971
|
-
let ruleLines = [];
|
|
13794
|
+
let briefingLines;
|
|
13972
13795
|
if (orientViewResult.status === "rejected") {
|
|
13973
13796
|
const reason = orientViewResult.reason instanceof Error ? orientViewResult.reason.message : String(orientViewResult.reason);
|
|
13974
13797
|
const normalized = sanitizeSingleLineField(reason);
|
|
13975
13798
|
const truncated = normalized.length > 120 ? `${normalized.slice(0, 120)}\u2026` : normalized;
|
|
13976
|
-
|
|
13799
|
+
briefingLines = [`_Briefing unavailable: the orient read failed (${truncated}); purpose, objective and the rules that bind you are not shown. Read this resource again or run orient to retry._`];
|
|
13977
13800
|
} else {
|
|
13978
13801
|
const orientView = orientViewResult.value;
|
|
13979
|
-
|
|
13980
|
-
ruleLines = agentSessionId ? formatRuleListsLines(orientView.ruleLists) : buildEveryoneOnlyRuleListsLines(orientView.ruleLists);
|
|
13802
|
+
briefingLines = buildOrientBriefingLines(orientView, { everyoneOnly: !agentSessionId });
|
|
13981
13803
|
}
|
|
13982
|
-
return buildOrientationMarkdown(collections,
|
|
13804
|
+
return buildOrientationMarkdown(collections, briefingLines);
|
|
13983
13805
|
}
|
|
13984
13806
|
|
|
13985
13807
|
// src/resources/terminologyResource.ts
|
|
@@ -14608,4 +14430,4 @@ export {
|
|
|
14608
14430
|
createProductBrainServer,
|
|
14609
14431
|
initFeatureFlags
|
|
14610
14432
|
};
|
|
14611
|
-
//# sourceMappingURL=chunk-
|
|
14433
|
+
//# sourceMappingURL=chunk-YCGDWKLK.js.map
|