@productbrain/mcp 0.0.1-beta.10313 → 0.0.1-beta.10326
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.
|
@@ -4087,7 +4087,7 @@ async function handleDelete(from, to, type) {
|
|
|
4087
4087
|
}
|
|
4088
4088
|
|
|
4089
4089
|
// src/tools/context.ts
|
|
4090
|
-
import { z as
|
|
4090
|
+
import { z as z18 } from "zod/v3";
|
|
4091
4091
|
|
|
4092
4092
|
// src/tools/documents.ts
|
|
4093
4093
|
import { z as z13 } from "zod/v3";
|
|
@@ -4168,7 +4168,7 @@ This row pre-dates snapshot capture (legacy backfill), so no summary is availabl
|
|
|
4168
4168
|
}
|
|
4169
4169
|
|
|
4170
4170
|
// src/tools/contextLookups.ts
|
|
4171
|
-
import { z as
|
|
4171
|
+
import { z as z17 } from "zod/v3";
|
|
4172
4172
|
|
|
4173
4173
|
// src/tools/graph.ts
|
|
4174
4174
|
import { z as z14 } from "zod/v3";
|
|
@@ -4440,46 +4440,312 @@ function registerPeopleTools(server) {
|
|
|
4440
4440
|
);
|
|
4441
4441
|
}
|
|
4442
4442
|
|
|
4443
|
+
// src/tools/outcome.ts
|
|
4444
|
+
import { z as z16 } from "zod/v3";
|
|
4445
|
+
|
|
4446
|
+
// src/lib/outcomeObjectiveLines.ts
|
|
4447
|
+
var LOOKUP_LINE = {
|
|
4448
|
+
none: "none: no accepted objective holds this entry",
|
|
4449
|
+
capped: "not found: the objectives or key results read were capped before reaching this one",
|
|
4450
|
+
unavailable: "could not be read just now; run show again"
|
|
4451
|
+
};
|
|
4452
|
+
var INDENT = " ";
|
|
4453
|
+
function siblingLine(kr, clean) {
|
|
4454
|
+
const current = kr.readingUnresolved ? 'current unresolved, not "never read"' : kr.currentValue === null ? "no reading yet" : `current ${kr.currentValue}`;
|
|
4455
|
+
const target = kr.targetValue === null ? "" : `, target ${kr.targetValue}`;
|
|
4456
|
+
return `${clean(kr.entryId)} \u2014 ${clean(kr.name)} (${current}${target})`;
|
|
4457
|
+
}
|
|
4458
|
+
function formatOutcomeObjectiveLines(view, clean) {
|
|
4459
|
+
const o = view.objective;
|
|
4460
|
+
if (view.objectiveLookup !== "found" || !o) return [` objective ${LOOKUP_LINE[view.objectiveLookup === "found" ? "none" : view.objectiveLookup]}`];
|
|
4461
|
+
const lines = [` objective ${clean(o.entryId)} \u2014 ${clean(o.name)}`];
|
|
4462
|
+
if (o.siblings.length === 0 && !o.truncated) return [...lines, " siblings none: the only key result under this objective"];
|
|
4463
|
+
o.siblings.forEach((kr, i) => lines.push(`${i === 0 ? " siblings " : INDENT}${siblingLine(kr, clean)}`));
|
|
4464
|
+
const more = o.hiddenSiblings > 0 ? `and at least ${o.hiddenSiblings} more not shown` : "more may exist: the key results read were capped";
|
|
4465
|
+
if (o.truncated) lines.push(`${o.siblings.length === 0 ? " siblings " : INDENT}${more}`);
|
|
4466
|
+
return lines;
|
|
4467
|
+
}
|
|
4468
|
+
|
|
4469
|
+
// src/tools/outcome.ts
|
|
4470
|
+
var OUTCOME_ACTIONS = ["record"];
|
|
4471
|
+
var OUTCOME_READS_MOVED = "outcome only records readings. Read with the read-only context tool: context action=outcome entryId=... (the derived view, its objective and sibling key results) or context action=readings entryId=... (the readings, newest first).";
|
|
4472
|
+
var READING_KINDS = ["measurement", "estimate", "correction"];
|
|
4473
|
+
var outcomeSchema = z16.object({
|
|
4474
|
+
// The host validates arguments before the handler runs, so the pointer to the moved reads rides the enum's own error.
|
|
4475
|
+
action: z16.enum(OUTCOME_ACTIONS, { errorMap: () => ({ message: OUTCOME_READS_MOVED }) }).describe(
|
|
4476
|
+
"'record': record a reading (evidence, not a verdict). Reads live on context: action=outcome and action=readings."
|
|
4477
|
+
),
|
|
4478
|
+
entryId: z16.string().max(200).optional().describe("The key result (or other outcome-bearing) entry, by its chain id. Required."),
|
|
4479
|
+
// PR #858 review round 3 (Codex P2, PRRT_kwDORS4ils6gXHj9): a JSON number that overflows to
|
|
4480
|
+
// `Infinity` (e.g. `1e400`) parses fine in JS and passes a plain `z.number()`, but
|
|
4481
|
+
// `callGateway()` serializes it with `JSON.stringify`, which turns `Infinity` into `null` —
|
|
4482
|
+
// the backend's `v.number()` validator then rejects a call this tool's own schema accepted.
|
|
4483
|
+
// `.finite()` rejects it here, matching the explicit finite-value checks the CLI/other outcome
|
|
4484
|
+
// entry surfaces already use.
|
|
4485
|
+
value: z16.number().finite().optional().describe("'record': the measured value. Required for 'record'."),
|
|
4486
|
+
valueText: z16.string().max(500).optional().describe("'record': verbatim as-reported form when the source was not clean, e.g. '~62%'. Display only."),
|
|
4487
|
+
asOf: z16.string().max(64).optional().describe("'record': when the world was in this state, as a parseable date (default: now). Back-dating a backfill is legitimate \u2014 it shows up as asOf earlier than recordedAt."),
|
|
4488
|
+
kind: z16.enum(READING_KINDS).optional().describe("'record': measurement | estimate | correction (default: measurement)."),
|
|
4489
|
+
correctsReadingId: z16.string().max(200).optional().describe("'record': required with kind='correction' \u2014 the reading id this replaces. Refused if that row is already superseded."),
|
|
4490
|
+
recordedByRoleId: z16.string().max(200).optional().describe("'record': the accountable role (default: the entry's reporterRoleId, then its owning role)."),
|
|
4491
|
+
note: z16.string().max(2e3).optional().describe("'record': free-text note recorded with the reading."),
|
|
4492
|
+
source: z16.string().max(500).optional().describe("'record': where the number came from \u2014 a dashboard name, a query, a URL.")
|
|
4493
|
+
});
|
|
4494
|
+
var recordVariant = z16.object({
|
|
4495
|
+
action: z16.literal("record"),
|
|
4496
|
+
entryId: z16.string().max(200),
|
|
4497
|
+
value: z16.number().finite(),
|
|
4498
|
+
valueText: z16.string().max(500).optional(),
|
|
4499
|
+
asOf: z16.string().max(64).optional(),
|
|
4500
|
+
kind: z16.enum(READING_KINDS).optional(),
|
|
4501
|
+
correctsReadingId: z16.string().max(200).optional(),
|
|
4502
|
+
recordedByRoleId: z16.string().max(200).optional(),
|
|
4503
|
+
note: z16.string().max(2e3).optional(),
|
|
4504
|
+
source: z16.string().max(500).optional()
|
|
4505
|
+
});
|
|
4506
|
+
var outcomeActionUnion = z16.discriminatedUnion("action", [recordVariant]);
|
|
4507
|
+
var OUTCOME_ACTION_SPECS = {
|
|
4508
|
+
record: {
|
|
4509
|
+
params: ["entryId", "value", "valueText", "asOf", "kind", "correctsReadingId", "recordedByRoleId", "note", "source"],
|
|
4510
|
+
description: "entryId and value are required; the rest are optional."
|
|
4511
|
+
}
|
|
4512
|
+
};
|
|
4513
|
+
function safeDateSlice(ms) {
|
|
4514
|
+
const d = new Date(ms);
|
|
4515
|
+
return Number.isNaN(d.getTime()) ? "invalid-date" : d.toISOString().slice(0, 10);
|
|
4516
|
+
}
|
|
4517
|
+
function formatRecordReceipt(numericValue, entryId, valueText, receipt) {
|
|
4518
|
+
const tier = receipt.independenceTier ?? "unknown";
|
|
4519
|
+
const lines = [
|
|
4520
|
+
`Recorded ${numericValue}${valueText ? ` ("${sanitizeSingleLineField(valueText)}")` : ""} on ${sanitizeSingleLineField(entryId)}.`,
|
|
4521
|
+
` attributed: ${receipt.actorKind ?? "unknown"} \xB7 independence: ${tier}`
|
|
4522
|
+
];
|
|
4523
|
+
if (tier === "provenance_unknown") {
|
|
4524
|
+
lines.push(" (no session named, so provenance is unknown \u2014 that is the honest answer, not an error)");
|
|
4525
|
+
}
|
|
4526
|
+
return lines.join("\n");
|
|
4527
|
+
}
|
|
4528
|
+
function formatReadingsList(entryId, result2) {
|
|
4529
|
+
const safeEntryId = sanitizeSingleLineField(entryId);
|
|
4530
|
+
const rows = result2?.readings ?? [];
|
|
4531
|
+
if (rows.length === 0) return `No readings recorded on ${safeEntryId} yet.`;
|
|
4532
|
+
const lines = rows.map((row) => {
|
|
4533
|
+
const when = safeDateSlice(row.asOf);
|
|
4534
|
+
const superseded = row.supersededByReadingId ? ` <- superseded by ${row.supersededByReadingId}` : "";
|
|
4535
|
+
const text = row.valueText ? ` ("${sanitizeSingleLineField(row.valueText)}")` : "";
|
|
4536
|
+
const note = row.note ? ` - ${sanitizeSingleLineField(row.note)}` : "";
|
|
4537
|
+
return ` ${when} ${String(row.value).padStart(8)}${text} [${row.kind}\xB7${row.independenceTier}] ${row.readingId}${note}${superseded}`;
|
|
4538
|
+
});
|
|
4539
|
+
const tail = result2?.pageExhausted === false ? "\n (older readings not loaded - raise --limit)" : "";
|
|
4540
|
+
return `${rows.length} reading(s) on ${safeEntryId}, newest first:
|
|
4541
|
+
${lines.join("\n")}${tail}`;
|
|
4542
|
+
}
|
|
4543
|
+
var pct = (v, unit = "%") => v === void 0 ? "\u2014" : `${Math.round(v * 10) / 10}${unit}`;
|
|
4544
|
+
var roleLabel = (role) => role === null ? "not set" : role.name === null ? "a role that no longer exists" : sanitizeSingleLineField(role.name);
|
|
4545
|
+
function formatOutcomeShow(result2) {
|
|
4546
|
+
if (!result2) return "No outcome found.";
|
|
4547
|
+
const o = result2.outcome;
|
|
4548
|
+
const unit = o.unit ? ` ${sanitizeSingleLineField(o.unit)}` : "";
|
|
4549
|
+
const lines = [
|
|
4550
|
+
// N2 (TASK-367): the metric line is retired — the entry's own name (above) already states
|
|
4551
|
+
// what is measured — mirrors packages/cli/src/commands/outcome.ts text-for-text.
|
|
4552
|
+
`${sanitizeSingleLineField(result2.entryId)} \u2014 ${sanitizeSingleLineField(result2.name)}`,
|
|
4553
|
+
` current ${o.current ? `${o.current.value}${unit}` : "no readings yet"} (${o.readingCount} reading(s))`,
|
|
4554
|
+
` progress ${pct(o.progressPct)} direction ${o.direction}`,
|
|
4555
|
+
` pace ${pct(o.pacePct)} ${o.pacePct === void 0 ? "(no cycle end set)" : o.pacePct >= 0 ? "(ahead of pace)" : "(behind pace)"}`,
|
|
4556
|
+
` state ${o.state}${o.hasNoReadings ? " \u2014 never read" : ""}${o.overdueByMs ? ` (by ${Math.floor(o.overdueByMs / 864e5)}d)` : ""}`,
|
|
4557
|
+
` next due ${o.nextDueAt ? safeDateSlice(o.nextDueAt) : "no cadence set"}`,
|
|
4558
|
+
` owner ${roleLabel(o.ownerRole)}`,
|
|
4559
|
+
` reporter ${roleLabel(o.reporterRole)}`,
|
|
4560
|
+
` completion recorded as ${o.completion} (source: ${o.completionProvenance})`,
|
|
4561
|
+
` attestation weakest in cycle: ${o.weakestTierInCycle ?? "none recorded"} \u2014 reported, not enforced`,
|
|
4562
|
+
...formatOutcomeObjectiveLines(result2, sanitizeSingleLineField)
|
|
4563
|
+
// TASK-817: its objective and sibling key results
|
|
4564
|
+
];
|
|
4565
|
+
if (o.currentResolution === "page-exhausted") {
|
|
4566
|
+
lines.push(' note every loaded reading is superseded and more remain \u2014 this is not "never read"');
|
|
4567
|
+
}
|
|
4568
|
+
if (result2.readyToCloseInstruction) {
|
|
4569
|
+
lines.push("", ` ${result2.readyToCloseInstruction}`);
|
|
4570
|
+
}
|
|
4571
|
+
return lines.join("\n");
|
|
4572
|
+
}
|
|
4573
|
+
function outcomeErrorResult(err, action, entryId, params = {}) {
|
|
4574
|
+
const classified = classifyError(err);
|
|
4575
|
+
const definedParams = Object.fromEntries(Object.entries(params).filter(([, v]) => v !== void 0));
|
|
4576
|
+
const isUnverifiedRecordTimeout = action === "record" && classified.code === "GATEWAY_TIMEOUT";
|
|
4577
|
+
const isMissingCorrectionTarget = action === "record" && classified.code === "NOT_FOUND" && classified.message.startsWith("Reading not found");
|
|
4578
|
+
const defaultActions = isUnverifiedRecordTimeout ? [
|
|
4579
|
+
{ tool: "context", description: "Check whether the reading already landed", parameters: { action: "readings", entryId } },
|
|
4580
|
+
{ tool: "context", description: "Check the derived view", parameters: { action: "outcome", entryId } }
|
|
4581
|
+
] : isMissingCorrectionTarget ? [{ tool: "context", description: "List readings for this entry to find a valid correctsReadingId", parameters: { action: "readings", entryId } }] : retryIsFutile(classified.code) ? void 0 : [retryAction(action, definedParams)];
|
|
4582
|
+
return failureResult(
|
|
4583
|
+
classified.message,
|
|
4584
|
+
classified.code,
|
|
4585
|
+
classified.message,
|
|
4586
|
+
isMissingCorrectionTarget ? `Reading correctsReadingId not found for entryId='${entryId}'. Use context action=readings to see valid reading ids.` : classified.recovery ?? "Use context action=outcome with a valid entryId to check the key result exists.",
|
|
4587
|
+
isMissingCorrectionTarget ? defaultActions : classified.availableActions ?? defaultActions,
|
|
4588
|
+
classified.diagnostics
|
|
4589
|
+
);
|
|
4590
|
+
}
|
|
4591
|
+
function retryAction(action, params) {
|
|
4592
|
+
if (action === "record") return { tool: "outcome", description: "Retry record", parameters: { action, ...params } };
|
|
4593
|
+
const read = action === "show" ? "outcome" : "readings";
|
|
4594
|
+
return { tool: "context", description: `Retry ${read}`, parameters: { action: read, ...params } };
|
|
4595
|
+
}
|
|
4596
|
+
async function handleOutcomeRecord(entryId, value, opts = {}) {
|
|
4597
|
+
requireWriteAccess();
|
|
4598
|
+
if (opts.correctsReadingId !== void 0 && opts.kind !== "correction") {
|
|
4599
|
+
return failureResult(
|
|
4600
|
+
"correctsReadingId is only meaningful with kind='correction'.",
|
|
4601
|
+
"VALIDATION_ERROR",
|
|
4602
|
+
"correctsReadingId is only meaningful with kind='correction'.",
|
|
4603
|
+
"Set kind='correction', or drop correctsReadingId to record an ordinary reading."
|
|
4604
|
+
);
|
|
4605
|
+
}
|
|
4606
|
+
if (opts.kind === "correction" && opts.correctsReadingId === void 0) {
|
|
4607
|
+
return failureResult(
|
|
4608
|
+
"kind='correction' requires correctsReadingId.",
|
|
4609
|
+
"VALIDATION_ERROR",
|
|
4610
|
+
"kind='correction' requires correctsReadingId.",
|
|
4611
|
+
"A correction must name the reading it replaces \u2014 find it with context action=readings."
|
|
4612
|
+
);
|
|
4613
|
+
}
|
|
4614
|
+
let asOf;
|
|
4615
|
+
if (opts.asOf !== void 0) {
|
|
4616
|
+
const parsed = Date.parse(opts.asOf);
|
|
4617
|
+
if (Number.isNaN(parsed)) {
|
|
4618
|
+
return failureResult(
|
|
4619
|
+
`asOf must be a parseable date (got "${opts.asOf}").`,
|
|
4620
|
+
"VALIDATION_ERROR",
|
|
4621
|
+
`asOf must be a parseable date (got "${opts.asOf}").`,
|
|
4622
|
+
"Example: asOf='2026-03-01'. Back-dating is legitimate \u2014 a backfill shows up as asOf earlier than recordedAt."
|
|
4623
|
+
);
|
|
4624
|
+
}
|
|
4625
|
+
asOf = parsed;
|
|
4626
|
+
}
|
|
4627
|
+
try {
|
|
4628
|
+
const agentSessionId = getAgentSessionId();
|
|
4629
|
+
const receipt = await kernelMutation("outcomes.recordReading", {
|
|
4630
|
+
entryId,
|
|
4631
|
+
value,
|
|
4632
|
+
...asOf !== void 0 ? { asOf } : {},
|
|
4633
|
+
...opts.kind ? { kind: opts.kind } : {},
|
|
4634
|
+
...opts.correctsReadingId ? { correctsReadingId: opts.correctsReadingId } : {},
|
|
4635
|
+
...opts.recordedByRoleId ? { recordedByRoleId: opts.recordedByRoleId } : {},
|
|
4636
|
+
...opts.note ? { note: opts.note } : {},
|
|
4637
|
+
...opts.source ? { source: opts.source } : {},
|
|
4638
|
+
...opts.valueText ? { valueText: opts.valueText } : {},
|
|
4639
|
+
...agentSessionId ? { agentSessionId } : {}
|
|
4640
|
+
});
|
|
4641
|
+
const message = formatRecordReceipt(value, entryId, opts.valueText, receipt);
|
|
4642
|
+
return successResult(message, message, receipt);
|
|
4643
|
+
} catch (err) {
|
|
4644
|
+
return outcomeErrorResult(err, "record", entryId, { entryId, value, ...opts });
|
|
4645
|
+
}
|
|
4646
|
+
}
|
|
4647
|
+
async function handleOutcomeList(entryId, limit) {
|
|
4648
|
+
try {
|
|
4649
|
+
const result2 = await kernelQuery("outcomes.listReadings", {
|
|
4650
|
+
entryId,
|
|
4651
|
+
...limit !== void 0 ? { limit } : {}
|
|
4652
|
+
});
|
|
4653
|
+
const message = formatReadingsList(entryId, result2);
|
|
4654
|
+
return successResult(message, message, result2);
|
|
4655
|
+
} catch (err) {
|
|
4656
|
+
return outcomeErrorResult(err, "list", entryId, { entryId, limit });
|
|
4657
|
+
}
|
|
4658
|
+
}
|
|
4659
|
+
async function handleOutcomeShow(entryId) {
|
|
4660
|
+
try {
|
|
4661
|
+
const result2 = await kernelQuery("outcomes.showOutcome", { entryId });
|
|
4662
|
+
const message = formatOutcomeShow(result2);
|
|
4663
|
+
return successResult(message, message, result2);
|
|
4664
|
+
} catch (err) {
|
|
4665
|
+
return outcomeErrorResult(err, "show", entryId, { entryId });
|
|
4666
|
+
}
|
|
4667
|
+
}
|
|
4668
|
+
function registerOutcomeTools(server) {
|
|
4669
|
+
const outcomeHandlers = {
|
|
4670
|
+
record: (data) => handleOutcomeRecord(data.entryId, data.value, {
|
|
4671
|
+
valueText: data.valueText,
|
|
4672
|
+
asOf: data.asOf,
|
|
4673
|
+
kind: data.kind,
|
|
4674
|
+
correctsReadingId: data.correctsReadingId,
|
|
4675
|
+
recordedByRoleId: data.recordedByRoleId,
|
|
4676
|
+
note: data.note,
|
|
4677
|
+
source: data.source
|
|
4678
|
+
})
|
|
4679
|
+
};
|
|
4680
|
+
server.registerTool(
|
|
4681
|
+
"outcome",
|
|
4682
|
+
{
|
|
4683
|
+
title: "Outcome",
|
|
4684
|
+
description: (
|
|
4685
|
+
// Chain IDs stay OUT of this user-facing string (check:chain-id-leaks) — same
|
|
4686
|
+
// precedent role.ts's own docblock names for its Team-Lead-vacancy sentence.
|
|
4687
|
+
'Key-result outcomes: record the measured readings behind a number.\n\n- **record**: Record a reading \u2014 evidence, not a verdict; any connector may record one.\n\nRead with the read-only `context` tool: `context action=outcome entryId="..."` (the derived view, its objective and sibling key results), `context action=readings entryId="..."` (the readings).'
|
|
4688
|
+
),
|
|
4689
|
+
inputSchema: outcomeSchema,
|
|
4690
|
+
// DEC-1894 / DEC-74: the reads live on the read-only `context` tool; record, the one action
|
|
4691
|
+
// left, appends to a ledger and never overwrites, so it is a write but not destructive.
|
|
4692
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }
|
|
4693
|
+
},
|
|
4694
|
+
thinWrapper(async (args) => {
|
|
4695
|
+
const parsed = parseOrFail(outcomeSchema, args);
|
|
4696
|
+
if (!parsed.ok) return parsed.result;
|
|
4697
|
+
const { action } = parsed.data;
|
|
4698
|
+
return runWithToolContext(
|
|
4699
|
+
{ tool: "outcome", action },
|
|
4700
|
+
() => dispatchDiscriminated("outcome", outcomeActionUnion, parsed.data, OUTCOME_ACTION_SPECS, outcomeHandlers)
|
|
4701
|
+
);
|
|
4702
|
+
})
|
|
4703
|
+
);
|
|
4704
|
+
}
|
|
4705
|
+
|
|
4443
4706
|
// src/tools/contextLookups.ts
|
|
4444
|
-
var LOOKUP_ACTIONS = ["get", "batch", "history", "list", "search", "find", "people"];
|
|
4445
|
-
var statusFilterSchema =
|
|
4446
|
-
var LOOKUP_ACTION_DESCRIBE = "'get': one entry in full by ID. 'batch': up to 20 entries by ID. 'history': audit trail for an entry. 'list': browse entries with filters (accepted by default). 'search': full-text search across entries. 'find': an entry's direct relations (direction: incoming|outgoing|both, default both). 'people': the workspace's members with name, email and status. ";
|
|
4447
|
-
var LOOKUP_TOOL_LINES = "- **get**: Fetch a single entry by ID \u2014 full record with data, labels, relations, history.\n- **batch**: Fetch multiple entries (max 20) in one call. Same shape as get per entry.\n- **history**: Audit trail for an entry.\n- **list**: Browse entries with optional filters (collection, status, tag, label). Use collections action=list first to discover slugs.\n- **search**: Full-text search across entries. Scope by collection or filter by status.\n- **find**: An entry's direct relations, incoming and outgoing. NOT full-text search (use search).\n- **people**: The workspace's members: name, email, status, role. Max 200.\n";
|
|
4707
|
+
var LOOKUP_ACTIONS = ["get", "batch", "history", "list", "search", "find", "people", "outcome", "readings"];
|
|
4708
|
+
var statusFilterSchema = z17.union([z17.string().max(200), z17.array(z17.enum(ENTRY_STATUS_READ_WORDS)).max(5)]);
|
|
4709
|
+
var LOOKUP_ACTION_DESCRIBE = "'get': one entry in full by ID. 'batch': up to 20 entries by ID. 'history': audit trail for an entry. 'list': browse entries with filters (accepted by default). 'search': full-text search across entries. 'find': an entry's direct relations (direction: incoming|outgoing|both, default both). 'people': the workspace's members with name, email and status. 'outcome': a key result's derived view, its objective and sibling key results. 'readings': its readings, newest first. ";
|
|
4710
|
+
var LOOKUP_TOOL_LINES = "- **get**: Fetch a single entry by ID \u2014 full record with data, labels, relations, history.\n- **batch**: Fetch multiple entries (max 20) in one call. Same shape as get per entry.\n- **history**: Audit trail for an entry.\n- **list**: Browse entries with optional filters (collection, status, tag, label). Use collections action=list first to discover slugs.\n- **search**: Full-text search across entries. Scope by collection or filter by status.\n- **find**: An entry's direct relations, incoming and outgoing. NOT full-text search (use search).\n- **people**: The workspace's members: name, email, status, role. Max 200.\n- **outcome**: A key result's derived view (current, progress, pace, staleness, recorded completion) with its objective and up to 5 sibling key results.\n- **readings**: A key result's readings, newest first; superseded rows are marked with their replacement. Record one with `outcome action=record`.\n";
|
|
4448
4711
|
var lookupParams = {
|
|
4449
|
-
entryIds:
|
|
4450
|
-
collection:
|
|
4451
|
-
query:
|
|
4712
|
+
entryIds: z17.array(z17.string().max(200)).min(1).max(20).optional().describe("For 'batch': entry IDs, e.g. ['TYPE-strategy', 'STR-jljeg7']"),
|
|
4713
|
+
collection: z17.string().max(200).optional().describe("For 'list'/'search': collection slug, e.g. 'glossary', 'tracking-events'."),
|
|
4714
|
+
query: z17.string().min(2).max(500).optional().describe("For 'search': search text (min 2 characters)."),
|
|
4452
4715
|
// 'active'/'accepted'/'current' are the same trust level (DEC-1575/DEC-1788) — all enumerated, never one substituted.
|
|
4453
4716
|
status: statusFilterSchema.optional().describe(
|
|
4454
4717
|
`For 'list': defaults to accepted entries (active/accepted/current); use status='draft' to discover drafts. One lifecycle or category value (${ENTRY_STATUS_READ_WORDS.join("|")}). For 'search': one value OR an array of up to 5 (e.g. ['active','accepted']).`
|
|
4455
4718
|
),
|
|
4456
|
-
tag:
|
|
4457
|
-
label:
|
|
4719
|
+
tag: z17.string().max(200).optional().describe("For 'list': filter by internal tag."),
|
|
4720
|
+
label: z17.string().max(200).optional().describe("For 'list': filter by label slug \u2014 matches entries across all collections."),
|
|
4721
|
+
limit: z17.number().int().positive().max(200).optional().describe("For 'readings': max rows to return (default and maximum 200).")
|
|
4458
4722
|
};
|
|
4459
4723
|
var lookupVariants = [
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
action:
|
|
4465
|
-
collection:
|
|
4466
|
-
status:
|
|
4724
|
+
z17.object({ action: z17.literal("get"), entryId: z17.string().max(200) }),
|
|
4725
|
+
z17.object({ action: z17.literal("batch"), entryIds: z17.array(z17.string().max(200)).min(1).max(20) }),
|
|
4726
|
+
z17.object({ action: z17.literal("history"), entryId: z17.string().max(200) }),
|
|
4727
|
+
z17.object({
|
|
4728
|
+
action: z17.literal("list"),
|
|
4729
|
+
collection: z17.string().max(200).optional(),
|
|
4730
|
+
status: z17.string().max(200).optional(),
|
|
4467
4731
|
// one status word; the flat union serves search
|
|
4468
|
-
tag:
|
|
4469
|
-
label:
|
|
4732
|
+
tag: z17.string().max(200).optional(),
|
|
4733
|
+
label: z17.string().max(200).optional()
|
|
4470
4734
|
}),
|
|
4471
|
-
|
|
4472
|
-
action:
|
|
4473
|
-
query:
|
|
4474
|
-
collection:
|
|
4735
|
+
z17.object({
|
|
4736
|
+
action: z17.literal("search"),
|
|
4737
|
+
query: z17.string().min(2).max(500),
|
|
4738
|
+
collection: z17.string().max(200).optional(),
|
|
4475
4739
|
status: statusFilterSchema.optional()
|
|
4476
4740
|
}),
|
|
4477
|
-
|
|
4478
|
-
action:
|
|
4479
|
-
entryId:
|
|
4480
|
-
direction:
|
|
4741
|
+
z17.object({
|
|
4742
|
+
action: z17.literal("find"),
|
|
4743
|
+
entryId: z17.string().max(200),
|
|
4744
|
+
direction: z17.enum(["incoming", "outgoing", "both"]).optional().default("both")
|
|
4481
4745
|
}),
|
|
4482
|
-
|
|
4746
|
+
z17.object({ action: z17.literal("people") }),
|
|
4747
|
+
z17.object({ action: z17.literal("outcome"), entryId: z17.string().max(200) }),
|
|
4748
|
+
z17.object({ action: z17.literal("readings"), entryId: z17.string().max(200), limit: z17.number().int().positive().max(200).optional() })
|
|
4483
4749
|
];
|
|
4484
4750
|
var LOOKUP_ACTION_SPECS = {
|
|
4485
4751
|
get: { params: ["entryId"], description: "entryId is required." },
|
|
@@ -4488,7 +4754,9 @@ var LOOKUP_ACTION_SPECS = {
|
|
|
4488
4754
|
list: { params: ["collection", "status", "tag", "label"], description: "Browse accepted entries by default; status='draft' lists drafts; status is one word. All params optional." },
|
|
4489
4755
|
search: { params: ["query", "collection", "status"], description: "Full-text search; query is required (min 2 chars)." },
|
|
4490
4756
|
find: { params: ["entryId", "direction"], description: "entryId is required." },
|
|
4491
|
-
people: { params: [], description: "No params." }
|
|
4757
|
+
people: { params: [], description: "No params." },
|
|
4758
|
+
outcome: { params: ["entryId"], description: "entryId is required." },
|
|
4759
|
+
readings: { params: ["entryId", "limit"], description: "entryId is required; limit is optional." }
|
|
4492
4760
|
};
|
|
4493
4761
|
function lookupHandlers(server) {
|
|
4494
4762
|
return {
|
|
@@ -4499,7 +4767,10 @@ function lookupHandlers(server) {
|
|
|
4499
4767
|
search: (data) => handleSearch(server, data.query, data.collection, data.status),
|
|
4500
4768
|
// logs progress to the client
|
|
4501
4769
|
find: (data) => handleFind(data.entryId, data.direction ?? "both"),
|
|
4502
|
-
people: () => handlePeopleList()
|
|
4770
|
+
people: () => handlePeopleList(),
|
|
4771
|
+
outcome: (data) => handleOutcomeShow(data.entryId),
|
|
4772
|
+
// DEC-1894 step 2 (TASK-817)
|
|
4773
|
+
readings: (data) => handleOutcomeList(data.entryId, data.limit)
|
|
4503
4774
|
};
|
|
4504
4775
|
}
|
|
4505
4776
|
|
|
@@ -4515,90 +4786,90 @@ function epistemicCollectionHint(collectionName) {
|
|
|
4515
4786
|
return "";
|
|
4516
4787
|
}
|
|
4517
4788
|
var CONTEXT_ACTIONS = [...LOOKUP_ACTIONS, "gather", "build", "neighborhood", "changes", "chain", "cross-cut", "incremental", "brief", "last-verified-brief"];
|
|
4518
|
-
var contextSchema =
|
|
4789
|
+
var contextSchema = z18.object({
|
|
4519
4790
|
// provenance: neighborhood BET-142; changes/chain/cross-cut/incremental/brief BET-239 (E4, E6)
|
|
4520
|
-
action:
|
|
4791
|
+
action: z18.enum(CONTEXT_ACTIONS).describe(
|
|
4521
4792
|
LOOKUP_ACTION_DESCRIBE + "'gather': assemble knowledge context (entry graph, task auto-load, journey mode, or graph mode). 'build': structured build spec for an entry. 'neighborhood': typed graph neighborhood for an entry \u2014 blocking chain, dependencies, parent context, tensions, staleness. 'changes': entries modified and relations created since a timestamp. Requires 'since' parameter. 'chain': directed traversal along one relation type to depth 4. Requires entryId. Optional: direction, relationType, maxHops (1-4). 'cross-cut': structural aggregation \u2014 all relations of a given type grouped by source collection. Requires 'relationType' parameter. 'incremental': delta since last brief run for a skill. Requires 'skill' parameter. Returns only entries changed since the skill's last brief. 'brief': compound intelligence query. Requires 'briefType' parameter: 'steering' (changes + structure + delta + readiness), 'confidence' (changes + active bets \u2014 use the pb CLI's `tensions list` for tensions), or 'delta' (changes + relations since timestamp). Optional 'since' for delta type. 'last-verified-brief': fetch the most recent verified brief snapshot for a (templateId, scopeKey) pair (absorbs documents action=get-last-verified-brief). Requires templateId and scopeKey."
|
|
4522
4793
|
),
|
|
4523
|
-
entryId:
|
|
4794
|
+
entryId: z18.string().max(200).optional().describe("For 'get'/'history'/'find'/'outcome'/'readings'/'build'/'neighborhood'/'chain': entry ID. For 'gather': optional (entry-graph mode)."),
|
|
4524
4795
|
...lookupParams,
|
|
4525
|
-
mapEntryId:
|
|
4796
|
+
mapEntryId: z18.string().max(200).optional().describe(
|
|
4526
4797
|
"For 'gather': journey map entry ID for journey-aware context. Returns context organised by journey stage. Takes precedence over entryId when both are supplied. Example: '<PREFIX>-<n>'."
|
|
4527
4798
|
),
|
|
4528
|
-
task:
|
|
4529
|
-
since:
|
|
4799
|
+
task: z18.string().max(2e3).optional().describe("For 'gather': natural-language task description for loading task-relevant governance, binding constraints, and supporting context."),
|
|
4800
|
+
since: z18.string().max(200).optional().describe(
|
|
4530
4801
|
"For 'changes': ISO 8601 timestamp \u2014 returns entries/relations modified since this time. For 'brief' briefType='delta': optional custom timestamp. Example: '2026-03-24T00:00:00Z'."
|
|
4531
4802
|
),
|
|
4532
|
-
direction:
|
|
4533
|
-
relationType:
|
|
4803
|
+
direction: z18.enum(["outgoing", "incoming", "both"]).optional().describe("For 'chain': 'outgoing' follows relations from source, 'incoming' to source (default outgoing). For 'find': incoming|outgoing|both (default both)."),
|
|
4804
|
+
relationType: z18.string().max(200).optional().describe(
|
|
4534
4805
|
"Relation type filter. For 'chain': optional filter to traverse only this relation type. For 'cross-cut': required \u2014 scans all relations of this type across the workspace. Examples: 'part_of', 'informs', 'governs', 'depends_on'."
|
|
4535
4806
|
),
|
|
4536
|
-
mode:
|
|
4537
|
-
maxHops:
|
|
4538
|
-
maxResults:
|
|
4539
|
-
strategy:
|
|
4540
|
-
skill:
|
|
4807
|
+
mode: z18.enum(["search", "graph"]).default("search").optional().describe("For gather: 'search' (default) or 'graph' (enhanced with provenance paths). Ignored when mapEntryId is provided."),
|
|
4808
|
+
maxHops: z18.number().min(1).max(4).default(2).describe("Relation traversal depth (1=direct only, 2=default, 3=wide net, 4=deep chain walk)"),
|
|
4809
|
+
maxResults: z18.number().min(1).max(25).default(10).optional().describe("Max entries to return in gather task mode (default 10)"),
|
|
4810
|
+
strategy: z18.enum(["hybrid", "keyword"]).default("keyword").optional().describe("Seed strategy for task-based gather: 'keyword' (FTS only, default) or 'hybrid' (vector + FTS). Only affects task mode."),
|
|
4811
|
+
skill: z18.string().max(200).optional().describe(
|
|
4541
4812
|
"Skill name for 'incremental' action \u2014 identifies which skill's brief history to compare against. Examples: 'preflight', 'shaping', 'review'. Required when action is 'incremental'."
|
|
4542
4813
|
),
|
|
4543
|
-
briefType:
|
|
4814
|
+
briefType: z18.enum(["steering", "confidence", "delta"]).optional().describe(
|
|
4544
4815
|
"Compound query type for 'brief' action. 'steering': 7d changes + structural aggregation (part_of, depends_on, constrains) + incremental delta + workspace readiness. 'confidence': 7d changes + active bets summary (tensions: use the pb CLI's `tensions list`, not this action). 'delta': changes + relations since a custom timestamp (use 'since' param). Required when action is 'brief'."
|
|
4545
4816
|
),
|
|
4546
|
-
templateId:
|
|
4817
|
+
templateId: z18.string().max(200).optional().describe(
|
|
4547
4818
|
"For 'last-verified-brief': brief template identifier \u2014 currently 'steering-brief' is the only registered template."
|
|
4548
4819
|
),
|
|
4549
|
-
scopeKey:
|
|
4820
|
+
scopeKey: z18.string().max(200).optional().describe(
|
|
4550
4821
|
"For 'last-verified-brief': canonical scope key \u2014 'workspace:<workspaceId>' or 'initiative:<INI-ID>'."
|
|
4551
4822
|
)
|
|
4552
4823
|
});
|
|
4553
|
-
var contextGatherVariant =
|
|
4554
|
-
action:
|
|
4555
|
-
entryId:
|
|
4556
|
-
mapEntryId:
|
|
4557
|
-
task:
|
|
4558
|
-
mode:
|
|
4559
|
-
maxHops:
|
|
4560
|
-
maxResults:
|
|
4561
|
-
strategy:
|
|
4824
|
+
var contextGatherVariant = z18.object({
|
|
4825
|
+
action: z18.literal("gather"),
|
|
4826
|
+
entryId: z18.string().max(200).optional(),
|
|
4827
|
+
mapEntryId: z18.string().max(200).optional(),
|
|
4828
|
+
task: z18.string().max(2e3).optional(),
|
|
4829
|
+
mode: z18.enum(["search", "graph"]).optional().default("search"),
|
|
4830
|
+
maxHops: z18.number().min(1).max(4).optional().default(2),
|
|
4831
|
+
maxResults: z18.number().min(1).max(25).optional().default(10),
|
|
4832
|
+
strategy: z18.enum(["hybrid", "keyword"]).optional().default("keyword")
|
|
4562
4833
|
});
|
|
4563
|
-
var contextBuildVariant =
|
|
4564
|
-
action:
|
|
4565
|
-
entryId:
|
|
4566
|
-
maxHops:
|
|
4834
|
+
var contextBuildVariant = z18.object({
|
|
4835
|
+
action: z18.literal("build"),
|
|
4836
|
+
entryId: z18.string().max(200),
|
|
4837
|
+
maxHops: z18.number().min(1).max(4).optional().default(2)
|
|
4567
4838
|
});
|
|
4568
|
-
var contextNeighborhoodVariant =
|
|
4569
|
-
action:
|
|
4570
|
-
entryId:
|
|
4839
|
+
var contextNeighborhoodVariant = z18.object({
|
|
4840
|
+
action: z18.literal("neighborhood"),
|
|
4841
|
+
entryId: z18.string().max(200)
|
|
4571
4842
|
});
|
|
4572
|
-
var contextChangesVariant =
|
|
4573
|
-
action:
|
|
4574
|
-
since:
|
|
4843
|
+
var contextChangesVariant = z18.object({
|
|
4844
|
+
action: z18.literal("changes"),
|
|
4845
|
+
since: z18.string().max(200)
|
|
4575
4846
|
});
|
|
4576
|
-
var contextChainVariant =
|
|
4577
|
-
action:
|
|
4578
|
-
entryId:
|
|
4579
|
-
direction:
|
|
4580
|
-
maxHops:
|
|
4581
|
-
relationType:
|
|
4847
|
+
var contextChainVariant = z18.object({
|
|
4848
|
+
action: z18.literal("chain"),
|
|
4849
|
+
entryId: z18.string().max(200),
|
|
4850
|
+
direction: z18.enum(["outgoing", "incoming"]).optional().default("outgoing"),
|
|
4851
|
+
maxHops: z18.number().min(1).max(4).optional().default(2),
|
|
4852
|
+
relationType: z18.string().max(200).optional()
|
|
4582
4853
|
});
|
|
4583
|
-
var contextCrossCutVariant =
|
|
4584
|
-
action:
|
|
4585
|
-
relationType:
|
|
4854
|
+
var contextCrossCutVariant = z18.object({
|
|
4855
|
+
action: z18.literal("cross-cut"),
|
|
4856
|
+
relationType: z18.string().max(200)
|
|
4586
4857
|
});
|
|
4587
|
-
var contextIncrementalVariant =
|
|
4588
|
-
action:
|
|
4589
|
-
skill:
|
|
4858
|
+
var contextIncrementalVariant = z18.object({
|
|
4859
|
+
action: z18.literal("incremental"),
|
|
4860
|
+
skill: z18.string().max(200)
|
|
4590
4861
|
});
|
|
4591
|
-
var contextBriefVariant =
|
|
4592
|
-
action:
|
|
4593
|
-
briefType:
|
|
4594
|
-
since:
|
|
4862
|
+
var contextBriefVariant = z18.object({
|
|
4863
|
+
action: z18.literal("brief"),
|
|
4864
|
+
briefType: z18.enum(["steering", "confidence", "delta"]),
|
|
4865
|
+
since: z18.string().max(200).optional()
|
|
4595
4866
|
});
|
|
4596
|
-
var contextLastVerifiedBriefVariant =
|
|
4597
|
-
action:
|
|
4598
|
-
templateId:
|
|
4599
|
-
scopeKey:
|
|
4867
|
+
var contextLastVerifiedBriefVariant = z18.object({
|
|
4868
|
+
action: z18.literal("last-verified-brief"),
|
|
4869
|
+
templateId: z18.string().max(200),
|
|
4870
|
+
scopeKey: z18.string().max(200)
|
|
4600
4871
|
});
|
|
4601
|
-
var contextActionUnion =
|
|
4872
|
+
var contextActionUnion = z18.discriminatedUnion("action", [
|
|
4602
4873
|
...lookupVariants,
|
|
4603
4874
|
contextGatherVariant,
|
|
4604
4875
|
contextBuildVariant,
|
|
@@ -5596,7 +5867,7 @@ function formatTimeAgo(ms) {
|
|
|
5596
5867
|
}
|
|
5597
5868
|
|
|
5598
5869
|
// src/tools/collections.ts
|
|
5599
|
-
import { z as
|
|
5870
|
+
import { z as z20 } from "zod/v3";
|
|
5600
5871
|
|
|
5601
5872
|
// src/lib/bodyTemplate.ts
|
|
5602
5873
|
function readBodyTemplateGuidance(bodyTemplate) {
|
|
@@ -5606,17 +5877,17 @@ ${entry.guidance}`).join("\n\n");
|
|
|
5606
5877
|
}
|
|
5607
5878
|
|
|
5608
5879
|
// src/tools/labels.ts
|
|
5609
|
-
import { z as
|
|
5610
|
-
var labelsSchema =
|
|
5611
|
-
action:
|
|
5612
|
-
slug:
|
|
5613
|
-
name:
|
|
5614
|
-
color:
|
|
5615
|
-
description:
|
|
5616
|
-
parentSlug:
|
|
5617
|
-
isGroup:
|
|
5618
|
-
order:
|
|
5619
|
-
entryId:
|
|
5880
|
+
import { z as z19 } from "zod/v3";
|
|
5881
|
+
var labelsSchema = z19.object({
|
|
5882
|
+
action: z19.enum(["list", "create", "update", "delete", "apply", "remove"]).describe("Action: list all labels, create/update/delete a label, or apply/remove a label on an entry"),
|
|
5883
|
+
slug: z19.string().max(200).optional().describe("Label slug (required for create/update/delete/apply/remove)"),
|
|
5884
|
+
name: z19.string().max(ENTRY_NAME_MAX_CHARS).optional().describe("Display name (required for create)"),
|
|
5885
|
+
color: z19.string().max(50).optional().describe("Hex color, e.g. '#ef4444'"),
|
|
5886
|
+
description: z19.string().max(LABEL_DESCRIPTION_MAX_CHARS).optional().describe("What this label means"),
|
|
5887
|
+
parentSlug: z19.string().max(200).optional().describe("Parent group slug for label hierarchy"),
|
|
5888
|
+
isGroup: z19.boolean().optional().describe("True if this is a group container, not a taggable label"),
|
|
5889
|
+
order: z19.number().optional().describe("Sort order within its group"),
|
|
5890
|
+
entryId: z19.string().max(200).optional().describe("Entry ID for apply/remove actions")
|
|
5620
5891
|
});
|
|
5621
5892
|
async function handleLabelsList() {
|
|
5622
5893
|
const labels = await kernelQuery("chain.listLabels");
|
|
@@ -5721,108 +5992,108 @@ var COLLECTIONS_ACTIONS = [
|
|
|
5721
5992
|
"label-remove"
|
|
5722
5993
|
];
|
|
5723
5994
|
var STATUS_CATEGORIES2 = ["draft", "current", "past", "discarded"];
|
|
5724
|
-
var statusListEntrySchema =
|
|
5725
|
-
var qualityCriterionSchema =
|
|
5726
|
-
field:
|
|
5995
|
+
var statusListEntrySchema = z20.object({ label: z20.string().max(200), category: z20.enum(STATUS_CATEGORIES2), archiveDefault: z20.boolean().optional(), resolveDefault: z20.boolean().optional() });
|
|
5996
|
+
var qualityCriterionSchema = z20.object({
|
|
5997
|
+
field: z20.string().max(200).describe("Entry data field key this criterion applies to, e.g. 'description', 'owner'"),
|
|
5727
5998
|
// WP-480 S1: `max_length` — must mirror the Convex rule union, or the tool rejects a
|
|
5728
5999
|
// valid criterion before the request ever reaches the server.
|
|
5729
|
-
rule:
|
|
5730
|
-
value:
|
|
6000
|
+
rule: z20.enum(["required", "min_length", "max_length", "pattern"]).describe("'required': field must be non-empty (blocks accept). 'min_length': minimum string length (warns). 'max_length': maximum string length (warns). 'pattern': regex match (warns)."),
|
|
6001
|
+
value: z20.string().max(500).optional().describe("For min_length/max_length: the length bound as a string integer. For pattern: the regex string. Unused for 'required'.")
|
|
5731
6002
|
});
|
|
5732
|
-
var fieldSchema =
|
|
5733
|
-
key:
|
|
5734
|
-
label:
|
|
5735
|
-
type:
|
|
5736
|
-
required:
|
|
5737
|
-
options:
|
|
5738
|
-
searchable:
|
|
5739
|
-
displayHint:
|
|
5740
|
-
zone:
|
|
5741
|
-
colorMap:
|
|
5742
|
-
accentSource:
|
|
5743
|
-
iconMap:
|
|
5744
|
-
helpText:
|
|
5745
|
-
optionDescriptions:
|
|
5746
|
-
semanticRole:
|
|
5747
|
-
maxLength:
|
|
5748
|
-
minLength:
|
|
6003
|
+
var fieldSchema = z20.object({
|
|
6004
|
+
key: z20.string().max(200).describe("Field key, e.g. 'description', 'severity', 'status'"),
|
|
6005
|
+
label: z20.string().max(200).describe("Display label, e.g. 'Description', 'Severity'"),
|
|
6006
|
+
type: z20.string().max(50).describe("Field type: 'string', 'select', 'array', 'number', 'boolean'"),
|
|
6007
|
+
required: z20.boolean().optional().describe("Whether this field is required"),
|
|
6008
|
+
options: z20.array(z20.string().max(200)).max(200).optional().describe("Options for 'select' type fields"),
|
|
6009
|
+
searchable: z20.boolean().optional().describe("Whether this field is included in full-text search"),
|
|
6010
|
+
displayHint: z20.enum(["hero", "badge", "meta", "section", "hidden", "inline-meta"]).optional().describe("V2 rendering hint: how the field should be displayed in Cortex"),
|
|
6011
|
+
zone: z20.enum(["header", "body", "meta"]).optional().describe("V2 layout zone: where the field appears in the entry view"),
|
|
6012
|
+
colorMap: z20.record(z20.string().max(50)).optional().describe("V2 value-to-semantic-color mapping, e.g. { critical: 'danger', low: 'success' }"),
|
|
6013
|
+
accentSource: z20.boolean().optional().describe("When true, this field's colorMap value drives the card-level accent styling"),
|
|
6014
|
+
iconMap: z20.record(z20.string(), z20.string().max(50)).optional().describe("Maps field values to icons (emoji/symbol), prepended to badge text"),
|
|
6015
|
+
helpText: z20.string().max(2e3).optional().describe("Help text shown in admin field editors"),
|
|
6016
|
+
optionDescriptions: z20.record(z20.string().max(500)).optional().describe("Per-option guidance for select fields"),
|
|
6017
|
+
semanticRole: z20.enum(["problem", "appetite", "elements", "architecture", "done_when", "risks", "exclusions"]).optional().describe("Semantic role for schema-driven consumers \u2014 enables field-key-independent validation and rendering"),
|
|
6018
|
+
maxLength: z20.number().optional().describe("Maximum character length for field values. Three-tier resolution: explicit > displayHint > type fallback."),
|
|
6019
|
+
minLength: z20.number().optional().describe("Minimum character length for field values. Only explicit \u2014 no defaults.")
|
|
5749
6020
|
});
|
|
5750
|
-
var collectionsSchema =
|
|
5751
|
-
action:
|
|
6021
|
+
var collectionsSchema = z20.object({
|
|
6022
|
+
action: z20.enum(COLLECTIONS_ACTIONS).describe(
|
|
5752
6023
|
"'list': browse all collections. 'update': update an existing collection. 'describe': full documentation for one collection \u2014 fields, option guides, usage guidance, examples. 'audit': health report for all collections \u2014 missing classification, displayHint coverage, and field schema gaps. 'export': full system_collection_definitions export with classification metadata (thinkingLayer, classificationPriority, classificationCheck, classificationSignals, governanceRole, governanceFunction, timelineRole, canBeElementOf, descriptionFieldKey). Admin only. 'label-list'/'label-create'/'label-update'/'label-delete'/'label-apply'/'label-remove': manage workspace labels (absorbs the `labels` tool). Creating a new collection is not offered here \u2014 ask a platform admin to provision it, or enable the module ontology pack that owns the drawer."
|
|
5753
6024
|
),
|
|
5754
|
-
slug:
|
|
5755
|
-
name:
|
|
5756
|
-
description:
|
|
5757
|
-
purpose:
|
|
5758
|
-
icon:
|
|
5759
|
-
navGroup:
|
|
5760
|
-
fields:
|
|
5761
|
-
axis:
|
|
5762
|
-
stageLabelMap:
|
|
5763
|
-
defaultCanonicalKey:
|
|
5764
|
-
defaultWorkflowStatus:
|
|
5765
|
-
validWorkflowStatuses:
|
|
6025
|
+
slug: z20.string().max(200).optional().describe("URL-safe identifier for create/update, e.g. 'glossary', 'tech-debt'. For label-*: label slug."),
|
|
6026
|
+
name: z20.string().max(ENTRY_NAME_MAX_CHARS).optional().describe("For label-*: the label's name. For update: refused (the catalog's)."),
|
|
6027
|
+
description: z20.string().max(2e4).optional().describe("For label-*: what the label means (max 2,000 chars). For update: refused (the catalog's)."),
|
|
6028
|
+
purpose: z20.string().max(2e3).optional().describe("Why this collection exists \u2014 strategic reason"),
|
|
6029
|
+
icon: z20.string().max(50).optional().describe("For update: always refused \u2014 a collection's icon comes from the platform catalog."),
|
|
6030
|
+
navGroup: z20.enum(["daily", "strategic", "governance", "reference", "collections"]).optional().describe("Sidebar placement: 'daily', 'strategic', 'governance', 'reference', 'collections'"),
|
|
6031
|
+
fields: z20.array(fieldSchema).max(200).optional().describe("Field definitions for create, or replacement schema for update (replaces all fields)"),
|
|
6032
|
+
axis: z20.enum(["work", "none", "pending"]).optional().describe("REQUIRED for create: 'work' (needs stageLabelMap + validWorkflowStatuses), 'none', or 'pending'. For update: always refused \u2014 a collection's axis comes from the platform catalog."),
|
|
6033
|
+
stageLabelMap: z20.record(z20.string(), z20.enum(["open", "in_progress", "done", "stopped", "tag"])).optional().describe("Required when axis is 'work': maps each valid workflowStatus to a canonical stage."),
|
|
6034
|
+
defaultCanonicalKey: z20.string().max(200).optional().describe("The canonical_key entries in this collection default to (e.g. 'decision', 'insight'). Consumers read from collection doc; code map is fallback."),
|
|
6035
|
+
defaultWorkflowStatus: z20.string().max(200).optional().describe("Default workflowStatus for new entries. For update: always refused \u2014 the status words come from the platform catalog."),
|
|
6036
|
+
validWorkflowStatuses: z20.array(z20.string().max(200)).max(50).optional().describe("The allowed workflowStatus values for entries in this collection. For update: always refused \u2014 the status words come from the platform catalog."),
|
|
5766
6037
|
// ENT-65, FEAT-200
|
|
5767
|
-
classificationCheck:
|
|
5768
|
-
classificationPriority:
|
|
5769
|
-
qualityCriteria:
|
|
5770
|
-
statusList:
|
|
6038
|
+
classificationCheck: z20.string().max(500).optional().describe("LLM decision-tree check for this collection (3\u2013500 chars). Guides the classifier in routing entries here."),
|
|
6039
|
+
classificationPriority: z20.number().optional().describe("Classifier priority (1\u20139, lower = higher priority). Used with classificationCheck to order the decision tree."),
|
|
6040
|
+
qualityCriteria: z20.array(qualityCriterionSchema).max(50).optional().describe("Per-collection accept gate rules. 'required' rule hard-blocks accepts on empty fields; 'min_length'/'pattern' rules warn. Pass an empty array to clear all criteria."),
|
|
6041
|
+
statusList: z20.array(statusListEntrySchema).max(50).optional().describe("Ordered status vocabulary: {label, category, archiveDefault?}[]. For update: always refused \u2014 the status words come from the platform catalog."),
|
|
5771
6042
|
// For label-*
|
|
5772
|
-
color:
|
|
5773
|
-
parentSlug:
|
|
5774
|
-
isGroup:
|
|
5775
|
-
order:
|
|
5776
|
-
entryId:
|
|
6043
|
+
color: z20.string().max(50).optional().describe("For label-create/label-update: hex color, e.g. '#ef4444'."),
|
|
6044
|
+
parentSlug: z20.string().max(200).optional().describe("For label-create: parent group slug for label hierarchy."),
|
|
6045
|
+
isGroup: z20.boolean().optional().describe("For label-create/label-update: true if this is a group container, not a taggable label."),
|
|
6046
|
+
order: z20.number().optional().describe("For label-create/label-update: sort order within its group."),
|
|
6047
|
+
entryId: z20.string().max(200).optional().describe("For label-apply/label-remove: entry ID.")
|
|
5777
6048
|
});
|
|
5778
|
-
var collectionsListVariant =
|
|
5779
|
-
var collectionsDescribeVariant =
|
|
5780
|
-
var collectionsUpdateVariant =
|
|
5781
|
-
action:
|
|
5782
|
-
slug:
|
|
5783
|
-
name:
|
|
5784
|
-
description:
|
|
5785
|
-
purpose:
|
|
5786
|
-
icon:
|
|
5787
|
-
navGroup:
|
|
5788
|
-
fields:
|
|
5789
|
-
axis:
|
|
5790
|
-
stageLabelMap:
|
|
6049
|
+
var collectionsListVariant = z20.object({ action: z20.literal("list") });
|
|
6050
|
+
var collectionsDescribeVariant = z20.object({ action: z20.literal("describe"), slug: z20.string().max(200) });
|
|
6051
|
+
var collectionsUpdateVariant = z20.object({
|
|
6052
|
+
action: z20.literal("update"),
|
|
6053
|
+
slug: z20.string().max(200),
|
|
6054
|
+
name: z20.string().max(ENTRY_NAME_MAX_CHARS).optional(),
|
|
6055
|
+
description: z20.string().max(2e4).optional(),
|
|
6056
|
+
purpose: z20.string().max(2e3).optional(),
|
|
6057
|
+
icon: z20.string().max(50).optional(),
|
|
6058
|
+
navGroup: z20.enum(["daily", "strategic", "governance", "reference", "collections"]).optional(),
|
|
6059
|
+
fields: z20.array(fieldSchema).optional(),
|
|
6060
|
+
axis: z20.enum(["work", "none", "pending"]).optional(),
|
|
6061
|
+
stageLabelMap: z20.record(z20.string(), z20.enum(["open", "in_progress", "done", "stopped", "tag"])).optional(),
|
|
5791
6062
|
// WP-640 SWEEP (P1): axis/stageLabelMap repair legacy custom collections — see collections.ts's updateCollection.
|
|
5792
|
-
defaultCanonicalKey:
|
|
5793
|
-
defaultWorkflowStatus:
|
|
5794
|
-
validWorkflowStatuses:
|
|
5795
|
-
classificationCheck:
|
|
5796
|
-
classificationPriority:
|
|
5797
|
-
qualityCriteria:
|
|
5798
|
-
statusList:
|
|
6063
|
+
defaultCanonicalKey: z20.string().max(200).optional(),
|
|
6064
|
+
defaultWorkflowStatus: z20.string().max(200).optional(),
|
|
6065
|
+
validWorkflowStatuses: z20.array(z20.string().max(200)).optional(),
|
|
6066
|
+
classificationCheck: z20.string().max(500).optional(),
|
|
6067
|
+
classificationPriority: z20.number().optional(),
|
|
6068
|
+
qualityCriteria: z20.array(qualityCriterionSchema).optional(),
|
|
6069
|
+
statusList: z20.array(statusListEntrySchema).optional()
|
|
5799
6070
|
});
|
|
5800
|
-
var collectionsAuditVariant =
|
|
5801
|
-
var collectionsExportVariant =
|
|
5802
|
-
var collectionsLabelListVariant =
|
|
5803
|
-
var collectionsLabelCreateVariant =
|
|
5804
|
-
action:
|
|
5805
|
-
slug:
|
|
5806
|
-
name:
|
|
5807
|
-
color:
|
|
5808
|
-
description:
|
|
5809
|
-
parentSlug:
|
|
5810
|
-
isGroup:
|
|
5811
|
-
order:
|
|
6071
|
+
var collectionsAuditVariant = z20.object({ action: z20.literal("audit") });
|
|
6072
|
+
var collectionsExportVariant = z20.object({ action: z20.literal("export") });
|
|
6073
|
+
var collectionsLabelListVariant = z20.object({ action: z20.literal("label-list") });
|
|
6074
|
+
var collectionsLabelCreateVariant = z20.object({
|
|
6075
|
+
action: z20.literal("label-create"),
|
|
6076
|
+
slug: z20.string().max(200),
|
|
6077
|
+
name: z20.string().max(ENTRY_NAME_MAX_CHARS),
|
|
6078
|
+
color: z20.string().max(50).optional(),
|
|
6079
|
+
description: z20.string().max(LABEL_DESCRIPTION_MAX_CHARS).optional(),
|
|
6080
|
+
parentSlug: z20.string().max(200).optional(),
|
|
6081
|
+
isGroup: z20.boolean().optional(),
|
|
6082
|
+
order: z20.number().optional()
|
|
5812
6083
|
});
|
|
5813
|
-
var collectionsLabelUpdateVariant =
|
|
5814
|
-
action:
|
|
5815
|
-
slug:
|
|
5816
|
-
name:
|
|
5817
|
-
color:
|
|
5818
|
-
description:
|
|
5819
|
-
isGroup:
|
|
5820
|
-
order:
|
|
6084
|
+
var collectionsLabelUpdateVariant = z20.object({
|
|
6085
|
+
action: z20.literal("label-update"),
|
|
6086
|
+
slug: z20.string().max(200),
|
|
6087
|
+
name: z20.string().max(ENTRY_NAME_MAX_CHARS).optional(),
|
|
6088
|
+
color: z20.string().max(50).optional(),
|
|
6089
|
+
description: z20.string().max(LABEL_DESCRIPTION_MAX_CHARS).optional(),
|
|
6090
|
+
isGroup: z20.boolean().optional(),
|
|
6091
|
+
order: z20.number().optional()
|
|
5821
6092
|
});
|
|
5822
|
-
var collectionsLabelDeleteVariant =
|
|
5823
|
-
var collectionsLabelApplyVariant =
|
|
5824
|
-
var collectionsLabelRemoveVariant =
|
|
5825
|
-
var collectionsActionUnion =
|
|
6093
|
+
var collectionsLabelDeleteVariant = z20.object({ action: z20.literal("label-delete"), slug: z20.string().max(200) });
|
|
6094
|
+
var collectionsLabelApplyVariant = z20.object({ action: z20.literal("label-apply"), slug: z20.string().max(200), entryId: z20.string().max(200) });
|
|
6095
|
+
var collectionsLabelRemoveVariant = z20.object({ action: z20.literal("label-remove"), slug: z20.string().max(200), entryId: z20.string().max(200) });
|
|
6096
|
+
var collectionsActionUnion = z20.discriminatedUnion("action", [
|
|
5826
6097
|
collectionsListVariant,
|
|
5827
6098
|
collectionsDescribeVariant,
|
|
5828
6099
|
collectionsUpdateVariant,
|
|
@@ -6130,7 +6401,7 @@ async function handleExport() {
|
|
|
6130
6401
|
}
|
|
6131
6402
|
|
|
6132
6403
|
// src/tools/orient.ts
|
|
6133
|
-
import { z as
|
|
6404
|
+
import { z as z21 } from "zod/v3";
|
|
6134
6405
|
|
|
6135
6406
|
// src/tools/planned-work.ts
|
|
6136
6407
|
var MORE_DRAFTS_LINE = "_More drafts exist than shown. `context action=list status=draft` lists more, but that list is capped as well; page with limit/cursor once context list supports it._";
|
|
@@ -7033,25 +7304,25 @@ async function markOrientedWithSnapshotFallback(agentSessionId, coherenceSnapsho
|
|
|
7033
7304
|
}
|
|
7034
7305
|
}
|
|
7035
7306
|
var ORIENT_ACTIONS = ["task"];
|
|
7036
|
-
var orientSchema =
|
|
7037
|
-
action:
|
|
7307
|
+
var orientSchema = z21.object({
|
|
7308
|
+
action: z21.enum(ORIENT_ACTIONS).optional().default("task").describe(
|
|
7038
7309
|
"'task': task-grounded context loader, the only action."
|
|
7039
7310
|
),
|
|
7040
|
-
mode:
|
|
7041
|
-
tier:
|
|
7311
|
+
mode: z21.enum(["full", "brief"]).optional().default("full").describe("For 'task': full = full context (default). brief = compact summary for mid-session re-orientation. Prefer using the `tier` param for depth control."),
|
|
7312
|
+
tier: z21.enum(["summary", "standard", "full"]).optional().describe(
|
|
7042
7313
|
"For 'task': 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."
|
|
7043
7314
|
),
|
|
7044
|
-
task:
|
|
7315
|
+
task: z21.string().max(2e3).optional().describe(
|
|
7045
7316
|
"For 'task': natural-language task description for task-scoped context. When provided, orient returns scored, relevant entries for the task."
|
|
7046
7317
|
),
|
|
7047
7318
|
// D1d (WP-754/TASK-204): matches the server's StartupResolutionSignals shape; domain resolution (original purpose) is deleted, sole survivor is `context.served` telemetry.
|
|
7048
|
-
startupSignals:
|
|
7049
|
-
changedPaths:
|
|
7050
|
-
reviewedArtifactRefs:
|
|
7051
|
-
branchName:
|
|
7052
|
-
worktreeName:
|
|
7319
|
+
startupSignals: z21.object({
|
|
7320
|
+
changedPaths: z21.array(z21.string()).max(25).optional().describe("Paths changed in the current working tree, if known (e.g. from a prior git status/diff tool call)."),
|
|
7321
|
+
reviewedArtifactRefs: z21.array(z21.string()).max(25).optional().describe("Chain entry IDs the caller has already reviewed this session, if tracked."),
|
|
7322
|
+
branchName: z21.string().max(120).optional().describe("Current git branch name, if known."),
|
|
7323
|
+
worktreeName: z21.string().max(120).optional().describe("Current worktree/directory name, if known.")
|
|
7053
7324
|
}).optional().describe("For 'task': best-effort startup signals \u2014 changedPaths/reviewedArtifactRefs/branchName/worktreeName. All optional; omit fields you don't know."),
|
|
7054
|
-
invocationPath:
|
|
7325
|
+
invocationPath: z21.enum(["session-start", "session-close", "manual-orient", "handshake", "unknown"]).optional().describe("For 'task': how this orient was invoked. Defaults to 'manual-orient' (the direct `orient task=...` call shape) when omitted.")
|
|
7055
7326
|
});
|
|
7056
7327
|
function taskGroundingWarningLines(task, hasTaskGrounding = false) {
|
|
7057
7328
|
if (hasTaskGrounding) return [];
|
|
@@ -7715,7 +7986,7 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
|
|
|
7715
7986
|
}
|
|
7716
7987
|
|
|
7717
7988
|
// src/tools/workflows.ts
|
|
7718
|
-
import { z as
|
|
7989
|
+
import { z as z22 } from "zod/v3";
|
|
7719
7990
|
|
|
7720
7991
|
// src/workflows/descriptor.ts
|
|
7721
7992
|
function cloneWorkflowQuestion(question) {
|
|
@@ -8560,73 +8831,73 @@ function workflowRunOutputToText(output) {
|
|
|
8560
8831
|
|
|
8561
8832
|
// src/tools/workflows.ts
|
|
8562
8833
|
var WORKFLOWS_ACTIONS = ["list", "start", "checkpoint", "get-run"];
|
|
8563
|
-
var jsonValueSchema =
|
|
8564
|
-
() =>
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8834
|
+
var jsonValueSchema = z22.lazy(
|
|
8835
|
+
() => z22.union([
|
|
8836
|
+
z22.string(),
|
|
8837
|
+
z22.number(),
|
|
8838
|
+
z22.boolean(),
|
|
8839
|
+
z22.null(),
|
|
8840
|
+
z22.array(jsonValueSchema),
|
|
8841
|
+
z22.record(jsonValueSchema)
|
|
8571
8842
|
])
|
|
8572
8843
|
);
|
|
8573
|
-
var workflowRunOutputInputSchema =
|
|
8574
|
-
|
|
8575
|
-
format:
|
|
8576
|
-
value:
|
|
8844
|
+
var workflowRunOutputInputSchema = z22.union([
|
|
8845
|
+
z22.object({
|
|
8846
|
+
format: z22.literal("freetext"),
|
|
8847
|
+
value: z22.string()
|
|
8577
8848
|
}),
|
|
8578
|
-
|
|
8579
|
-
format:
|
|
8580
|
-
value:
|
|
8849
|
+
z22.object({
|
|
8850
|
+
format: z22.literal("list"),
|
|
8851
|
+
value: z22.array(z22.string())
|
|
8581
8852
|
}),
|
|
8582
|
-
|
|
8583
|
-
format:
|
|
8584
|
-
value:
|
|
8853
|
+
z22.object({
|
|
8854
|
+
format: z22.literal("choice"),
|
|
8855
|
+
value: z22.union([z22.string(), z22.array(z22.string())])
|
|
8585
8856
|
}),
|
|
8586
|
-
|
|
8587
|
-
format:
|
|
8857
|
+
z22.object({
|
|
8858
|
+
format: z22.literal("structured"),
|
|
8588
8859
|
value: jsonValueSchema
|
|
8589
8860
|
})
|
|
8590
8861
|
]);
|
|
8591
|
-
var workflowsSchema =
|
|
8592
|
-
action:
|
|
8862
|
+
var workflowsSchema = z22.object({
|
|
8863
|
+
action: z22.enum(WORKFLOWS_ACTIONS).describe(
|
|
8593
8864
|
"'list': browse available workflows. 'start': start or resume a workflow \u2014 returns first (or current) round and next-step checkpoint call. 'checkpoint': record round output or final summary. 'get-run': inspect a persisted workflow run."
|
|
8594
8865
|
),
|
|
8595
|
-
workflowId:
|
|
8596
|
-
runId:
|
|
8597
|
-
roundId:
|
|
8598
|
-
output:
|
|
8599
|
-
isFinal:
|
|
8600
|
-
restart:
|
|
8601
|
-
summaryName:
|
|
8602
|
-
summaryDescription:
|
|
8603
|
-
summaryEntryId:
|
|
8866
|
+
workflowId: z22.string().max(200).optional().describe("Workflow ID for start, checkpoint, or get-run, e.g. 'retro', 'implementation-review'"),
|
|
8867
|
+
runId: z22.string().max(200).optional().describe("Workflow run ID: for get-run, which run to load; for checkpoint, target this run (avoids session drift \u2014 pass runId from get-run)."),
|
|
8868
|
+
roundId: z22.string().max(200).optional().describe("Round ID for checkpoint, e.g. 'what-went-well'"),
|
|
8869
|
+
output: z22.union([z22.string(), workflowRunOutputInputSchema]).optional().describe("The round's output \u2014 either legacy synthesized text or a typed workflow run payload."),
|
|
8870
|
+
isFinal: z22.boolean().optional().describe("If true, finalize an existing durable workflow run from its terminal round and create the summary chain entry."),
|
|
8871
|
+
restart: z22.boolean().optional().describe("If true, start a new durable run from the workflow's first round in the current session."),
|
|
8872
|
+
summaryName: z22.string().max(ENTRY_NAME_MAX_CHARS).optional().describe("Optional name for final chain entry. If omitted, the workflow summary template is used."),
|
|
8873
|
+
summaryDescription: z22.string().max(ENTRY_BODY_MAX_CHARS).optional().describe("Optional override for the final chain entry description. Defaults to the final round output text."),
|
|
8874
|
+
summaryEntryId: z22.string().max(200).optional().describe("Link an existing entry as the run's summary instead of creating one. Used by facilitated workflows (e.g. shape) where the primary record is created by the specialized tool."),
|
|
8604
8875
|
// WP-513: team+role to create the finalize summary AS OWNER of (rung 2 only).
|
|
8605
|
-
ownerTeamEntryId:
|
|
8606
|
-
ownerRoleEntryId:
|
|
8876
|
+
ownerTeamEntryId: z22.string().max(200).optional().describe("For 'checkpoint' (isFinal): owning team (rung-2)."),
|
|
8877
|
+
ownerRoleEntryId: z22.string().max(200).optional().describe("For 'checkpoint' (isFinal): owning role (rung-2).")
|
|
8607
8878
|
});
|
|
8608
|
-
var workflowsListVariant =
|
|
8609
|
-
var workflowsGetRunVariant =
|
|
8610
|
-
action:
|
|
8611
|
-
runId:
|
|
8612
|
-
workflowId:
|
|
8879
|
+
var workflowsListVariant = z22.object({ action: z22.literal("list") });
|
|
8880
|
+
var workflowsGetRunVariant = z22.object({
|
|
8881
|
+
action: z22.literal("get-run"),
|
|
8882
|
+
runId: z22.string().max(200).optional(),
|
|
8883
|
+
workflowId: z22.string().max(200).optional()
|
|
8613
8884
|
});
|
|
8614
|
-
var workflowsStartVariant =
|
|
8615
|
-
var workflowsCheckpointVariant =
|
|
8616
|
-
action:
|
|
8617
|
-
workflowId:
|
|
8618
|
-
roundId:
|
|
8619
|
-
output:
|
|
8620
|
-
isFinal:
|
|
8621
|
-
restart:
|
|
8622
|
-
summaryName:
|
|
8623
|
-
summaryDescription:
|
|
8624
|
-
summaryEntryId:
|
|
8625
|
-
runId:
|
|
8626
|
-
ownerTeamEntryId:
|
|
8627
|
-
ownerRoleEntryId:
|
|
8885
|
+
var workflowsStartVariant = z22.object({ action: z22.literal("start"), workflowId: z22.string().max(200) });
|
|
8886
|
+
var workflowsCheckpointVariant = z22.object({
|
|
8887
|
+
action: z22.literal("checkpoint"),
|
|
8888
|
+
workflowId: z22.string().max(200),
|
|
8889
|
+
roundId: z22.string().max(200),
|
|
8890
|
+
output: z22.union([z22.string(), workflowRunOutputInputSchema]),
|
|
8891
|
+
isFinal: z22.boolean().optional(),
|
|
8892
|
+
restart: z22.boolean().optional(),
|
|
8893
|
+
summaryName: z22.string().max(ENTRY_NAME_MAX_CHARS).optional(),
|
|
8894
|
+
summaryDescription: z22.string().max(ENTRY_BODY_MAX_CHARS).optional(),
|
|
8895
|
+
summaryEntryId: z22.string().max(200).optional(),
|
|
8896
|
+
runId: z22.string().max(200).optional(),
|
|
8897
|
+
ownerTeamEntryId: z22.string().max(200).optional(),
|
|
8898
|
+
ownerRoleEntryId: z22.string().max(200).optional()
|
|
8628
8899
|
});
|
|
8629
|
-
var workflowsActionUnion =
|
|
8900
|
+
var workflowsActionUnion = z22.discriminatedUnion("action", [
|
|
8630
8901
|
workflowsListVariant,
|
|
8631
8902
|
workflowsGetRunVariant,
|
|
8632
8903
|
workflowsStartVariant,
|
|
@@ -9355,7 +9626,7 @@ function parseListOutput(output) {
|
|
|
9355
9626
|
}
|
|
9356
9627
|
|
|
9357
9628
|
// src/tools/quality.ts
|
|
9358
|
-
import { z as
|
|
9629
|
+
import { z as z23 } from "zod/v3";
|
|
9359
9630
|
|
|
9360
9631
|
// src/lib/spineVerdictRead.ts
|
|
9361
9632
|
function isRecord(value) {
|
|
@@ -9520,36 +9791,36 @@ async function handleSpineCheck(story, refresh = false) {
|
|
|
9520
9791
|
|
|
9521
9792
|
// src/tools/quality.ts
|
|
9522
9793
|
var QUALITY_ACTIONS = ["check", "re-evaluate", "verify-chain", "spine-check"];
|
|
9523
|
-
var qualitySchema =
|
|
9524
|
-
action:
|
|
9794
|
+
var qualitySchema = z23.object({
|
|
9795
|
+
action: z23.enum(QUALITY_ACTIONS).describe(
|
|
9525
9796
|
"'check': read the entry's server quality verdict (tier + criteria). 're-evaluate': trigger fresh evaluation. 'verify-chain': verify entries against the codebase (codeMapping drift, cross-references) \u2014 absorbs `verify`. 'spine-check': structural completeness of the purpose+vision+strategy spine \u2014 story:true also runs the on-demand one-story judgment."
|
|
9526
9797
|
),
|
|
9527
|
-
entryId:
|
|
9528
|
-
context:
|
|
9529
|
-
collection:
|
|
9530
|
-
mode:
|
|
9531
|
-
story:
|
|
9532
|
-
refresh:
|
|
9798
|
+
entryId: z23.string().max(200).optional().describe("For 'check'/'re-evaluate': entry ID, e.g. 'TEN-graph-db', '<PREFIX>-<n>'."),
|
|
9799
|
+
context: z23.enum(["capture", "commit", "review"]).default("review").optional().describe("For re-evaluate: evaluation context"),
|
|
9800
|
+
collection: z23.string().max(200).optional().describe("For 'verify-chain': collection slug to verify (default: glossary)."),
|
|
9801
|
+
mode: z23.enum(["report", "fix"]).optional().describe("For 'verify-chain': 'report' = read-only trust report (default). 'fix' = also update drifted codeMapping statuses."),
|
|
9802
|
+
story: z23.boolean().optional().describe("For 'spine-check': also run the on-demand one-story LLM judgment (never scheduled; result labelled [unvalidated])."),
|
|
9803
|
+
refresh: z23.boolean().optional().describe(
|
|
9533
9804
|
"For 'spine-check': force a new run even if a fresh verdict already exists. Default false \u2014 a plain call NEVER re-triggers work just to read the last result; it auto-schedules only when no run is already in flight AND the stored verdict is absent/stale/missing the requested story pass."
|
|
9534
9805
|
)
|
|
9535
9806
|
});
|
|
9536
|
-
var qualityCheckVariant =
|
|
9537
|
-
var qualityReEvaluateVariant =
|
|
9538
|
-
action:
|
|
9539
|
-
entryId:
|
|
9540
|
-
context:
|
|
9807
|
+
var qualityCheckVariant = z23.object({ action: z23.literal("check"), entryId: z23.string().max(200) });
|
|
9808
|
+
var qualityReEvaluateVariant = z23.object({
|
|
9809
|
+
action: z23.literal("re-evaluate"),
|
|
9810
|
+
entryId: z23.string().max(200),
|
|
9811
|
+
context: z23.enum(["capture", "commit", "review"]).optional().default("review")
|
|
9541
9812
|
});
|
|
9542
|
-
var qualityVerifyChainVariant =
|
|
9543
|
-
action:
|
|
9544
|
-
collection:
|
|
9545
|
-
mode:
|
|
9813
|
+
var qualityVerifyChainVariant = z23.object({
|
|
9814
|
+
action: z23.literal("verify-chain"),
|
|
9815
|
+
collection: z23.string().max(200).optional().default("glossary"),
|
|
9816
|
+
mode: z23.enum(["report", "fix"]).optional().default("report")
|
|
9546
9817
|
});
|
|
9547
|
-
var qualitySpineCheckVariant =
|
|
9548
|
-
action:
|
|
9549
|
-
story:
|
|
9550
|
-
refresh:
|
|
9818
|
+
var qualitySpineCheckVariant = z23.object({
|
|
9819
|
+
action: z23.literal("spine-check"),
|
|
9820
|
+
story: z23.boolean().optional().default(false),
|
|
9821
|
+
refresh: z23.boolean().optional().default(false)
|
|
9551
9822
|
});
|
|
9552
|
-
var qualityActionUnion =
|
|
9823
|
+
var qualityActionUnion = z23.discriminatedUnion("action", [
|
|
9553
9824
|
qualityCheckVariant,
|
|
9554
9825
|
qualityReEvaluateVariant,
|
|
9555
9826
|
qualityVerifyChainVariant,
|
|
@@ -9561,43 +9832,43 @@ var QUALITY_ACTION_SPECS = {
|
|
|
9561
9832
|
"verify-chain": { params: ["collection", "mode"], description: "All params optional; collection defaults to 'glossary'." },
|
|
9562
9833
|
"spine-check": { params: ["story", "refresh"], description: "All params optional; story and refresh default to false \u2014 a plain call never re-triggers work, it just reads back the latest verdict (auto-refreshing only when stale/absent)." }
|
|
9563
9834
|
};
|
|
9564
|
-
var qualityCheckOutputSchema =
|
|
9565
|
-
entryId:
|
|
9835
|
+
var qualityCheckOutputSchema = z23.object({
|
|
9836
|
+
entryId: z23.string(),
|
|
9566
9837
|
/** WP-480 S1: false = the ID does not resolve to an entry (typo/deleted) — distinct from "no verdict yet". */
|
|
9567
|
-
entryFound:
|
|
9568
|
-
hasVerdict:
|
|
9838
|
+
entryFound: z23.boolean().optional(),
|
|
9839
|
+
hasVerdict: z23.boolean(),
|
|
9569
9840
|
/** WP-480 S1: the verdict was judged against content the entry no longer has — re-evaluate for a current one. */
|
|
9570
|
-
stale:
|
|
9571
|
-
tier:
|
|
9572
|
-
passed:
|
|
9573
|
-
criteria:
|
|
9574
|
-
id:
|
|
9575
|
-
passed:
|
|
9576
|
-
hint:
|
|
9841
|
+
stale: z23.boolean().optional(),
|
|
9842
|
+
tier: z23.string().optional(),
|
|
9843
|
+
passed: z23.boolean().optional(),
|
|
9844
|
+
criteria: z23.array(z23.object({
|
|
9845
|
+
id: z23.string(),
|
|
9846
|
+
passed: z23.boolean(),
|
|
9847
|
+
hint: z23.string().optional()
|
|
9577
9848
|
}))
|
|
9578
9849
|
});
|
|
9579
|
-
var qualityReevaluateOutputSchema =
|
|
9580
|
-
entryId:
|
|
9581
|
-
context:
|
|
9582
|
-
score:
|
|
9583
|
-
maxScore:
|
|
9584
|
-
improved:
|
|
9850
|
+
var qualityReevaluateOutputSchema = z23.object({
|
|
9851
|
+
entryId: z23.string(),
|
|
9852
|
+
context: z23.string(),
|
|
9853
|
+
score: z23.number(),
|
|
9854
|
+
maxScore: z23.number(),
|
|
9855
|
+
improved: z23.boolean()
|
|
9585
9856
|
});
|
|
9586
|
-
var qualitySpineCheckOutputSchema =
|
|
9587
|
-
hasVerdict:
|
|
9588
|
-
noSpineEntries:
|
|
9589
|
-
structuralPassed:
|
|
9590
|
-
storyPassed:
|
|
9591
|
-
stale:
|
|
9857
|
+
var qualitySpineCheckOutputSchema = z23.object({
|
|
9858
|
+
hasVerdict: z23.boolean(),
|
|
9859
|
+
noSpineEntries: z23.boolean().optional(),
|
|
9860
|
+
structuralPassed: z23.boolean().optional(),
|
|
9861
|
+
storyPassed: z23.boolean().nullable().optional(),
|
|
9862
|
+
stale: z23.boolean().optional(),
|
|
9592
9863
|
// TASK-156: a capped membership scan must stay distinguishable from a complete one, and a
|
|
9593
9864
|
// malformed verdict needs its own discriminator — both were silently stripped before this.
|
|
9594
|
-
staleMemberIds:
|
|
9595
|
-
membershipTruncated:
|
|
9865
|
+
staleMemberIds: z23.array(z23.string()).optional(),
|
|
9866
|
+
membershipTruncated: z23.boolean().optional(),
|
|
9596
9867
|
// PRRT_kwDORS4ils6i_PVS: a KNOWN relations-fingerprint mismatch, distinct from "unknown" —
|
|
9597
9868
|
// without this, a detected topology change and an unverifiable legacy fingerprint were
|
|
9598
9869
|
// indistinguishable in structured output.
|
|
9599
|
-
relationsChanged:
|
|
9600
|
-
malformed:
|
|
9870
|
+
relationsChanged: z23.boolean().optional(),
|
|
9871
|
+
malformed: z23.boolean().optional()
|
|
9601
9872
|
});
|
|
9602
9873
|
function registerQualityTools(server) {
|
|
9603
9874
|
const qualityHandlers = {
|
|
@@ -9755,10 +10026,10 @@ async function handleReEvaluate(entryId, context) {
|
|
|
9755
10026
|
}
|
|
9756
10027
|
|
|
9757
10028
|
// src/tools/session.ts
|
|
9758
|
-
import { z as
|
|
10029
|
+
import { z as z26 } from "zod/v3";
|
|
9759
10030
|
|
|
9760
10031
|
// src/tools/wrapup.ts
|
|
9761
|
-
import { z as
|
|
10032
|
+
import { z as z24 } from "zod/v3";
|
|
9762
10033
|
|
|
9763
10034
|
// src/lib/compose-wrapup-view.ts
|
|
9764
10035
|
function toComposed(e) {
|
|
@@ -10050,8 +10321,8 @@ async function runWrapupCommitAll(data) {
|
|
|
10050
10321
|
overflowUnscanned
|
|
10051
10322
|
};
|
|
10052
10323
|
}
|
|
10053
|
-
var wrapupSchema =
|
|
10054
|
-
action:
|
|
10324
|
+
var wrapupSchema = z24.object({
|
|
10325
|
+
action: z24.enum(["review", "commit-all"]).optional().describe(
|
|
10055
10326
|
"Action to perform. 'review' (default) shows the wrapup summary. 'commit-all' accepts all uncommitted drafts; it writes no relations."
|
|
10056
10327
|
)
|
|
10057
10328
|
});
|
|
@@ -10144,26 +10415,26 @@ ${text}` : text;
|
|
|
10144
10415
|
}
|
|
10145
10416
|
|
|
10146
10417
|
// src/tools/facilitate.ts
|
|
10147
|
-
import { z as
|
|
10418
|
+
import { z as z25 } from "zod/v3";
|
|
10148
10419
|
var FACILITATE_ACTIONS = ["resume", "commit-constellation"];
|
|
10149
|
-
var coherencyAcknowledgementSchema =
|
|
10150
|
-
response:
|
|
10151
|
-
entryId:
|
|
10152
|
-
reason:
|
|
10153
|
-
subjectEntryId:
|
|
10420
|
+
var coherencyAcknowledgementSchema = z25.object({
|
|
10421
|
+
response: z25.string().max(200).describe("Acknowledgement response per offender: 'linked' | 'accepted-fix' | 'diverged'."),
|
|
10422
|
+
entryId: z25.string().max(200).optional().describe("Entry the acknowledgement links to (e.g. the strategic spine entry)."),
|
|
10423
|
+
reason: z25.string().max(2e3).optional().describe("Free-text justification, required for a 'diverged' response."),
|
|
10424
|
+
subjectEntryId: z25.string().max(200).optional().describe("The refused entry this acknowledgement answers.")
|
|
10154
10425
|
});
|
|
10155
|
-
var facilitateSchema =
|
|
10156
|
-
action:
|
|
10426
|
+
var facilitateSchema = z25.object({
|
|
10427
|
+
action: z25.enum(FACILITATE_ACTIONS).describe(
|
|
10157
10428
|
"'resume': load session state from an existing bet entry. 'commit-constellation': atomically accept a bet and all its linked draft entries in one call. Requires betEntryId."
|
|
10158
10429
|
),
|
|
10159
|
-
betEntryId:
|
|
10160
|
-
operationId:
|
|
10430
|
+
betEntryId: z25.string().max(200).optional().describe("Bet entry ID. Required for both actions."),
|
|
10431
|
+
operationId: z25.string().max(200).optional().describe("Optional idempotency key for commit-constellation retries."),
|
|
10161
10432
|
// WP-465 slice ⑤: coherency retry controls for a COHERENCY_REFUSED constellation hold.
|
|
10162
10433
|
// Forwarded verbatim to agentKnowledge.facilitateEnvelope (validation lives at the gate).
|
|
10163
|
-
coherencyAcknowledgements:
|
|
10434
|
+
coherencyAcknowledgements: z25.array(coherencyAcknowledgementSchema).max(20).optional().describe(
|
|
10164
10435
|
"Per-offender acknowledgements to retry a constellation held under standard/strict coherency mode. Each: {subjectEntryId, response: 'linked' | 'accepted-fix' | 'diverged', entryId?, reason?}."
|
|
10165
10436
|
),
|
|
10166
|
-
steeringOverrideReason:
|
|
10437
|
+
steeringOverrideReason: z25.string().max(2e3).optional().describe(
|
|
10167
10438
|
"Typed override reason (>= 12 chars) to push a constellation past a coherency hold instead of acknowledging."
|
|
10168
10439
|
)
|
|
10169
10440
|
});
|
|
@@ -10508,49 +10779,49 @@ var SESSION_ACTIONS = [
|
|
|
10508
10779
|
"resume",
|
|
10509
10780
|
"commit-constellation"
|
|
10510
10781
|
];
|
|
10511
|
-
var coherencyAcknowledgementFlatSchema2 =
|
|
10512
|
-
response:
|
|
10513
|
-
entryId:
|
|
10514
|
-
reason:
|
|
10515
|
-
subjectEntryId:
|
|
10782
|
+
var coherencyAcknowledgementFlatSchema2 = z26.object({
|
|
10783
|
+
response: z26.string().max(200).describe("Acknowledgement response per offender: 'linked' | 'accepted-fix' | 'diverged'."),
|
|
10784
|
+
entryId: z26.string().max(200).optional().describe("Entry the acknowledgement links to."),
|
|
10785
|
+
reason: z26.string().max(2e3).optional().describe("Free-text justification, required for a 'diverged' response."),
|
|
10786
|
+
subjectEntryId: z26.string().max(200).optional().describe("The refused entry this acknowledgement answers.")
|
|
10516
10787
|
});
|
|
10517
10788
|
var TEAM_PARAM_DESCRIPTION = "For 'start': the team the role is held in, by its 'TEAM-<n>' id \u2014 only needed with role, when you hold that role in more than one team; a refusal that names the way in prints it.";
|
|
10518
|
-
var sessionSchema =
|
|
10519
|
-
action:
|
|
10789
|
+
var sessionSchema = z26.object({
|
|
10790
|
+
action: z26.enum(SESSION_ACTIONS).describe(
|
|
10520
10791
|
"'start': begin a tracked session. 'close': end the session and record activity. 'status': check current session state. 'wrapup-review': review uncommitted drafts before closing (absorbs session-wrapup action=review). 'wrapup-commit': accept all uncommitted drafts (absorbs session-wrapup action=commit-all). 'resume': load session state from an existing bet entry (absorbs facilitate action=resume). 'commit-constellation': atomically accept a bet and its linked drafts (absorbs facilitate action=commit-constellation)."
|
|
10521
10792
|
),
|
|
10522
|
-
betEntryId:
|
|
10523
|
-
operationId:
|
|
10524
|
-
coherencyAcknowledgements:
|
|
10793
|
+
betEntryId: z26.string().max(200).optional().describe("For 'resume'/'commit-constellation': bet entry ID. Required for both."),
|
|
10794
|
+
operationId: z26.string().max(200).optional().describe("For 'commit-constellation': optional idempotency key for retries."),
|
|
10795
|
+
coherencyAcknowledgements: z26.array(coherencyAcknowledgementFlatSchema2).max(20).optional().describe(
|
|
10525
10796
|
"For 'commit-constellation': per-offender acknowledgements to retry a constellation held under standard/strict coherency mode."
|
|
10526
10797
|
),
|
|
10527
|
-
steeringOverrideReason:
|
|
10798
|
+
steeringOverrideReason: z26.string().max(2e3).optional().describe(
|
|
10528
10799
|
"For 'commit-constellation': typed override reason (>= 12 chars) to push past a coherency hold instead of acknowledging."
|
|
10529
10800
|
),
|
|
10530
10801
|
// DEC-1715 (WP-753 O1a)
|
|
10531
|
-
role:
|
|
10802
|
+
role: z26.string().max(200).optional().describe(
|
|
10532
10803
|
"For 'start': role to act as this session, by the '<PREFIX>-<n>' id a start reply prints beside the role name \u2014 only needed if you hold more than one; the error lists your roles if omitted."
|
|
10533
10804
|
),
|
|
10534
|
-
team:
|
|
10805
|
+
team: z26.string().max(200).optional().describe(TEAM_PARAM_DESCRIPTION)
|
|
10535
10806
|
// TASK-801
|
|
10536
10807
|
});
|
|
10537
|
-
var sessionStartVariant =
|
|
10538
|
-
action:
|
|
10808
|
+
var sessionStartVariant = z26.object({
|
|
10809
|
+
action: z26.literal("start"),
|
|
10539
10810
|
// DEC-1715 (WP-753 O1a): the role to act as this session — only needed when the person holds
|
|
10540
10811
|
// more than one role; the server refuses and lists the choices when it's required and omitted.
|
|
10541
|
-
role:
|
|
10812
|
+
role: z26.string().max(200).optional().describe(
|
|
10542
10813
|
"Role to act as this session, by the '<PREFIX>-<n>' id a start reply prints beside the role name \u2014 only needed if you hold more than one; the error lists your roles if omitted."
|
|
10543
10814
|
),
|
|
10544
|
-
team:
|
|
10815
|
+
team: z26.string().max(200).optional().describe(TEAM_PARAM_DESCRIPTION)
|
|
10545
10816
|
// TASK-801
|
|
10546
10817
|
});
|
|
10547
|
-
var sessionCloseVariant =
|
|
10548
|
-
var sessionStatusVariant =
|
|
10549
|
-
var sessionWrapupReviewVariant =
|
|
10550
|
-
var sessionWrapupCommitVariant =
|
|
10551
|
-
var sessionResumeVariant = facilitateSchema.omit({ action: true }).extend({ action:
|
|
10552
|
-
var sessionCommitConstellationVariant = facilitateSchema.omit({ action: true }).extend({ action:
|
|
10553
|
-
var sessionActionUnion =
|
|
10818
|
+
var sessionCloseVariant = z26.object({ action: z26.literal("close") });
|
|
10819
|
+
var sessionStatusVariant = z26.object({ action: z26.literal("status") });
|
|
10820
|
+
var sessionWrapupReviewVariant = z26.object({ action: z26.literal("wrapup-review") });
|
|
10821
|
+
var sessionWrapupCommitVariant = z26.object({ action: z26.literal("wrapup-commit") });
|
|
10822
|
+
var sessionResumeVariant = facilitateSchema.omit({ action: true }).extend({ action: z26.literal("resume") });
|
|
10823
|
+
var sessionCommitConstellationVariant = facilitateSchema.omit({ action: true }).extend({ action: z26.literal("commit-constellation") });
|
|
10824
|
+
var sessionActionUnion = z26.discriminatedUnion("action", [
|
|
10554
10825
|
sessionStartVariant,
|
|
10555
10826
|
sessionCloseVariant,
|
|
10556
10827
|
sessionStatusVariant,
|
|
@@ -10801,10 +11072,10 @@ async function handleStatus() {
|
|
|
10801
11072
|
}
|
|
10802
11073
|
|
|
10803
11074
|
// src/tools/workspace.ts
|
|
10804
|
-
import { z as
|
|
11075
|
+
import { z as z29 } from "zod/v3";
|
|
10805
11076
|
|
|
10806
11077
|
// src/tools/health.ts
|
|
10807
|
-
import { z as
|
|
11078
|
+
import { z as z27 } from "zod/v3";
|
|
10808
11079
|
|
|
10809
11080
|
// src/lib/auditView.ts
|
|
10810
11081
|
async function buildTenantAuditView(limit) {
|
|
@@ -11148,60 +11419,60 @@ ${logLines.join("\n")}${seamSummaryText}` }],
|
|
|
11148
11419
|
};
|
|
11149
11420
|
}
|
|
11150
11421
|
var HEALTH_ACTIONS = ["check", "whoami", "status", "audit", "self-test"];
|
|
11151
|
-
var healthSchema =
|
|
11152
|
-
action:
|
|
11422
|
+
var healthSchema = z27.object({
|
|
11423
|
+
action: z27.enum(HEALTH_ACTIONS).describe(
|
|
11153
11424
|
"'check': connectivity and workspace stats. 'whoami': session identity. 'status': workspace readiness. 'audit': session audit log. 'self-test': validate all tool schemas."
|
|
11154
11425
|
),
|
|
11155
|
-
limit:
|
|
11426
|
+
limit: z27.number().min(1).max(50).default(20).optional().describe("For audit: how many recent calls to show (max 50)")
|
|
11156
11427
|
});
|
|
11157
|
-
var healthCheckOutputSchema =
|
|
11158
|
-
healthy:
|
|
11159
|
-
collections:
|
|
11160
|
-
entries:
|
|
11161
|
-
latencyMs:
|
|
11162
|
-
workspace:
|
|
11428
|
+
var healthCheckOutputSchema = z27.object({
|
|
11429
|
+
healthy: z27.boolean(),
|
|
11430
|
+
collections: z27.number(),
|
|
11431
|
+
entries: z27.number(),
|
|
11432
|
+
latencyMs: z27.number(),
|
|
11433
|
+
workspace: z27.string()
|
|
11163
11434
|
});
|
|
11164
|
-
var organisationHealthSchema =
|
|
11165
|
-
reviewed:
|
|
11166
|
-
agreements:
|
|
11167
|
-
disagreements:
|
|
11168
|
-
abstentions:
|
|
11169
|
-
agreementRate:
|
|
11170
|
-
flags:
|
|
11435
|
+
var organisationHealthSchema = z27.object({
|
|
11436
|
+
reviewed: z27.number(),
|
|
11437
|
+
agreements: z27.number(),
|
|
11438
|
+
disagreements: z27.number(),
|
|
11439
|
+
abstentions: z27.number(),
|
|
11440
|
+
agreementRate: z27.number(),
|
|
11441
|
+
flags: z27.array(z27.object({ collection: z27.string(), count: z27.number(), suggestedCollection: z27.string() }))
|
|
11171
11442
|
});
|
|
11172
|
-
var healthStatusOutputSchema =
|
|
11173
|
-
sampleTruncated:
|
|
11174
|
-
activeEntries:
|
|
11175
|
-
totalRelations:
|
|
11176
|
-
orphanedEntries:
|
|
11177
|
-
checks:
|
|
11178
|
-
gaps:
|
|
11443
|
+
var healthStatusOutputSchema = z27.object({
|
|
11444
|
+
sampleTruncated: z27.boolean().nullable().optional(),
|
|
11445
|
+
activeEntries: z27.number(),
|
|
11446
|
+
totalRelations: z27.number(),
|
|
11447
|
+
orphanedEntries: z27.number(),
|
|
11448
|
+
checks: z27.array(z27.object({ label: z27.string(), passed: z27.boolean(), current: z27.number(), required: z27.number() })),
|
|
11449
|
+
gaps: z27.array(z27.object({ id: z27.string(), label: z27.string(), guidance: z27.string() })),
|
|
11179
11450
|
organisationHealth: organisationHealthSchema.optional()
|
|
11180
11451
|
});
|
|
11181
|
-
var healthAuditOutputSchema =
|
|
11182
|
-
totalCalls:
|
|
11183
|
-
calls:
|
|
11184
|
-
tool:
|
|
11185
|
-
action:
|
|
11186
|
-
timestamp:
|
|
11187
|
-
durationMs:
|
|
11452
|
+
var healthAuditOutputSchema = z27.object({
|
|
11453
|
+
totalCalls: z27.number(),
|
|
11454
|
+
calls: z27.array(z27.object({
|
|
11455
|
+
tool: z27.string(),
|
|
11456
|
+
action: z27.string().optional(),
|
|
11457
|
+
timestamp: z27.string(),
|
|
11458
|
+
durationMs: z27.number().optional()
|
|
11188
11459
|
}))
|
|
11189
11460
|
});
|
|
11190
|
-
var healthWhoamiOutputSchema =
|
|
11191
|
-
workspaceId:
|
|
11192
|
-
workspaceName:
|
|
11193
|
-
scope:
|
|
11194
|
-
sessionId:
|
|
11195
|
-
oriented:
|
|
11461
|
+
var healthWhoamiOutputSchema = z27.object({
|
|
11462
|
+
workspaceId: z27.string(),
|
|
11463
|
+
workspaceName: z27.string(),
|
|
11464
|
+
scope: z27.string(),
|
|
11465
|
+
sessionId: z27.union([z27.string(), z27.null()]),
|
|
11466
|
+
oriented: z27.boolean()
|
|
11196
11467
|
});
|
|
11197
|
-
var selfTestOutputSchema =
|
|
11198
|
-
passed:
|
|
11199
|
-
failed:
|
|
11200
|
-
total:
|
|
11201
|
-
results:
|
|
11202
|
-
tool:
|
|
11203
|
-
valid:
|
|
11204
|
-
error:
|
|
11468
|
+
var selfTestOutputSchema = z27.object({
|
|
11469
|
+
passed: z27.number(),
|
|
11470
|
+
failed: z27.number(),
|
|
11471
|
+
total: z27.number(),
|
|
11472
|
+
results: z27.array(z27.object({
|
|
11473
|
+
tool: z27.string(),
|
|
11474
|
+
valid: z27.boolean(),
|
|
11475
|
+
error: z27.string().optional()
|
|
11205
11476
|
}))
|
|
11206
11477
|
});
|
|
11207
11478
|
function handleSelfTest(server) {
|
|
@@ -11252,9 +11523,9 @@ function handleSelfTest(server) {
|
|
|
11252
11523
|
}
|
|
11253
11524
|
|
|
11254
11525
|
// src/tools/usage.ts
|
|
11255
|
-
import { z as
|
|
11256
|
-
var usageSummarySchema =
|
|
11257
|
-
periodDays:
|
|
11526
|
+
import { z as z28 } from "zod/v3";
|
|
11527
|
+
var usageSummarySchema = z28.object({
|
|
11528
|
+
periodDays: z28.number().min(1).max(90).optional().describe("Number of days to look back (default 30, max 90)")
|
|
11258
11529
|
});
|
|
11259
11530
|
async function handleUsageSummary(periodDays) {
|
|
11260
11531
|
const ws = await getWorkspaceContext();
|
|
@@ -11324,20 +11595,20 @@ var WORKSPACE_ACTIONS = [
|
|
|
11324
11595
|
"self-test",
|
|
11325
11596
|
"usage"
|
|
11326
11597
|
];
|
|
11327
|
-
var workspaceSchema =
|
|
11328
|
-
action:
|
|
11598
|
+
var workspaceSchema = z29.object({
|
|
11599
|
+
action: z29.enum(WORKSPACE_ACTIONS).describe(
|
|
11329
11600
|
"'check': connectivity and workspace stats (absorbs health action=check). 'whoami': session identity (absorbs health action=whoami). 'status': workspace readiness (absorbs health action=status). 'audit': session audit log (absorbs health action=audit). 'self-test': validate all tool schemas (absorbs health action=self-test). 'usage': LLM usage and cost summary (absorbs get-usage-summary)."
|
|
11330
11601
|
),
|
|
11331
|
-
limit:
|
|
11332
|
-
periodDays:
|
|
11602
|
+
limit: z29.number().min(1).max(50).optional().describe("For 'audit': how many recent calls to show (max 50, default 20)."),
|
|
11603
|
+
periodDays: z29.number().min(1).max(90).optional().describe("For 'usage': number of days to look back (default 30, max 90).")
|
|
11333
11604
|
});
|
|
11334
|
-
var workspaceCheckVariant =
|
|
11335
|
-
var workspaceWhoamiVariant =
|
|
11336
|
-
var workspaceStatusVariant =
|
|
11337
|
-
var workspaceAuditVariant =
|
|
11338
|
-
var workspaceSelfTestVariant =
|
|
11339
|
-
var workspaceUsageVariant =
|
|
11340
|
-
var workspaceActionUnion =
|
|
11605
|
+
var workspaceCheckVariant = z29.object({ action: z29.literal("check") });
|
|
11606
|
+
var workspaceWhoamiVariant = z29.object({ action: z29.literal("whoami") });
|
|
11607
|
+
var workspaceStatusVariant = z29.object({ action: z29.literal("status") });
|
|
11608
|
+
var workspaceAuditVariant = z29.object({ action: z29.literal("audit"), limit: z29.number().min(1).max(50).optional().default(20) });
|
|
11609
|
+
var workspaceSelfTestVariant = z29.object({ action: z29.literal("self-test") });
|
|
11610
|
+
var workspaceUsageVariant = z29.object({ action: z29.literal("usage"), periodDays: z29.number().min(1).max(90).optional() });
|
|
11611
|
+
var workspaceActionUnion = z29.discriminatedUnion("action", [
|
|
11341
11612
|
workspaceCheckVariant,
|
|
11342
11613
|
workspaceWhoamiVariant,
|
|
11343
11614
|
workspaceStatusVariant,
|
|
@@ -11383,7 +11654,7 @@ function registerWorkspaceTools(server) {
|
|
|
11383
11654
|
}
|
|
11384
11655
|
|
|
11385
11656
|
// src/tools/feedback.ts
|
|
11386
|
-
import { z as
|
|
11657
|
+
import { z as z30 } from "zod/v3";
|
|
11387
11658
|
|
|
11388
11659
|
// src/lib/productFeedbackConstants.ts
|
|
11389
11660
|
var PRODUCT_FEEDBACK_CATEGORIES = ["bug", "friction", "idea", "praise", "other"];
|
|
@@ -11394,37 +11665,37 @@ var VENDOR_SETTABLE_STATUSES = PRODUCT_FEEDBACK_STATUSES.filter(
|
|
|
11394
11665
|
|
|
11395
11666
|
// src/tools/feedback.ts
|
|
11396
11667
|
var actions = ["submit", "list", "queue", "note", "group", "status"];
|
|
11397
|
-
var category =
|
|
11398
|
-
var status =
|
|
11399
|
-
var vendorStatus =
|
|
11668
|
+
var category = z30.enum(PRODUCT_FEEDBACK_CATEGORIES);
|
|
11669
|
+
var status = z30.enum(PRODUCT_FEEDBACK_STATUSES);
|
|
11670
|
+
var vendorStatus = z30.enum(VENDOR_SETTABLE_STATUSES);
|
|
11400
11671
|
var MESSAGE_DISPLAY_LIMIT = 1e3;
|
|
11401
11672
|
var FULL_MESSAGE_MAX_LIMIT = 5;
|
|
11402
|
-
var feedbackSchema =
|
|
11403
|
-
action:
|
|
11404
|
-
message:
|
|
11673
|
+
var feedbackSchema = z30.object({
|
|
11674
|
+
action: z30.enum(actions).describe("submit requires message; list returns your own workspace's feedback (all statuses); queue is the vendor triage queue (system admins only) and accepts filters; note requires feedbackId+note; group requires feedbackIds+groupId (null clears); status requires feedbackId+status."),
|
|
11675
|
+
message: z30.string().max(1e4).optional().describe("Required for submit: the product feedback text (max 10,000 characters)."),
|
|
11405
11676
|
category: category.optional().describe("Submit/queue category; submit defaults to other."),
|
|
11406
|
-
command:
|
|
11407
|
-
route:
|
|
11408
|
-
client:
|
|
11409
|
-
feedbackId:
|
|
11410
|
-
feedbackIds:
|
|
11411
|
-
note:
|
|
11677
|
+
command: z30.string().max(1e3).optional().describe("Optional submit command context; argument values are scrubbed server-side."),
|
|
11678
|
+
route: z30.string().max(500).optional().describe("Optional submit route context."),
|
|
11679
|
+
client: z30.string().max(100).optional().describe("Optional submit client label."),
|
|
11680
|
+
feedbackId: z30.string().max(200).optional().describe("Required for note/status: target feedback ID."),
|
|
11681
|
+
feedbackIds: z30.array(z30.string().max(200)).max(100).optional().describe("Required for group: 1\u2013100 target feedback IDs."),
|
|
11682
|
+
note: z30.string().max(4e3).optional().describe("Required for note: replacement triage note (max 4,000 characters)."),
|
|
11412
11683
|
status: status.optional().describe("list/queue filter (any status, including 'screening'); the status action's required target value excludes 'screening' (system-only)."),
|
|
11413
|
-
groupId:
|
|
11414
|
-
workspaceId:
|
|
11415
|
-
since:
|
|
11416
|
-
before:
|
|
11417
|
-
limit:
|
|
11418
|
-
cursor:
|
|
11419
|
-
full:
|
|
11684
|
+
groupId: z30.string().min(1).max(200).nullable().optional().describe("Group filter, or required group destination; null explicitly clears grouping."),
|
|
11685
|
+
workspaceId: z30.string().max(200).optional().describe("Queue-only filter (vendor cross-workspace triage); omitted means all workspaces. Has no effect on list \u2014 your own workspace is always injected server-side."),
|
|
11686
|
+
since: z30.number().optional().describe("Queue-only lower createdAt window bound (inclusive) in epoch milliseconds."),
|
|
11687
|
+
before: z30.number().optional().describe("Queue-only upper createdAt window bound (exclusive) in epoch milliseconds. A time-window FILTER, not the pager \u2014 use cursor to page."),
|
|
11688
|
+
limit: z30.number().int().min(1).max(100).optional().describe("list/queue row limit, default 50, maximum 100."),
|
|
11689
|
+
cursor: z30.string().max(2e3).optional().describe("Opaque pagination cursor from a previous list/queue response (continueCursor); omit for the first page."),
|
|
11690
|
+
full: z30.boolean().optional().describe(`list/queue only: return untruncated messages; allowed only when limit <= ${FULL_MESSAGE_MAX_LIMIT}.`)
|
|
11420
11691
|
});
|
|
11421
|
-
var union =
|
|
11422
|
-
|
|
11423
|
-
|
|
11424
|
-
|
|
11425
|
-
|
|
11426
|
-
|
|
11427
|
-
|
|
11692
|
+
var union = z30.discriminatedUnion("action", [
|
|
11693
|
+
z30.object({ action: z30.literal("submit"), message: z30.string().min(1).max(1e4), category: category.optional(), command: z30.string().max(1e3).optional(), route: z30.string().max(500).optional(), client: z30.string().max(100).optional() }),
|
|
11694
|
+
z30.object({ action: z30.literal("list"), status: status.optional(), limit: z30.number().int().min(1).max(100).optional(), cursor: z30.string().max(2e3).optional(), full: z30.boolean().optional() }),
|
|
11695
|
+
z30.object({ action: z30.literal("queue"), status: status.optional(), category: category.optional(), groupId: z30.string().min(1).max(200).optional(), workspaceId: z30.string().max(200).optional(), since: z30.number().optional(), before: z30.number().optional(), limit: z30.number().int().min(1).max(100).optional(), cursor: z30.string().max(2e3).optional(), full: z30.boolean().optional() }),
|
|
11696
|
+
z30.object({ action: z30.literal("note"), feedbackId: z30.string().min(1).max(200), note: z30.string().max(4e3) }),
|
|
11697
|
+
z30.object({ action: z30.literal("group"), feedbackIds: z30.array(z30.string().min(1).max(200)).min(1).max(100), groupId: z30.string().min(1).max(200).nullable() }),
|
|
11698
|
+
z30.object({ action: z30.literal("status"), feedbackId: z30.string().min(1).max(200), status: vendorStatus })
|
|
11428
11699
|
]);
|
|
11429
11700
|
var specs = {
|
|
11430
11701
|
submit: { params: ["message", "category", "command", "route", "client"], description: "message is required; category defaults to other." },
|
|
@@ -11550,26 +11821,26 @@ function registerFeedbackTool(server) {
|
|
|
11550
11821
|
}
|
|
11551
11822
|
|
|
11552
11823
|
// src/tools/question.ts
|
|
11553
|
-
import { z as
|
|
11824
|
+
import { z as z31 } from "zod/v3";
|
|
11554
11825
|
var QUESTION_ACTIONS = ["create", "assign", "answer", "force-close", "list"];
|
|
11555
|
-
var questionSchema =
|
|
11556
|
-
action:
|
|
11826
|
+
var questionSchema = z31.object({
|
|
11827
|
+
action: z31.enum(QUESTION_ACTIONS).describe(
|
|
11557
11828
|
"'create': create a new routed question from text \u2014 the dedicated birth action; every question is born escalated to the team lead (generic entry creation and move-and-retype also pair a routing facet). 'assign': reassign ownership to a role (toRole required \u2014 no bare self-confirm, no toPerson). 'answer': close the loop \u2014 writes the answer on the question and moves it to answered; --entry links an existing decision instead. 'force-close': Team-Lead-only escape hatch \u2014 reason required. 'list': the ack-gate read model \u2014 what you owe (or, with mine:true, every question you asked, including closed ones)."
|
|
11558
11829
|
),
|
|
11559
|
-
entryId:
|
|
11560
|
-
text:
|
|
11561
|
-
blocks:
|
|
11562
|
-
toRole:
|
|
11563
|
-
reason:
|
|
11564
|
-
answerEntryId:
|
|
11565
|
-
mine:
|
|
11830
|
+
entryId: z31.string().max(200).optional().describe("Target question's id (human TEN-nnn form or a raw entry id). Required for every action except 'create'/'list'."),
|
|
11831
|
+
text: z31.string().max(5e3).optional().describe("'create': the question text. 'answer': the answer text (mutually exclusive with answerEntryId, max 2000 chars)."),
|
|
11832
|
+
blocks: z31.array(z31.string().max(200)).max(50).optional().describe("'create': entry ids this question is blocking (repeatable)."),
|
|
11833
|
+
toRole: z31.string().max(200).optional().describe("'assign': reassign to this role (human ROL-nnn form or a raw entry id) \u2014 required."),
|
|
11834
|
+
reason: z31.string().max(2e3).optional().describe("'force-close': required reason."),
|
|
11835
|
+
answerEntryId: z31.string().max(200).optional().describe("'answer': point at an already-written entry instead of supplying text (mutually exclusive with text)."),
|
|
11836
|
+
mine: z31.boolean().optional().describe("'list': true for arm C (every question YOU asked, every status). Omit/false for the ack-gate view (what you owe).")
|
|
11566
11837
|
});
|
|
11567
|
-
var createVariant =
|
|
11568
|
-
var assignVariant =
|
|
11569
|
-
var answerVariant =
|
|
11570
|
-
var forceCloseVariant =
|
|
11571
|
-
var listVariant =
|
|
11572
|
-
var questionActionUnion =
|
|
11838
|
+
var createVariant = z31.object({ action: z31.literal("create"), text: z31.string().min(1).max(5e3), blocks: z31.array(z31.string().max(200)).max(50).optional() });
|
|
11839
|
+
var assignVariant = z31.object({ action: z31.literal("assign"), entryId: z31.string().max(200), toRole: z31.string().max(200).min(1) });
|
|
11840
|
+
var answerVariant = z31.object({ action: z31.literal("answer"), entryId: z31.string().max(200), text: z31.string().max(2e3).optional(), answerEntryId: z31.string().max(200).optional() });
|
|
11841
|
+
var forceCloseVariant = z31.object({ action: z31.literal("force-close"), entryId: z31.string().max(200), reason: z31.string().min(1).max(2e3) });
|
|
11842
|
+
var listVariant = z31.object({ action: z31.literal("list"), mine: z31.boolean().optional() });
|
|
11843
|
+
var questionActionUnion = z31.discriminatedUnion("action", [
|
|
11573
11844
|
createVariant,
|
|
11574
11845
|
assignVariant,
|
|
11575
11846
|
answerVariant,
|
|
@@ -11723,47 +11994,47 @@ function registerQuestionTools(server) {
|
|
|
11723
11994
|
}
|
|
11724
11995
|
|
|
11725
11996
|
// src/tools/role.ts
|
|
11726
|
-
import { z as
|
|
11997
|
+
import { z as z32 } from "zod/v3";
|
|
11727
11998
|
var ROLE_ACTIONS = ["accountable", "seat", "unseat"];
|
|
11728
|
-
var roleSchema =
|
|
11729
|
-
action:
|
|
11999
|
+
var roleSchema = z32.object({
|
|
12000
|
+
action: z32.enum(ROLE_ACTIONS).describe(
|
|
11730
12001
|
"'accountable': what this role owns (explicit), reports on (reporting), and \u2014 not yet computed \u2014 inherits via Team-Lead vacancy coverage. 'seat': put a person in this role. 'unseat': take this role from a person."
|
|
11731
12002
|
),
|
|
11732
|
-
roleId:
|
|
11733
|
-
canonicalKey:
|
|
11734
|
-
limit:
|
|
11735
|
-
cursor:
|
|
11736
|
-
person:
|
|
12003
|
+
roleId: z32.string().max(200).optional().describe("The role, by the human chain id `chain.getEntry` or `pb get` would print for it, or a raw entry id."),
|
|
12004
|
+
canonicalKey: z32.string().max(200).optional().describe("'accountable': narrow to one kind (e.g. objective, key_result, tension)."),
|
|
12005
|
+
limit: z32.number().int().positive().max(200).optional().describe("'accountable': max explicit-list rows per page (default and maximum 200)."),
|
|
12006
|
+
cursor: z32.number().optional().describe("'accountable': continue the explicit list from an earlier truncated page's nextCursor."),
|
|
12007
|
+
person: z32.string().max(200).optional().describe(
|
|
11737
12008
|
"'seat' / 'unseat': an existing person, by person id or exact email. For 'seat', give this or newPersonName, not both."
|
|
11738
12009
|
),
|
|
11739
|
-
newPersonName:
|
|
12010
|
+
newPersonName: z32.string().max(120).optional().describe(
|
|
11740
12011
|
"'seat': the name of a person who has no login yet; a placeholder person is created once and reused for the same exact name. Refused when the name belongs to someone with an account."
|
|
11741
12012
|
),
|
|
11742
|
-
teamId:
|
|
12013
|
+
teamId: z32.string().max(200).optional().describe(
|
|
11743
12014
|
"'seat' / 'unseat': the team, by chain id or entry id. Only needed for Team Lead, which lives in every team; any other role is seated in its home team."
|
|
11744
12015
|
)
|
|
11745
12016
|
});
|
|
11746
|
-
var accountableVariant =
|
|
11747
|
-
action:
|
|
11748
|
-
roleId:
|
|
11749
|
-
canonicalKey:
|
|
11750
|
-
limit:
|
|
11751
|
-
cursor:
|
|
12017
|
+
var accountableVariant = z32.object({
|
|
12018
|
+
action: z32.literal("accountable"),
|
|
12019
|
+
roleId: z32.string().max(200),
|
|
12020
|
+
canonicalKey: z32.string().max(200).optional(),
|
|
12021
|
+
limit: z32.number().int().positive().max(200).optional(),
|
|
12022
|
+
cursor: z32.number().optional()
|
|
11752
12023
|
});
|
|
11753
|
-
var seatVariant =
|
|
11754
|
-
action:
|
|
11755
|
-
roleId:
|
|
11756
|
-
person:
|
|
11757
|
-
newPersonName:
|
|
11758
|
-
teamId:
|
|
12024
|
+
var seatVariant = z32.object({
|
|
12025
|
+
action: z32.literal("seat"),
|
|
12026
|
+
roleId: z32.string().max(200),
|
|
12027
|
+
person: z32.string().max(200).optional(),
|
|
12028
|
+
newPersonName: z32.string().max(120).optional(),
|
|
12029
|
+
teamId: z32.string().max(200).optional()
|
|
11759
12030
|
});
|
|
11760
|
-
var unseatVariant =
|
|
11761
|
-
action:
|
|
11762
|
-
roleId:
|
|
11763
|
-
person:
|
|
11764
|
-
teamId:
|
|
12031
|
+
var unseatVariant = z32.object({
|
|
12032
|
+
action: z32.literal("unseat"),
|
|
12033
|
+
roleId: z32.string().max(200),
|
|
12034
|
+
person: z32.string().max(200),
|
|
12035
|
+
teamId: z32.string().max(200).optional()
|
|
11765
12036
|
});
|
|
11766
|
-
var roleActionUnion =
|
|
12037
|
+
var roleActionUnion = z32.discriminatedUnion("action", [accountableVariant, seatVariant, unseatVariant]);
|
|
11767
12038
|
var ROLE_ACTION_SPECS = {
|
|
11768
12039
|
accountable: { params: ["roleId", "canonicalKey", "limit", "cursor"], description: "roleId is required; canonicalKey/limit/cursor are optional." },
|
|
11769
12040
|
seat: { params: ["roleId", "person", "newPersonName", "teamId"], description: "roleId is required, plus exactly one of person or newPersonName; teamId only for Team Lead." },
|
|
@@ -11890,246 +12161,6 @@ function registerRoleTools(server) {
|
|
|
11890
12161
|
);
|
|
11891
12162
|
}
|
|
11892
12163
|
|
|
11893
|
-
// src/tools/outcome.ts
|
|
11894
|
-
import { z as z32 } from "zod/v3";
|
|
11895
|
-
var OUTCOME_ACTIONS = ["record", "list", "show"];
|
|
11896
|
-
var READING_KINDS = ["measurement", "estimate", "correction"];
|
|
11897
|
-
var outcomeSchema = z32.object({
|
|
11898
|
-
action: z32.enum(OUTCOME_ACTIONS).describe(
|
|
11899
|
-
"'record': record a reading (evidence, not a verdict). 'list': list readings, newest first. 'show': the derived view \u2014 current, progress, pace, staleness, recorded completion."
|
|
11900
|
-
),
|
|
11901
|
-
entryId: z32.string().max(200).optional().describe("The key result (or other outcome-bearing) entry, by its chain id. Required for all three actions."),
|
|
11902
|
-
// PR #858 review round 3 (Codex P2, PRRT_kwDORS4ils6gXHj9): a JSON number that overflows to
|
|
11903
|
-
// `Infinity` (e.g. `1e400`) parses fine in JS and passes a plain `z.number()`, but
|
|
11904
|
-
// `callGateway()` serializes it with `JSON.stringify`, which turns `Infinity` into `null` —
|
|
11905
|
-
// the backend's `v.number()` validator then rejects a call this tool's own schema accepted.
|
|
11906
|
-
// `.finite()` rejects it here, matching the explicit finite-value checks the CLI/other outcome
|
|
11907
|
-
// entry surfaces already use.
|
|
11908
|
-
value: z32.number().finite().optional().describe("'record': the measured value. Required for 'record'."),
|
|
11909
|
-
valueText: z32.string().max(500).optional().describe("'record': verbatim as-reported form when the source was not clean, e.g. '~62%'. Display only."),
|
|
11910
|
-
asOf: z32.string().max(64).optional().describe("'record': when the world was in this state, as a parseable date (default: now). Back-dating a backfill is legitimate \u2014 it shows up as asOf earlier than recordedAt."),
|
|
11911
|
-
kind: z32.enum(READING_KINDS).optional().describe("'record': measurement | estimate | correction (default: measurement)."),
|
|
11912
|
-
correctsReadingId: z32.string().max(200).optional().describe("'record': required with kind='correction' \u2014 the reading id this replaces. Refused if that row is already superseded."),
|
|
11913
|
-
recordedByRoleId: z32.string().max(200).optional().describe("'record': the accountable role (default: the entry's reporterRoleId, then its owning role)."),
|
|
11914
|
-
note: z32.string().max(2e3).optional().describe("'record': free-text note recorded with the reading."),
|
|
11915
|
-
source: z32.string().max(500).optional().describe("'record': where the number came from \u2014 a dashboard name, a query, a URL."),
|
|
11916
|
-
limit: z32.number().int().positive().max(200).optional().describe("'list': max rows to return (default and maximum 200).")
|
|
11917
|
-
});
|
|
11918
|
-
var recordVariant = z32.object({
|
|
11919
|
-
action: z32.literal("record"),
|
|
11920
|
-
entryId: z32.string().max(200),
|
|
11921
|
-
value: z32.number().finite(),
|
|
11922
|
-
valueText: z32.string().max(500).optional(),
|
|
11923
|
-
asOf: z32.string().max(64).optional(),
|
|
11924
|
-
kind: z32.enum(READING_KINDS).optional(),
|
|
11925
|
-
correctsReadingId: z32.string().max(200).optional(),
|
|
11926
|
-
recordedByRoleId: z32.string().max(200).optional(),
|
|
11927
|
-
note: z32.string().max(2e3).optional(),
|
|
11928
|
-
source: z32.string().max(500).optional()
|
|
11929
|
-
});
|
|
11930
|
-
var listVariant2 = z32.object({
|
|
11931
|
-
action: z32.literal("list"),
|
|
11932
|
-
entryId: z32.string().max(200),
|
|
11933
|
-
limit: z32.number().int().positive().max(200).optional()
|
|
11934
|
-
});
|
|
11935
|
-
var showVariant = z32.object({ action: z32.literal("show"), entryId: z32.string().max(200) });
|
|
11936
|
-
var outcomeActionUnion = z32.discriminatedUnion("action", [recordVariant, listVariant2, showVariant]);
|
|
11937
|
-
var OUTCOME_ACTION_SPECS = {
|
|
11938
|
-
record: {
|
|
11939
|
-
params: ["entryId", "value", "valueText", "asOf", "kind", "correctsReadingId", "recordedByRoleId", "note", "source"],
|
|
11940
|
-
description: "entryId and value are required; the rest are optional."
|
|
11941
|
-
},
|
|
11942
|
-
list: { params: ["entryId", "limit"], description: "entryId is required; limit is optional." },
|
|
11943
|
-
show: { params: ["entryId"], description: "entryId is required." }
|
|
11944
|
-
};
|
|
11945
|
-
function safeDateSlice(ms) {
|
|
11946
|
-
const d = new Date(ms);
|
|
11947
|
-
return Number.isNaN(d.getTime()) ? "invalid-date" : d.toISOString().slice(0, 10);
|
|
11948
|
-
}
|
|
11949
|
-
function formatRecordReceipt(numericValue, entryId, valueText, receipt) {
|
|
11950
|
-
const tier = receipt.independenceTier ?? "unknown";
|
|
11951
|
-
const lines = [
|
|
11952
|
-
`Recorded ${numericValue}${valueText ? ` ("${sanitizeSingleLineField(valueText)}")` : ""} on ${sanitizeSingleLineField(entryId)}.`,
|
|
11953
|
-
` attributed: ${receipt.actorKind ?? "unknown"} \xB7 independence: ${tier}`
|
|
11954
|
-
];
|
|
11955
|
-
if (tier === "provenance_unknown") {
|
|
11956
|
-
lines.push(" (no session named, so provenance is unknown \u2014 that is the honest answer, not an error)");
|
|
11957
|
-
}
|
|
11958
|
-
return lines.join("\n");
|
|
11959
|
-
}
|
|
11960
|
-
function formatReadingsList(entryId, result2) {
|
|
11961
|
-
const safeEntryId = sanitizeSingleLineField(entryId);
|
|
11962
|
-
const rows = result2?.readings ?? [];
|
|
11963
|
-
if (rows.length === 0) return `No readings recorded on ${safeEntryId} yet.`;
|
|
11964
|
-
const lines = rows.map((row) => {
|
|
11965
|
-
const when = safeDateSlice(row.asOf);
|
|
11966
|
-
const superseded = row.supersededByReadingId ? ` <- superseded by ${row.supersededByReadingId}` : "";
|
|
11967
|
-
const text = row.valueText ? ` ("${sanitizeSingleLineField(row.valueText)}")` : "";
|
|
11968
|
-
const note = row.note ? ` - ${sanitizeSingleLineField(row.note)}` : "";
|
|
11969
|
-
return ` ${when} ${String(row.value).padStart(8)}${text} [${row.kind}\xB7${row.independenceTier}] ${row.readingId}${note}${superseded}`;
|
|
11970
|
-
});
|
|
11971
|
-
const tail = result2?.pageExhausted === false ? "\n (older readings not loaded - raise --limit)" : "";
|
|
11972
|
-
return `${rows.length} reading(s) on ${safeEntryId}, newest first:
|
|
11973
|
-
${lines.join("\n")}${tail}`;
|
|
11974
|
-
}
|
|
11975
|
-
var pct = (v, unit = "%") => v === void 0 ? "\u2014" : `${Math.round(v * 10) / 10}${unit}`;
|
|
11976
|
-
var roleLabel = (role) => role === null ? "not set" : role.name === null ? "a role that no longer exists" : sanitizeSingleLineField(role.name);
|
|
11977
|
-
function formatOutcomeShow(result2) {
|
|
11978
|
-
if (!result2) return "No outcome found.";
|
|
11979
|
-
const o = result2.outcome;
|
|
11980
|
-
const unit = o.unit ? ` ${sanitizeSingleLineField(o.unit)}` : "";
|
|
11981
|
-
const lines = [
|
|
11982
|
-
// N2 (TASK-367): the metric line is retired — the entry's own name (above) already states
|
|
11983
|
-
// what is measured — mirrors packages/cli/src/commands/outcome.ts text-for-text.
|
|
11984
|
-
`${sanitizeSingleLineField(result2.entryId)} \u2014 ${sanitizeSingleLineField(result2.name)}`,
|
|
11985
|
-
` current ${o.current ? `${o.current.value}${unit}` : "no readings yet"} (${o.readingCount} reading(s))`,
|
|
11986
|
-
` progress ${pct(o.progressPct)} direction ${o.direction}`,
|
|
11987
|
-
` pace ${pct(o.pacePct)} ${o.pacePct === void 0 ? "(no cycle end set)" : o.pacePct >= 0 ? "(ahead of pace)" : "(behind pace)"}`,
|
|
11988
|
-
` state ${o.state}${o.hasNoReadings ? " \u2014 never read" : ""}${o.overdueByMs ? ` (by ${Math.floor(o.overdueByMs / 864e5)}d)` : ""}`,
|
|
11989
|
-
` next due ${o.nextDueAt ? safeDateSlice(o.nextDueAt) : "no cadence set"}`,
|
|
11990
|
-
` owner ${roleLabel(o.ownerRole)}`,
|
|
11991
|
-
` reporter ${roleLabel(o.reporterRole)}`,
|
|
11992
|
-
` completion recorded as ${o.completion} (source: ${o.completionProvenance})`,
|
|
11993
|
-
` attestation weakest in cycle: ${o.weakestTierInCycle ?? "none recorded"} \u2014 reported, not enforced`
|
|
11994
|
-
];
|
|
11995
|
-
if (o.currentResolution === "page-exhausted") {
|
|
11996
|
-
lines.push(' note every loaded reading is superseded and more remain \u2014 this is not "never read"');
|
|
11997
|
-
}
|
|
11998
|
-
if (result2.readyToCloseInstruction) {
|
|
11999
|
-
lines.push("", ` ${result2.readyToCloseInstruction}`);
|
|
12000
|
-
}
|
|
12001
|
-
return lines.join("\n");
|
|
12002
|
-
}
|
|
12003
|
-
function outcomeErrorResult(err, action, entryId, params = {}) {
|
|
12004
|
-
const classified = classifyError(err);
|
|
12005
|
-
const definedParams = Object.fromEntries(Object.entries(params).filter(([, v]) => v !== void 0));
|
|
12006
|
-
const isUnverifiedRecordTimeout = action === "record" && classified.code === "GATEWAY_TIMEOUT";
|
|
12007
|
-
const isMissingCorrectionTarget = action === "record" && classified.code === "NOT_FOUND" && classified.message.startsWith("Reading not found");
|
|
12008
|
-
const defaultActions = isUnverifiedRecordTimeout ? [
|
|
12009
|
-
{ tool: "outcome", description: "Check whether the reading already landed", parameters: { action: "list", entryId } },
|
|
12010
|
-
{ tool: "outcome", description: "Check the derived view", parameters: { action: "show", entryId } }
|
|
12011
|
-
] : isMissingCorrectionTarget ? [{ tool: "outcome", description: "List readings for this entry to find a valid correctsReadingId", parameters: { action: "list", entryId } }] : retryIsFutile(classified.code) ? void 0 : [{ tool: "outcome", description: `Retry ${action}`, parameters: { action, ...definedParams } }];
|
|
12012
|
-
return failureResult(
|
|
12013
|
-
classified.message,
|
|
12014
|
-
classified.code,
|
|
12015
|
-
classified.message,
|
|
12016
|
-
isMissingCorrectionTarget ? `Reading correctsReadingId not found for entryId='${entryId}'. Use action='list' to see valid reading ids.` : classified.recovery ?? "Use action='show' or action='list' with a valid entryId to check the key result exists.",
|
|
12017
|
-
isMissingCorrectionTarget ? defaultActions : classified.availableActions ?? defaultActions,
|
|
12018
|
-
classified.diagnostics
|
|
12019
|
-
);
|
|
12020
|
-
}
|
|
12021
|
-
async function handleOutcomeRecord(entryId, value, opts = {}) {
|
|
12022
|
-
requireWriteAccess();
|
|
12023
|
-
if (opts.correctsReadingId !== void 0 && opts.kind !== "correction") {
|
|
12024
|
-
return failureResult(
|
|
12025
|
-
"correctsReadingId is only meaningful with kind='correction'.",
|
|
12026
|
-
"VALIDATION_ERROR",
|
|
12027
|
-
"correctsReadingId is only meaningful with kind='correction'.",
|
|
12028
|
-
"Set kind='correction', or drop correctsReadingId to record an ordinary reading."
|
|
12029
|
-
);
|
|
12030
|
-
}
|
|
12031
|
-
if (opts.kind === "correction" && opts.correctsReadingId === void 0) {
|
|
12032
|
-
return failureResult(
|
|
12033
|
-
"kind='correction' requires correctsReadingId.",
|
|
12034
|
-
"VALIDATION_ERROR",
|
|
12035
|
-
"kind='correction' requires correctsReadingId.",
|
|
12036
|
-
"A correction must name the reading it replaces \u2014 find it with action='list'."
|
|
12037
|
-
);
|
|
12038
|
-
}
|
|
12039
|
-
let asOf;
|
|
12040
|
-
if (opts.asOf !== void 0) {
|
|
12041
|
-
const parsed = Date.parse(opts.asOf);
|
|
12042
|
-
if (Number.isNaN(parsed)) {
|
|
12043
|
-
return failureResult(
|
|
12044
|
-
`asOf must be a parseable date (got "${opts.asOf}").`,
|
|
12045
|
-
"VALIDATION_ERROR",
|
|
12046
|
-
`asOf must be a parseable date (got "${opts.asOf}").`,
|
|
12047
|
-
"Example: asOf='2026-03-01'. Back-dating is legitimate \u2014 a backfill shows up as asOf earlier than recordedAt."
|
|
12048
|
-
);
|
|
12049
|
-
}
|
|
12050
|
-
asOf = parsed;
|
|
12051
|
-
}
|
|
12052
|
-
try {
|
|
12053
|
-
const agentSessionId = getAgentSessionId();
|
|
12054
|
-
const receipt = await kernelMutation("outcomes.recordReading", {
|
|
12055
|
-
entryId,
|
|
12056
|
-
value,
|
|
12057
|
-
...asOf !== void 0 ? { asOf } : {},
|
|
12058
|
-
...opts.kind ? { kind: opts.kind } : {},
|
|
12059
|
-
...opts.correctsReadingId ? { correctsReadingId: opts.correctsReadingId } : {},
|
|
12060
|
-
...opts.recordedByRoleId ? { recordedByRoleId: opts.recordedByRoleId } : {},
|
|
12061
|
-
...opts.note ? { note: opts.note } : {},
|
|
12062
|
-
...opts.source ? { source: opts.source } : {},
|
|
12063
|
-
...opts.valueText ? { valueText: opts.valueText } : {},
|
|
12064
|
-
...agentSessionId ? { agentSessionId } : {}
|
|
12065
|
-
});
|
|
12066
|
-
const message = formatRecordReceipt(value, entryId, opts.valueText, receipt);
|
|
12067
|
-
return successResult(message, message, receipt);
|
|
12068
|
-
} catch (err) {
|
|
12069
|
-
return outcomeErrorResult(err, "record", entryId, { entryId, value, ...opts });
|
|
12070
|
-
}
|
|
12071
|
-
}
|
|
12072
|
-
async function handleOutcomeList(entryId, limit) {
|
|
12073
|
-
try {
|
|
12074
|
-
const result2 = await kernelQuery("outcomes.listReadings", {
|
|
12075
|
-
entryId,
|
|
12076
|
-
...limit !== void 0 ? { limit } : {}
|
|
12077
|
-
});
|
|
12078
|
-
const message = formatReadingsList(entryId, result2);
|
|
12079
|
-
return successResult(message, message, result2);
|
|
12080
|
-
} catch (err) {
|
|
12081
|
-
return outcomeErrorResult(err, "list", entryId, { entryId, limit });
|
|
12082
|
-
}
|
|
12083
|
-
}
|
|
12084
|
-
async function handleOutcomeShow(entryId) {
|
|
12085
|
-
try {
|
|
12086
|
-
const result2 = await kernelQuery("outcomes.showOutcome", { entryId });
|
|
12087
|
-
const message = formatOutcomeShow(result2);
|
|
12088
|
-
return successResult(message, message, result2);
|
|
12089
|
-
} catch (err) {
|
|
12090
|
-
return outcomeErrorResult(err, "show", entryId, { entryId });
|
|
12091
|
-
}
|
|
12092
|
-
}
|
|
12093
|
-
function registerOutcomeTools(server) {
|
|
12094
|
-
const outcomeHandlers = {
|
|
12095
|
-
record: (data) => handleOutcomeRecord(data.entryId, data.value, {
|
|
12096
|
-
valueText: data.valueText,
|
|
12097
|
-
asOf: data.asOf,
|
|
12098
|
-
kind: data.kind,
|
|
12099
|
-
correctsReadingId: data.correctsReadingId,
|
|
12100
|
-
recordedByRoleId: data.recordedByRoleId,
|
|
12101
|
-
note: data.note,
|
|
12102
|
-
source: data.source
|
|
12103
|
-
}),
|
|
12104
|
-
list: (data) => handleOutcomeList(data.entryId, data.limit),
|
|
12105
|
-
show: (data) => handleOutcomeShow(data.entryId)
|
|
12106
|
-
};
|
|
12107
|
-
server.registerTool(
|
|
12108
|
-
"outcome",
|
|
12109
|
-
{
|
|
12110
|
-
title: "Outcome",
|
|
12111
|
-
description: (
|
|
12112
|
-
// Chain IDs stay OUT of this user-facing string (check:chain-id-leaks) — same
|
|
12113
|
-
// precedent role.ts's own docblock names for its Team-Lead-vacancy sentence.
|
|
12114
|
-
"Key-result outcomes \u2014 record and read the measured readings behind a number. Three actions:\n\n- **record**: Record a reading \u2014 evidence, not a verdict; any connector may record one.\n- **list**: List readings, newest first; superseded rows are shown and marked with their replacement.\n- **show**: The derived view \u2014 current, progress, pace, staleness, recorded completion and its provenance, and any close proposal."
|
|
12115
|
-
),
|
|
12116
|
-
inputSchema: outcomeSchema,
|
|
12117
|
-
// Mixed read/write noun (same as shape's list/show read, agree/dismiss write): record
|
|
12118
|
-
// writes; list/show read.
|
|
12119
|
-
annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: false }
|
|
12120
|
-
},
|
|
12121
|
-
thinWrapper(async (args) => {
|
|
12122
|
-
const parsed = parseOrFail(outcomeSchema, args);
|
|
12123
|
-
if (!parsed.ok) return parsed.result;
|
|
12124
|
-
const { action } = parsed.data;
|
|
12125
|
-
return runWithToolContext(
|
|
12126
|
-
{ tool: "outcome", action },
|
|
12127
|
-
() => dispatchDiscriminated("outcome", outcomeActionUnion, parsed.data, OUTCOME_ACTION_SPECS, outcomeHandlers)
|
|
12128
|
-
);
|
|
12129
|
-
})
|
|
12130
|
-
);
|
|
12131
|
-
}
|
|
12132
|
-
|
|
12133
12164
|
// src/resources/index.ts
|
|
12134
12165
|
import { existsSync as existsSync3 } from "fs";
|
|
12135
12166
|
import { dirname, join, resolve as resolve4 } from "path";
|
|
@@ -12758,4 +12789,4 @@ export {
|
|
|
12758
12789
|
createProductBrainServer,
|
|
12759
12790
|
initFeatureFlags
|
|
12760
12791
|
};
|
|
12761
|
-
//# sourceMappingURL=chunk-
|
|
12792
|
+
//# sourceMappingURL=chunk-LPRJQOIQ.js.map
|