@useorgx/wizard 0.1.37 → 0.1.39
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.
- package/dist/cli.js +1923 -104
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import * as clack from "@clack/prompts";
|
|
5
5
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
6
|
-
import { readFileSync as
|
|
6
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
7
7
|
import { hostname } from "os";
|
|
8
|
-
import { resolve } from "path";
|
|
8
|
+
import { resolve as resolve2 } from "path";
|
|
9
9
|
import { Command } from "commander";
|
|
10
10
|
import pc3 from "picocolors";
|
|
11
11
|
|
|
@@ -795,7 +795,7 @@ function parsePairingPollResult(value) {
|
|
|
795
795
|
};
|
|
796
796
|
}
|
|
797
797
|
function sleep(ms) {
|
|
798
|
-
return new Promise((
|
|
798
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
799
799
|
}
|
|
800
800
|
async function startBrowserPairing(options, fetchImpl) {
|
|
801
801
|
const data = await fetchJson({
|
|
@@ -908,12 +908,12 @@ h1{font-size:1.5rem;color:#b91c1c}p{color:#555;margin-top:.5rem}</style>
|
|
|
908
908
|
<p>Return to your terminal and try again.</p>
|
|
909
909
|
</div></body></html>`;
|
|
910
910
|
function tryListen(port, hostname2) {
|
|
911
|
-
return new Promise((
|
|
911
|
+
return new Promise((resolve3, reject) => {
|
|
912
912
|
const server = createServer();
|
|
913
913
|
server.once("error", reject);
|
|
914
914
|
server.listen(port, hostname2, () => {
|
|
915
915
|
server.removeListener("error", reject);
|
|
916
|
-
|
|
916
|
+
resolve3(server);
|
|
917
917
|
});
|
|
918
918
|
});
|
|
919
919
|
}
|
|
@@ -942,7 +942,7 @@ async function startLocalAuthServer(options) {
|
|
|
942
942
|
const successHtml = options.successHtml ?? DEFAULT_SUCCESS_HTML;
|
|
943
943
|
const errorHtml = options.errorHtml ?? DEFAULT_ERROR_HTML;
|
|
944
944
|
const { server, port } = await bindServer(options.preferredPort, hostname2);
|
|
945
|
-
const result = new Promise((
|
|
945
|
+
const result = new Promise((resolve3, reject) => {
|
|
946
946
|
const timer = setTimeout(() => {
|
|
947
947
|
server.close();
|
|
948
948
|
reject(new Error("Timed out waiting for browser authorization."));
|
|
@@ -985,7 +985,7 @@ async function startLocalAuthServer(options) {
|
|
|
985
985
|
res.writeHead(200, { "Content-Type": "text/html" }).end(successHtml);
|
|
986
986
|
clearTimeout(timer);
|
|
987
987
|
server.close();
|
|
988
|
-
|
|
988
|
+
resolve3({ code, state });
|
|
989
989
|
});
|
|
990
990
|
});
|
|
991
991
|
return { port, result };
|
|
@@ -2569,10 +2569,10 @@ var EXTENSION_FRONTMATTER_DELIMITER = "---";
|
|
|
2569
2569
|
var CURSOR_RULES_CONTENT = `# OrgX Rules
|
|
2570
2570
|
|
|
2571
2571
|
- Prefer \`workspace_id\` on OrgX tool calls. \`command_center_id\` is a deprecated alias and should only be used for backwards compatibility. If both are present, they must match.
|
|
2572
|
-
- Treat \`
|
|
2573
|
-
- Treat \`
|
|
2572
|
+
- Treat \`orgx_act\` with \`force: true\` as an escape hatch. It bypasses hierarchy and proof checks, so only use it when the user explicitly wants that behavior and say why.
|
|
2573
|
+
- Treat \`orgx_write continue_on_error\` as best-effort creation. Use it only when partial scaffolds are acceptable, and follow up on any failed children.
|
|
2574
2574
|
- Preserve \`_context\` when widget or app-rendering flows depend on client, conversation, session, or user metadata. Do not strip or rename it.
|
|
2575
|
-
- Prefer \`
|
|
2575
|
+
- Prefer \`orgx_search\` for pending approvals and state inspection before reaching for legacy aliases.
|
|
2576
2576
|
- Keep hosted OrgX MCP calls distinct from local OpenClaw/plugin surfaces before mutating config or entity state.
|
|
2577
2577
|
- Artifact proof must use durable sources: GitHub PR/commit/blob permalinks, published/public URLs, or absolute file paths / \`file://...\`.
|
|
2578
2578
|
- Never use OrgX wrapper pages like \`/live/...\`, \`/artifacts/...\`, or \`/console/...\` as proof links. \`preview_markdown\` is supplemental, not proof.
|
|
@@ -2597,10 +2597,10 @@ This skill is for the hosted OrgX tool surface, not the local OpenClaw plugin. K
|
|
|
2597
2597
|
## Operating Rules
|
|
2598
2598
|
|
|
2599
2599
|
- Prefer \`workspace_id\` on OrgX tools. \`command_center_id\` is a deprecated alias kept for compatibility.
|
|
2600
|
-
- Treat \`
|
|
2601
|
-
- Treat \`
|
|
2600
|
+
- Treat \`orgx_act\` with \`force: true\` as a deliberate override only. It bypasses hierarchy and proof-chain checks.
|
|
2601
|
+
- Treat \`orgx_write continue_on_error\` as best-effort scaffolding. Use it only when partial creation is acceptable and inspect failures afterward.
|
|
2602
2602
|
- Preserve \`_context\` when widget or app rendering depends on client, conversation, session, or user metadata.
|
|
2603
|
-
- Prefer \`
|
|
2603
|
+
- Prefer \`orgx_search\` over older aliases when you need pending decisions, blockers, or entity state.
|
|
2604
2604
|
- Artifact proof must use durable sources: GitHub PR/commit/blob permalinks, published/public URLs, or absolute file paths / \`file://...\`.
|
|
2605
2605
|
- Never use OrgX wrapper pages like \`/live/...\`, \`/artifacts/...\`, or \`/console/...\` as proof links. \`preview_markdown\` is supporting context only.
|
|
2606
2606
|
|
|
@@ -2615,7 +2615,7 @@ Install and use these packs alongside this base skill:
|
|
|
2615
2615
|
|
|
2616
2616
|
## Suggested Workflow
|
|
2617
2617
|
|
|
2618
|
-
1. Inspect state with \`
|
|
2618
|
+
1. Inspect state with \`mcp__orgx__orgx_search\`, \`mcp__orgx__get_initiative_pulse\`, or the relevant workspace-scoped read tool.
|
|
2619
2619
|
2. Mutate state with the narrowest tool that matches the task.
|
|
2620
2620
|
3. When you need a hard override, explain why before using \`force: true\`.
|
|
2621
2621
|
4. When you scaffold, decide up front whether \`continue_on_error\` is acceptable.
|
|
@@ -3215,8 +3215,8 @@ function encodeRepoPath2(value) {
|
|
|
3215
3215
|
return value.split("/").filter((segment) => segment.length > 0).map((segment) => encodeURIComponent(segment)).join("/");
|
|
3216
3216
|
}
|
|
3217
3217
|
function isLikelyRepoFilePath(path) {
|
|
3218
|
-
const
|
|
3219
|
-
return
|
|
3218
|
+
const basename4 = path.split("/").pop() ?? path;
|
|
3219
|
+
return basename4.includes(".") && !/^\.[^./]+$/.test(basename4);
|
|
3220
3220
|
}
|
|
3221
3221
|
function buildContentsUrl2(spec, path) {
|
|
3222
3222
|
const encodedPath = encodeRepoPath2(path);
|
|
@@ -3550,7 +3550,7 @@ function formatCommandFailure(command, args, result) {
|
|
|
3550
3550
|
return `${command} ${args.join(" ")} failed${result.exitCode >= 0 ? ` with exit code ${result.exitCode}` : ""}${detail ? `: ${detail}` : "."}`;
|
|
3551
3551
|
}
|
|
3552
3552
|
async function defaultCommandRunner(command, args) {
|
|
3553
|
-
return await new Promise((
|
|
3553
|
+
return await new Promise((resolve3) => {
|
|
3554
3554
|
const child = spawn(command, [...args], {
|
|
3555
3555
|
env: process.env,
|
|
3556
3556
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -3565,7 +3565,7 @@ async function defaultCommandRunner(command, args) {
|
|
|
3565
3565
|
});
|
|
3566
3566
|
child.on("error", (error) => {
|
|
3567
3567
|
const errorCode = typeof error === "object" && error && "code" in error ? String(error.code) : void 0;
|
|
3568
|
-
|
|
3568
|
+
resolve3({
|
|
3569
3569
|
exitCode: -1,
|
|
3570
3570
|
stdout,
|
|
3571
3571
|
stderr,
|
|
@@ -3573,7 +3573,7 @@ async function defaultCommandRunner(command, args) {
|
|
|
3573
3573
|
});
|
|
3574
3574
|
});
|
|
3575
3575
|
child.on("close", (code) => {
|
|
3576
|
-
|
|
3576
|
+
resolve3({
|
|
3577
3577
|
exitCode: code ?? -1,
|
|
3578
3578
|
stdout,
|
|
3579
3579
|
stderr
|
|
@@ -6228,9 +6228,9 @@ var AI_SESSION_SOURCES = ["codex", "claude"];
|
|
|
6228
6228
|
var DEFAULT_LIMIT_PER_SOURCE = 3;
|
|
6229
6229
|
var DEFAULT_SINCE_DAYS = 30;
|
|
6230
6230
|
var DEFAULT_MAX_BYTES_PER_FILE = 1e6;
|
|
6231
|
-
var AUDIT_RELEVANT_LINE_PATTERN = /\b(decision|decided|artifact|receipt|proof|commitment|committed|next action|follow[- ]?up|outcome|result|impact|roi|economics|token|cost|saved|open loop|gap|blocker|risk|owner|dri|writeback|rollback|quality score|mcp|tool call|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|
|
|
6231
|
+
var AUDIT_RELEVANT_LINE_PATTERN = /\b(decision|decided|artifact|receipt|proof|commitment|committed|next action|follow[- ]?up|outcome|result|impact|roi|economics|token|cost|saved|open loop|gap|blocker|risk|owner|dri|writeback|rollback|quality score|mcp|tool call|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|orgx_write|mcp__orgx__)\b/i;
|
|
6232
6232
|
var STRONG_AUDIT_LINE_PATTERN = /^(?:[-*]\s*)?(?:decision|artifact|receipt|proof|commitment|next action|follow[- ]?up|outcome|result|impact|roi|economics|open loop|gap|blocker|risk|owner|dri|rollback|quality score)\s*:/i;
|
|
6233
|
-
var ORGX_TOOL_SIGNAL_PATTERN = /\b(?:mcp__orgx__|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|
|
|
6233
|
+
var ORGX_TOOL_SIGNAL_PATTERN = /\b(?:mcp__orgx__|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|orgx_write|orgx_inspect|ship_batch|record_outcome|orgx_free_audit)\b/i;
|
|
6234
6234
|
var INSTRUCTION_BOILERPLATE_PATTERN = /^(?:#{1,6}\s*)?(?:agents\.md|instructions?|codex guardrails|precedence|read before you write|use exactly what was specified|don'?t confuse technologies|repo \+ scope hygiene|initiative \/ mcp discipline|ui quality bar|verification standards|secrets \+ safety|patch\/editing rules|commit \/ pr \/ merge protocol|output style|mcp integration|agent domains|skills|conventions)\b/i;
|
|
6235
6235
|
var IMPERATIVE_BOILERPLATE_PATTERN = /^[-*]\s+(?:if the user|when the user|if mcp|when agents|never|always|do not|don'?t|default to|treat|produce|pick|verify|avoid|match|use exactly|keep system boundaries|quote bracketed|for orgx|when capture tooling|if no meaningful|do \*\*not\*\*)\b/i;
|
|
6236
6236
|
var CODE_OR_DOC_NOISE_PATTERN = /^(?:[-*]\s*)?(?:https?:\/\/|\/|\.{0,2}\/|[A-Za-z]:\/|`{1,3}|"{1,2}[A-Za-z0-9:_-]+":|\d+\s*$|\d+\t|import\s|export\s|const\s|let\s|var\s|function\s|type\s|interface\s|CREATE\s+TABLE|ALTER\s+TABLE|SELECT\s+|INSERT\s+|UPDATE\s+|DELETE\s+)/i;
|
|
@@ -6238,15 +6238,15 @@ var EMPTY_AUDIT_LABEL_PATTERN = /^(?:[-*]\s*)?(?:decision|artifact|receipt|proof
|
|
|
6238
6238
|
var LABEL_VALUE_NOISE_PATTERN = /^(?:[-*]\s*)?(?:decision|artifact|receipt|proof|commitment|next action|follow[- ]?up|outcome|result|impact|roi|economics|open loop|gap|blocker|risk|owner|dri|rollback|quality score)\s*:\s*(?:["']?[\w-]+["']?\s*\|\s*["']?[\w-]+["']?|[\d\s.,%$]+)[,;)]*$/i;
|
|
6239
6239
|
var TYPE_SIGNATURE_NOISE_PATTERN = /^(?:[-*]\s*)?(?:decision|artifact|receipt|proof|commitment|next action|follow[- ]?up|outcome|result|impact|roi|economics|open loop|gap|blocker|risk|owner|dri|rollback|quality score)\s*:\s*[A-Za-z_$][\w$]*(?:<[^>]+>)?[\s,;)]*$/i;
|
|
6240
6240
|
var TOOL_CATALOG_NOISE_PATTERN = /^(?:[-*]\s*)?(?:[a-z][\w.:-]*\s*\([^)]+\),?\s*){2,}$/i;
|
|
6241
|
-
var BARE_TOOL_SIGNAL_PATTERN = /^(?:\d+\.\s*|[-*]\s*)?(?:mcp__orgx__[\w-]*|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|
|
|
6242
|
-
var TOOL_QUESTION_NOISE_PATTERN = /^(?:\d+\.\s*)?\*\*[^*]+\*\*.*\?\s*(?:\([^)]*\b(?:mcp|
|
|
6241
|
+
var BARE_TOOL_SIGNAL_PATTERN = /^(?:\d+\.\s*|[-*]\s*)?(?:mcp__orgx__[\w-]*|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|orgx_write|orgx_inspect|ship_batch|record_outcome|orgx_free_audit)\s*$/i;
|
|
6242
|
+
var TOOL_QUESTION_NOISE_PATTERN = /^(?:\d+\.\s*)?\*\*[^*]+\*\*.*\?\s*(?:\([^)]*\b(?:mcp|orgx_write|start_plan_session)\b[^)]*\)\.?)?$/i;
|
|
6243
6243
|
var SOURCE_REFERENCE_NOISE_PATTERN = /(?:^|\s)(?:\.{0,2}\/)?(?:orgx|src|lib|workers|public|scripts|tests|apps|packages)\/[\w./-]+\.(?:ts|tsx|js|jsx|json|md|txt|sql|py)(?::\d+)?\b/i;
|
|
6244
6244
|
var FILE_REFERENCE_NOISE_PATTERN = /\b[\w.-]+\.(?:ts|tsx|js|jsx|json|md|txt|sql|py)(?::\d+(?:[–-]\d+)?)?\b/i;
|
|
6245
6245
|
var LOCAL_ASSET_REFERENCE_PATTERN = /(?:<BlogImage\b|source:\s*\/Users\/|\/blog\/[\w./-]+\.(?:png|jpg|jpeg|webp|gif))/i;
|
|
6246
6246
|
var LINE_NUMBER_SOURCE_NOISE_PATTERN = /^\d+(?::|\s+)\s*/i;
|
|
6247
|
-
var TOOL_WORKFLOW_NOISE_PATTERN = /(?:→|->).*\b(?:
|
|
6248
|
-
var TOOL_FAILURE_PATTERN = /^(?:\d+\.\s*)?(?:mcp__orgx__[\w-]*|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|
|
|
6249
|
-
var RUNTIME_FAILURE_PATTERN = /\b(?:mcp__orgx__[\w-]*|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|
|
|
6247
|
+
var TOOL_WORKFLOW_NOISE_PATTERN = /(?:→|->).*\b(?:orgx_write|orgx_spawn|record_outcome|submit_learning|orgx_recommend|mcp__orgx__)\b/i;
|
|
6248
|
+
var TOOL_FAILURE_PATTERN = /^(?:\d+\.\s*)?(?:mcp__orgx__[\w-]*|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|orgx_write|orgx_inspect|ship_batch|record_outcome|orgx_free_audit)\b.*\b(?:rejected|requires|failed|fails|error|invalid|unavailable|timeout|timed out|not\s+(?:called|dispatched|wired|created|available)|missing|broken)\b/i;
|
|
6249
|
+
var RUNTIME_FAILURE_PATTERN = /\b(?:mcp__orgx__[\w-]*|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|orgx_write|orgx_inspect|ship_batch|record_outcome|submit_learning|orgx_spawn|agent run)\b.*\b(?:rejected|requires|failed|fails|error|invalid|unavailable|timeout|timed out|never|no\s+\w+|not\s+(?:called|dispatched|wired|created|available|append)|missing|broken|only\s+in\s+agent\s+skill\s+prompts)\b/i;
|
|
6250
6250
|
var PROCESS_NARRATION_NOISE_PATTERN = /^(?:now i\b|let me\b|i (?:have|need|will|can)\b|i['’]ll\b|i['’]m\b|so\b.*\b(?:confirm|check|verify|fetches)\b)/i;
|
|
6251
6251
|
function parseAiSessionSources(value) {
|
|
6252
6252
|
if (!value?.trim()) return [];
|
|
@@ -6500,8 +6500,634 @@ function loadAiSessionImports(options) {
|
|
|
6500
6500
|
};
|
|
6501
6501
|
}
|
|
6502
6502
|
|
|
6503
|
-
// src/lib/
|
|
6503
|
+
// src/lib/work-graph-source-adapters.ts
|
|
6504
6504
|
import { createHash as createHash3 } from "crypto";
|
|
6505
|
+
import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
|
|
6506
|
+
import { homedir as homedir2 } from "os";
|
|
6507
|
+
import { basename as basename3, join as join5, resolve } from "path";
|
|
6508
|
+
var CLIENT_SOURCES = ["claude_code", "codex", "opencode", "goose", "cursor"];
|
|
6509
|
+
var DEFAULT_LIMIT_PER_SOURCE2 = 8;
|
|
6510
|
+
var DEFAULT_SINCE_DAYS2 = 45;
|
|
6511
|
+
var DEFAULT_MAX_BYTES_PER_FILE2 = 2e6;
|
|
6512
|
+
var WORK_SIGNAL_PATTERN = /\b(decision|decided|tradeoff|artifact|implemented|created|changed|edited|shipped|verified|test|proof|commit|blocked|blocker|failed|fails|error|timeout|permission|owner|handoff|mcp__|orgx_|tool call|schema|zod|next action|follow[- ]?up|initiative|agent|skill|recipe|workflow|customer|business|launch|deploy)\b/i;
|
|
6513
|
+
function parseInvestigationSourceList(value) {
|
|
6514
|
+
if (!value?.trim() || value.trim().toLowerCase() === "manual") return [];
|
|
6515
|
+
const requested = value.split(",").map((item) => item.trim().toLowerCase().replace(/-/g, "_")).filter(Boolean);
|
|
6516
|
+
const expanded = requested.includes("all") ? [...CLIENT_SOURCES] : requested.map((source) => source === "claude" ? "claude_code" : source);
|
|
6517
|
+
const deduped = [...new Set(expanded)];
|
|
6518
|
+
const invalid = deduped.filter((source) => !CLIENT_SOURCES.includes(source));
|
|
6519
|
+
if (invalid.length > 0) {
|
|
6520
|
+
throw new Error(
|
|
6521
|
+
`Unsupported investigation source: ${invalid.join(", ")}. Use claude, codex, opencode, goose, cursor, or all.`
|
|
6522
|
+
);
|
|
6523
|
+
}
|
|
6524
|
+
return deduped;
|
|
6525
|
+
}
|
|
6526
|
+
function hash(value, length = 24) {
|
|
6527
|
+
return createHash3("sha256").update(JSON.stringify(value)).digest("hex").slice(0, length);
|
|
6528
|
+
}
|
|
6529
|
+
function expandPath(path, env) {
|
|
6530
|
+
return path.replace(/^~(?=\/|$)/, env.home).replace(/\$CWD/g, env.cwd).replace(/\$HOME/g, env.home);
|
|
6531
|
+
}
|
|
6532
|
+
function safeStat(path) {
|
|
6533
|
+
try {
|
|
6534
|
+
return statSync4(path);
|
|
6535
|
+
} catch {
|
|
6536
|
+
return null;
|
|
6537
|
+
}
|
|
6538
|
+
}
|
|
6539
|
+
function walkFiles(root, predicate, maxFiles = 500) {
|
|
6540
|
+
if (!existsSync6(root)) return [];
|
|
6541
|
+
const files = [];
|
|
6542
|
+
const stack = [root];
|
|
6543
|
+
const ignored = /* @__PURE__ */ new Set(["node_modules", ".git", ".next", "dist", "build", ".turbo"]);
|
|
6544
|
+
while (stack.length > 0 && files.length < maxFiles) {
|
|
6545
|
+
const current = stack.pop();
|
|
6546
|
+
if (!current) continue;
|
|
6547
|
+
let entries;
|
|
6548
|
+
try {
|
|
6549
|
+
entries = readdirSync4(current);
|
|
6550
|
+
} catch {
|
|
6551
|
+
continue;
|
|
6552
|
+
}
|
|
6553
|
+
for (const entry of entries) {
|
|
6554
|
+
if (ignored.has(entry)) continue;
|
|
6555
|
+
const path = join5(current, entry);
|
|
6556
|
+
const stats = safeStat(path);
|
|
6557
|
+
if (!stats) continue;
|
|
6558
|
+
if (stats.isDirectory()) {
|
|
6559
|
+
stack.push(path);
|
|
6560
|
+
} else if (stats.isFile() && predicate(path)) {
|
|
6561
|
+
files.push(path);
|
|
6562
|
+
}
|
|
6563
|
+
}
|
|
6564
|
+
}
|
|
6565
|
+
return files;
|
|
6566
|
+
}
|
|
6567
|
+
function providerForClient(client) {
|
|
6568
|
+
if (client === "claude_code") return "anthropic";
|
|
6569
|
+
if (client === "codex") return "openai";
|
|
6570
|
+
return "unknown";
|
|
6571
|
+
}
|
|
6572
|
+
function workGraphSourceClient(client) {
|
|
6573
|
+
if (client === "claude_code") return "claude-code";
|
|
6574
|
+
return client;
|
|
6575
|
+
}
|
|
6576
|
+
function clientLabel(client) {
|
|
6577
|
+
switch (client) {
|
|
6578
|
+
case "claude_code":
|
|
6579
|
+
return "Claude Code sessions";
|
|
6580
|
+
case "codex":
|
|
6581
|
+
return "Codex sessions";
|
|
6582
|
+
case "opencode":
|
|
6583
|
+
return "OpenCode sessions";
|
|
6584
|
+
case "goose":
|
|
6585
|
+
return "goose sessions";
|
|
6586
|
+
case "cursor":
|
|
6587
|
+
return "Cursor workspace evidence";
|
|
6588
|
+
}
|
|
6589
|
+
}
|
|
6590
|
+
function redactedText(value, limit = 900) {
|
|
6591
|
+
return value.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, "[redacted-email]").replace(/\b(?:sk|oxk|ghp|gho|xox[baprs])_[A-Za-z0-9_-]{12,}\b/g, "[redacted-token]").replace(/\s+/g, " ").trim().slice(0, limit);
|
|
6592
|
+
}
|
|
6593
|
+
function nowWindow(timestamp, now) {
|
|
6594
|
+
const occurred = Date.parse(timestamp);
|
|
6595
|
+
if (!Number.isFinite(occurred)) return "older";
|
|
6596
|
+
const delta = now.getTime() - occurred;
|
|
6597
|
+
if (delta < 5 * 60 * 1e3) return "live";
|
|
6598
|
+
if (delta <= 24 * 60 * 60 * 1e3) return "recent_24h";
|
|
6599
|
+
if (delta <= 7 * 24 * 60 * 60 * 1e3) return "recent_7d";
|
|
6600
|
+
if (delta <= 30 * 24 * 60 * 60 * 1e3) return "recent_30d";
|
|
6601
|
+
return "older";
|
|
6602
|
+
}
|
|
6603
|
+
function makeRawEvent(input) {
|
|
6604
|
+
const contentHash = hash(input.payload, 64);
|
|
6605
|
+
const uri = `${input.client}:${input.sessionId}:${input.uriSuffix}`;
|
|
6606
|
+
return {
|
|
6607
|
+
event_id: `evt_${hash([uri, contentHash], 24)}`,
|
|
6608
|
+
source_ref: {
|
|
6609
|
+
source_id: input.client,
|
|
6610
|
+
uri,
|
|
6611
|
+
cite_url: null,
|
|
6612
|
+
resolves: true
|
|
6613
|
+
},
|
|
6614
|
+
source_id: input.client,
|
|
6615
|
+
provider: providerForClient(input.client),
|
|
6616
|
+
session_id: input.sessionId,
|
|
6617
|
+
project_id: null,
|
|
6618
|
+
timestamp: input.timestamp,
|
|
6619
|
+
occurred_in_window: nowWindow(input.timestamp, input.now),
|
|
6620
|
+
kind: input.kind,
|
|
6621
|
+
role: input.role,
|
|
6622
|
+
payload: input.payload,
|
|
6623
|
+
raw_byte_offset: input.rawByteOffset ?? null,
|
|
6624
|
+
raw_row_id: input.rawRowId ?? null,
|
|
6625
|
+
content_hash: contentHash,
|
|
6626
|
+
redaction_applied: true
|
|
6627
|
+
};
|
|
6628
|
+
}
|
|
6629
|
+
function parseJsonLine2(line) {
|
|
6630
|
+
try {
|
|
6631
|
+
return JSON.parse(line);
|
|
6632
|
+
} catch {
|
|
6633
|
+
return null;
|
|
6634
|
+
}
|
|
6635
|
+
}
|
|
6636
|
+
function asText2(value) {
|
|
6637
|
+
if (typeof value === "string") return value;
|
|
6638
|
+
if (Array.isArray(value)) {
|
|
6639
|
+
return value.map((item) => {
|
|
6640
|
+
if (typeof item === "string") return item;
|
|
6641
|
+
if (!isRecord(item)) return "";
|
|
6642
|
+
if (typeof item.text === "string") return item.text;
|
|
6643
|
+
if (typeof item.content === "string") return item.content;
|
|
6644
|
+
return "";
|
|
6645
|
+
}).filter(Boolean).join("\n");
|
|
6646
|
+
}
|
|
6647
|
+
if (isRecord(value)) {
|
|
6648
|
+
if (typeof value.text === "string") return value.text;
|
|
6649
|
+
if (typeof value.content === "string") return value.content;
|
|
6650
|
+
}
|
|
6651
|
+
return "";
|
|
6652
|
+
}
|
|
6653
|
+
function stringField(record, ...keys) {
|
|
6654
|
+
for (const key of keys) {
|
|
6655
|
+
const value = record[key];
|
|
6656
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
6657
|
+
}
|
|
6658
|
+
return null;
|
|
6659
|
+
}
|
|
6660
|
+
function timestampFor(record, statsMtime) {
|
|
6661
|
+
if (isRecord(record)) {
|
|
6662
|
+
const timestamp = stringField(record, "timestamp", "created_at", "createdAt", "created", "time");
|
|
6663
|
+
if (timestamp && Number.isFinite(Date.parse(timestamp))) return new Date(timestamp).toISOString();
|
|
6664
|
+
const numeric = record.timestamp ?? record.created_at ?? record.created;
|
|
6665
|
+
if (typeof numeric === "number" && Number.isFinite(numeric)) {
|
|
6666
|
+
return new Date(numeric > 1e10 ? numeric : numeric * 1e3).toISOString();
|
|
6667
|
+
}
|
|
6668
|
+
}
|
|
6669
|
+
return new Date(statsMtime).toISOString();
|
|
6670
|
+
}
|
|
6671
|
+
function mapCodexRecord(record, fallbackTimestamp) {
|
|
6672
|
+
if (!isRecord(record)) return [];
|
|
6673
|
+
const timestamp = timestampFor(record, Date.parse(fallbackTimestamp));
|
|
6674
|
+
if (record.type === "response_item" && isRecord(record.payload)) {
|
|
6675
|
+
const payload = record.payload;
|
|
6676
|
+
if (payload.type === "message" && (payload.role === "user" || payload.role === "assistant")) {
|
|
6677
|
+
return [{
|
|
6678
|
+
kind: payload.role === "user" ? "user_prompt" : "assistant_text",
|
|
6679
|
+
role: payload.role,
|
|
6680
|
+
text: asText2(payload.content),
|
|
6681
|
+
timestamp
|
|
6682
|
+
}];
|
|
6683
|
+
}
|
|
6684
|
+
if (payload.type === "function_call") {
|
|
6685
|
+
const toolName = stringField(payload, "name", "tool_name") ?? "unknown_tool";
|
|
6686
|
+
return [{
|
|
6687
|
+
kind: toolName.startsWith("mcp__") ? "mcp_tool_call" : "tool_call_start",
|
|
6688
|
+
role: "tool",
|
|
6689
|
+
text: redactedText(JSON.stringify(payload.arguments ?? payload)),
|
|
6690
|
+
toolName,
|
|
6691
|
+
timestamp
|
|
6692
|
+
}];
|
|
6693
|
+
}
|
|
6694
|
+
if (payload.type === "function_call_output") {
|
|
6695
|
+
const text2 = asText2(payload.output) || redactedText(JSON.stringify(payload.output ?? payload));
|
|
6696
|
+
return [{
|
|
6697
|
+
kind: /\berror|failed|exception\b/i.test(text2) ? "tool_call_error" : "tool_call_result",
|
|
6698
|
+
role: "tool",
|
|
6699
|
+
text: text2,
|
|
6700
|
+
timestamp
|
|
6701
|
+
}];
|
|
6702
|
+
}
|
|
6703
|
+
if (payload.type === "reasoning") {
|
|
6704
|
+
return [{ kind: "assistant_reasoning", role: "assistant", text: asText2(payload.content), timestamp }];
|
|
6705
|
+
}
|
|
6706
|
+
}
|
|
6707
|
+
if (record.type === "event_msg" && isRecord(record.payload) && typeof record.payload.message === "string") {
|
|
6708
|
+
return [{ kind: "assistant_text", role: "meta", text: record.payload.message, timestamp }];
|
|
6709
|
+
}
|
|
6710
|
+
return [];
|
|
6711
|
+
}
|
|
6712
|
+
function mapClaudeRecord(record, fallbackTimestamp) {
|
|
6713
|
+
if (!isRecord(record)) return [];
|
|
6714
|
+
const timestamp = timestampFor(record, Date.parse(fallbackTimestamp));
|
|
6715
|
+
const message = isRecord(record.message) ? record.message : record;
|
|
6716
|
+
const role = message.role === "user" || message.role === "assistant" ? message.role : "meta";
|
|
6717
|
+
const content = message.content;
|
|
6718
|
+
const out = [];
|
|
6719
|
+
if (Array.isArray(content)) {
|
|
6720
|
+
for (const [index, part] of content.entries()) {
|
|
6721
|
+
if (!isRecord(part)) continue;
|
|
6722
|
+
if (part.type === "text" || typeof part.text === "string") {
|
|
6723
|
+
out.push({ kind: role === "user" ? "user_prompt" : "assistant_text", role, text: asText2(part), timestamp });
|
|
6724
|
+
} else if (part.type === "thinking") {
|
|
6725
|
+
out.push({ kind: "assistant_reasoning", role: "assistant", text: asText2(part), timestamp });
|
|
6726
|
+
} else if (part.type === "tool_use") {
|
|
6727
|
+
const toolName = stringField(part, "name") ?? `tool_${index}`;
|
|
6728
|
+
out.push({
|
|
6729
|
+
kind: toolName.startsWith("mcp__") ? "mcp_tool_call" : "tool_call_start",
|
|
6730
|
+
role: "tool",
|
|
6731
|
+
text: redactedText(JSON.stringify(part.input ?? part)),
|
|
6732
|
+
toolName,
|
|
6733
|
+
timestamp
|
|
6734
|
+
});
|
|
6735
|
+
} else if (part.type === "tool_result") {
|
|
6736
|
+
const text3 = asText2(part.content) || redactedText(JSON.stringify(part.content ?? part));
|
|
6737
|
+
out.push({ kind: part.is_error === true ? "tool_call_error" : "tool_call_result", role: "tool", text: text3, timestamp });
|
|
6738
|
+
}
|
|
6739
|
+
}
|
|
6740
|
+
return out;
|
|
6741
|
+
}
|
|
6742
|
+
const text2 = asText2(content);
|
|
6743
|
+
if (text2) out.push({ kind: role === "user" ? "user_prompt" : "assistant_text", role, text: text2, timestamp });
|
|
6744
|
+
return out;
|
|
6745
|
+
}
|
|
6746
|
+
function readJsonlCandidate(candidate, options) {
|
|
6747
|
+
const stats = safeStat(candidate.path);
|
|
6748
|
+
if (!stats || stats.size > options.maxBytesPerFile) {
|
|
6749
|
+
return {
|
|
6750
|
+
events: [],
|
|
6751
|
+
filesRead: 0,
|
|
6752
|
+
filesSkipped: [{ path: candidate.path, reason: stats ? "schema_version_unsupported" : "permission_denied" }],
|
|
6753
|
+
notes: [],
|
|
6754
|
+
searchedSessions: 0
|
|
6755
|
+
};
|
|
6756
|
+
}
|
|
6757
|
+
const lines = readFileSync4(candidate.path, "utf8").split(/\r?\n/);
|
|
6758
|
+
const fallbackTimestamp = new Date(stats.mtimeMs).toISOString();
|
|
6759
|
+
const sessionId = basename3(candidate.path).replace(/\.[^.]+$/, "");
|
|
6760
|
+
const events = [];
|
|
6761
|
+
for (const [index, line] of lines.entries()) {
|
|
6762
|
+
if (!line.trim()) continue;
|
|
6763
|
+
const record = parseJsonLine2(line);
|
|
6764
|
+
const mapped = candidate.source === "codex" ? mapCodexRecord(record, fallbackTimestamp) : candidate.source === "claude_code" ? mapClaudeRecord(record, fallbackTimestamp) : mapGenericJsonRecord(record, fallbackTimestamp);
|
|
6765
|
+
for (const [partIndex, item] of mapped.entries()) {
|
|
6766
|
+
if (!item.text && !item.toolName) continue;
|
|
6767
|
+
events.push(makeRawEvent({
|
|
6768
|
+
client: candidate.source,
|
|
6769
|
+
kind: item.kind,
|
|
6770
|
+
now: options.now,
|
|
6771
|
+
path: candidate.path,
|
|
6772
|
+
payload: {
|
|
6773
|
+
extraction_mode: candidate.extractionMode,
|
|
6774
|
+
relative_source_path: candidate.path,
|
|
6775
|
+
text_summary: redactedText(item.text),
|
|
6776
|
+
tool_name: item.toolName
|
|
6777
|
+
},
|
|
6778
|
+
rawByteOffset: index,
|
|
6779
|
+
role: item.role,
|
|
6780
|
+
sessionId,
|
|
6781
|
+
timestamp: item.timestamp,
|
|
6782
|
+
uriSuffix: `line:${index}:part:${partIndex}`
|
|
6783
|
+
}));
|
|
6784
|
+
}
|
|
6785
|
+
}
|
|
6786
|
+
return {
|
|
6787
|
+
events,
|
|
6788
|
+
filesRead: 1,
|
|
6789
|
+
filesSkipped: [],
|
|
6790
|
+
notes: [],
|
|
6791
|
+
searchedSessions: 1
|
|
6792
|
+
};
|
|
6793
|
+
}
|
|
6794
|
+
function mapGenericJsonRecord(record, fallbackTimestamp) {
|
|
6795
|
+
if (!isRecord(record)) return [];
|
|
6796
|
+
const timestamp = timestampFor(record, Date.parse(fallbackTimestamp));
|
|
6797
|
+
const roleValue = record.role === "user" || record.role === "assistant" ? record.role : "meta";
|
|
6798
|
+
const toolName = stringField(record, "tool_name", "toolName", "name");
|
|
6799
|
+
if (toolName) {
|
|
6800
|
+
const text3 = asText2(record.response) || asText2(record.output) || redactedText(JSON.stringify(record));
|
|
6801
|
+
return [{
|
|
6802
|
+
kind: toolName.startsWith("mcp__") ? "mcp_tool_call" : record.success === false ? "tool_call_error" : "tool_call_start",
|
|
6803
|
+
role: "tool",
|
|
6804
|
+
text: text3,
|
|
6805
|
+
toolName,
|
|
6806
|
+
timestamp
|
|
6807
|
+
}];
|
|
6808
|
+
}
|
|
6809
|
+
const text2 = asText2(record.content) || asText2(record.message) || asText2(record.text);
|
|
6810
|
+
if (!text2) return [];
|
|
6811
|
+
return [{
|
|
6812
|
+
kind: roleValue === "user" ? "user_prompt" : "assistant_text",
|
|
6813
|
+
role: roleValue,
|
|
6814
|
+
text: text2,
|
|
6815
|
+
timestamp
|
|
6816
|
+
}];
|
|
6817
|
+
}
|
|
6818
|
+
function readJsonCandidate(candidate, options) {
|
|
6819
|
+
const stats = safeStat(candidate.path);
|
|
6820
|
+
if (!stats || stats.size > options.maxBytesPerFile) {
|
|
6821
|
+
return {
|
|
6822
|
+
events: [],
|
|
6823
|
+
filesRead: 0,
|
|
6824
|
+
filesSkipped: [{ path: candidate.path, reason: stats ? "schema_version_unsupported" : "permission_denied" }],
|
|
6825
|
+
notes: [],
|
|
6826
|
+
searchedSessions: 0
|
|
6827
|
+
};
|
|
6828
|
+
}
|
|
6829
|
+
let parsed;
|
|
6830
|
+
try {
|
|
6831
|
+
parsed = JSON.parse(readFileSync4(candidate.path, "utf8"));
|
|
6832
|
+
} catch {
|
|
6833
|
+
return {
|
|
6834
|
+
events: [],
|
|
6835
|
+
filesRead: 0,
|
|
6836
|
+
filesSkipped: [{ path: candidate.path, reason: "binary_or_corrupt" }],
|
|
6837
|
+
notes: [],
|
|
6838
|
+
searchedSessions: 0
|
|
6839
|
+
};
|
|
6840
|
+
}
|
|
6841
|
+
const records = flattenPotentialMessages(parsed).slice(0, 800);
|
|
6842
|
+
const fallbackTimestamp = new Date(stats.mtimeMs).toISOString();
|
|
6843
|
+
const sessionId = basename3(candidate.path).replace(/\.[^.]+$/, "");
|
|
6844
|
+
const events = records.flatMap(
|
|
6845
|
+
(record, index) => mapGenericJsonRecord(record, fallbackTimestamp).map(
|
|
6846
|
+
(item, partIndex) => makeRawEvent({
|
|
6847
|
+
client: candidate.source,
|
|
6848
|
+
kind: item.kind,
|
|
6849
|
+
now: options.now,
|
|
6850
|
+
path: candidate.path,
|
|
6851
|
+
payload: {
|
|
6852
|
+
extraction_mode: candidate.extractionMode,
|
|
6853
|
+
relative_source_path: candidate.path,
|
|
6854
|
+
text_summary: redactedText(item.text),
|
|
6855
|
+
tool_name: item.toolName
|
|
6856
|
+
},
|
|
6857
|
+
rawRowId: String(index),
|
|
6858
|
+
role: item.role,
|
|
6859
|
+
sessionId,
|
|
6860
|
+
timestamp: item.timestamp,
|
|
6861
|
+
uriSuffix: `json:${index}:part:${partIndex}`
|
|
6862
|
+
})
|
|
6863
|
+
)
|
|
6864
|
+
);
|
|
6865
|
+
return {
|
|
6866
|
+
events,
|
|
6867
|
+
filesRead: 1,
|
|
6868
|
+
filesSkipped: [],
|
|
6869
|
+
notes: [],
|
|
6870
|
+
searchedSessions: 1
|
|
6871
|
+
};
|
|
6872
|
+
}
|
|
6873
|
+
function flattenPotentialMessages(value) {
|
|
6874
|
+
const out = [];
|
|
6875
|
+
const visit = (item, depth) => {
|
|
6876
|
+
if (depth > 8 || out.length >= 1e3) return;
|
|
6877
|
+
if (Array.isArray(item)) {
|
|
6878
|
+
for (const child of item) visit(child, depth + 1);
|
|
6879
|
+
return;
|
|
6880
|
+
}
|
|
6881
|
+
if (!isRecord(item)) return;
|
|
6882
|
+
if (typeof item.role === "string" || typeof item.content === "string" || typeof item.text === "string" || typeof item.tool_name === "string" || typeof item.toolName === "string") {
|
|
6883
|
+
out.push(item);
|
|
6884
|
+
}
|
|
6885
|
+
for (const value2 of Object.values(item)) {
|
|
6886
|
+
if (Array.isArray(value2) || isRecord(value2)) visit(value2, depth + 1);
|
|
6887
|
+
}
|
|
6888
|
+
};
|
|
6889
|
+
visit(value, 0);
|
|
6890
|
+
return out;
|
|
6891
|
+
}
|
|
6892
|
+
function readMarkdownCandidate(candidate, options) {
|
|
6893
|
+
const stats = safeStat(candidate.path);
|
|
6894
|
+
if (!stats || stats.size > options.maxBytesPerFile) {
|
|
6895
|
+
return {
|
|
6896
|
+
events: [],
|
|
6897
|
+
filesRead: 0,
|
|
6898
|
+
filesSkipped: [{ path: candidate.path, reason: stats ? "schema_version_unsupported" : "permission_denied" }],
|
|
6899
|
+
notes: [],
|
|
6900
|
+
searchedSessions: 0
|
|
6901
|
+
};
|
|
6902
|
+
}
|
|
6903
|
+
const text2 = readFileSync4(candidate.path, "utf8");
|
|
6904
|
+
const sessionId = basename3(candidate.path).replace(/\.[^.]+$/, "");
|
|
6905
|
+
const timestamp = new Date(stats.mtimeMs).toISOString();
|
|
6906
|
+
const event = makeRawEvent({
|
|
6907
|
+
client: candidate.source,
|
|
6908
|
+
kind: candidate.path.includes(".cursor/rules") || candidate.path.endsWith(".cursorrules") ? "session_start" : "assistant_text",
|
|
6909
|
+
now: options.now,
|
|
6910
|
+
path: candidate.path,
|
|
6911
|
+
payload: {
|
|
6912
|
+
extraction_mode: candidate.extractionMode,
|
|
6913
|
+
relative_source_path: candidate.path,
|
|
6914
|
+
text_summary: redactedText(text2, 1200),
|
|
6915
|
+
tool_usage_state: candidate.path.includes("mcp.json") ? "configured" : void 0
|
|
6916
|
+
},
|
|
6917
|
+
role: "meta",
|
|
6918
|
+
sessionId,
|
|
6919
|
+
timestamp,
|
|
6920
|
+
uriSuffix: "markdown:0"
|
|
6921
|
+
});
|
|
6922
|
+
return {
|
|
6923
|
+
events: [event],
|
|
6924
|
+
filesRead: 1,
|
|
6925
|
+
filesSkipped: [],
|
|
6926
|
+
notes: candidate.extractionMode === "specstory" ? ["SpecStory evidence is repo-grounded and version-stable."] : [],
|
|
6927
|
+
searchedSessions: 1
|
|
6928
|
+
};
|
|
6929
|
+
}
|
|
6930
|
+
function discoverCandidates(source, env, sinceMs) {
|
|
6931
|
+
const candidates = [];
|
|
6932
|
+
const addFiles = (paths, extractionMode, predicate) => {
|
|
6933
|
+
for (const rootPattern of paths) {
|
|
6934
|
+
const expanded = expandPath(rootPattern, env);
|
|
6935
|
+
const root = expanded.includes("*") ? expanded.slice(0, expanded.indexOf("*")).replace(/\/$/, "") : expanded;
|
|
6936
|
+
const exactStats = safeStat(expanded);
|
|
6937
|
+
const found = exactStats?.isFile() ? [expanded] : walkFiles(root, predicate);
|
|
6938
|
+
for (const path of found) {
|
|
6939
|
+
const stats = safeStat(path);
|
|
6940
|
+
if (!stats || stats.mtimeMs < sinceMs) continue;
|
|
6941
|
+
candidates.push({ extractionMode, mtimeMs: stats.mtimeMs, path, source });
|
|
6942
|
+
}
|
|
6943
|
+
}
|
|
6944
|
+
};
|
|
6945
|
+
if (source === "codex") {
|
|
6946
|
+
addFiles([CODEX_SESSIONS_DIR], "jsonl", (path) => path.endsWith(".jsonl"));
|
|
6947
|
+
} else if (source === "claude_code") {
|
|
6948
|
+
addFiles([CLAUDE_PROJECTS_DIR], "jsonl", (path) => path.endsWith(".jsonl"));
|
|
6949
|
+
} else if (source === "opencode") {
|
|
6950
|
+
addFiles([
|
|
6951
|
+
"~/.local/share/opencode/storage/session",
|
|
6952
|
+
"~/Library/Application Support/opencode/storage/session"
|
|
6953
|
+
], "json", (path) => path.endsWith(".json"));
|
|
6954
|
+
addFiles([
|
|
6955
|
+
"~/.local/share/opencode/storage/db.sqlite",
|
|
6956
|
+
"~/Library/Application Support/opencode/storage/db.sqlite"
|
|
6957
|
+
], "sqlite", (path) => path.endsWith(".sqlite") || path.endsWith(".db"));
|
|
6958
|
+
} else if (source === "goose") {
|
|
6959
|
+
addFiles(["~/.local/share/goose/sessions"], "jsonl", (path) => path.endsWith(".jsonl"));
|
|
6960
|
+
addFiles([
|
|
6961
|
+
"~/.local/share/goose/logs",
|
|
6962
|
+
"~/.local/share/goose/data/sessions/sessions.db"
|
|
6963
|
+
], "sqlite", (path) => path.endsWith(".db") || /llm_request\.\d+\.jsonl$/.test(path));
|
|
6964
|
+
} else if (source === "cursor") {
|
|
6965
|
+
addFiles(
|
|
6966
|
+
[
|
|
6967
|
+
"$CWD/.specstory/history",
|
|
6968
|
+
"$CWD/.cursor/rules",
|
|
6969
|
+
"$CWD/.cursorrules",
|
|
6970
|
+
"$CWD/.cursor/mcp.json"
|
|
6971
|
+
],
|
|
6972
|
+
"specstory",
|
|
6973
|
+
(path) => path.endsWith(".md") || path.endsWith(".mdc") || path.endsWith(".json") || path.endsWith(".cursorrules")
|
|
6974
|
+
);
|
|
6975
|
+
addFiles([
|
|
6976
|
+
"~/Library/Application Support/Cursor/User/workspaceStorage",
|
|
6977
|
+
"~/.config/Cursor/User/workspaceStorage"
|
|
6978
|
+
], "sqlite", (path) => path.endsWith("state.vscdb"));
|
|
6979
|
+
}
|
|
6980
|
+
return candidates.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
6981
|
+
}
|
|
6982
|
+
function discoverOverrideCandidates(source, root, sinceMs) {
|
|
6983
|
+
const extractionMode = root.endsWith(".json") ? "json" : "jsonl";
|
|
6984
|
+
const files = walkFiles(root, (path) => path.endsWith(".jsonl") || path.endsWith(".json"));
|
|
6985
|
+
const candidates = [];
|
|
6986
|
+
for (const path of files) {
|
|
6987
|
+
const stats = safeStat(path);
|
|
6988
|
+
if (!stats || stats.mtimeMs < sinceMs) continue;
|
|
6989
|
+
candidates.push({ extractionMode, mtimeMs: stats.mtimeMs, path, source });
|
|
6990
|
+
}
|
|
6991
|
+
return candidates.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
6992
|
+
}
|
|
6993
|
+
function findingTypeFromEvent(event) {
|
|
6994
|
+
const text2 = `${event.payload.text_summary ?? ""}
|
|
6995
|
+
${event.payload.tool_name ?? ""}`;
|
|
6996
|
+
if (!WORK_SIGNAL_PATTERN.test(text2)) return null;
|
|
6997
|
+
if (/\b(decision|decided|tradeoff|architecture|approval)\b/i.test(text2)) return "decision";
|
|
6998
|
+
if (/\b(blocked|blocker|failed|fails|error|timeout|permission|schema|zod|invalid)\b/i.test(text2)) return "blocker";
|
|
6999
|
+
if (/\b(artifact|implemented|created|changed|edited|commit|pr|file|shipped|deploy)\b/i.test(text2)) return "artifact";
|
|
7000
|
+
if (/\b(test|verified|proof|outcome|result)\b/i.test(text2)) return "outcome";
|
|
7001
|
+
if (/\b(customer|business|revenue|deal|buyer)\b/i.test(text2)) return "business";
|
|
7002
|
+
if (/\b(agent|skill|recipe|tool|mcp__|orgx_)\b/i.test(text2)) return "missed_orchestration_opportunity";
|
|
7003
|
+
return "action";
|
|
7004
|
+
}
|
|
7005
|
+
function titleFromEvent(event) {
|
|
7006
|
+
const text2 = redactedText(String(event.payload.text_summary ?? event.payload.tool_name ?? "AI-client work signal"), 240);
|
|
7007
|
+
const first = text2.replace(/^(decision|artifact|blocker|proof|next action|outcome)\s*:\s*/i, "").split(/[.!?]\s/)[0]?.trim();
|
|
7008
|
+
return (first || `${event.source_id} work signal`).slice(0, 110);
|
|
7009
|
+
}
|
|
7010
|
+
function extractionFromEvents(input) {
|
|
7011
|
+
const findings = [];
|
|
7012
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7013
|
+
for (const event of input.events) {
|
|
7014
|
+
const type = findingTypeFromEvent(event);
|
|
7015
|
+
if (!type) continue;
|
|
7016
|
+
const dedupe = `${type}:${titleFromEvent(event).toLowerCase()}`;
|
|
7017
|
+
if (seen.has(dedupe)) continue;
|
|
7018
|
+
seen.add(dedupe);
|
|
7019
|
+
findings.push({
|
|
7020
|
+
type,
|
|
7021
|
+
title: titleFromEvent(event),
|
|
7022
|
+
summary: type === "missed_orchestration_opportunity" && Number(event.payload.tool_name ? 1 : 0) === 0 ? "The client evidence mentions agent/tool workflow but does not prove an invocation event." : redactedText(String(event.payload.text_summary ?? "Client work signal"), 260),
|
|
7023
|
+
source_client: workGraphSourceClient(input.client),
|
|
7024
|
+
source_id: event.session_id,
|
|
7025
|
+
source_label: clientLabel(input.client),
|
|
7026
|
+
evidence_ref: event.source_ref.uri,
|
|
7027
|
+
confidence: event.kind === "mcp_tool_call" || event.kind === "tool_call_start" ? 0.82 : 0.68,
|
|
7028
|
+
occurred_at: event.timestamp,
|
|
7029
|
+
redacted_verbatim: redactedText(String(event.payload.text_summary ?? ""), 360),
|
|
7030
|
+
privacy_state: "redacted",
|
|
7031
|
+
metadata: {
|
|
7032
|
+
event_id: event.event_id,
|
|
7033
|
+
event_kind: event.kind,
|
|
7034
|
+
extraction_mode: event.payload.extraction_mode,
|
|
7035
|
+
provider: event.provider,
|
|
7036
|
+
tool_name: event.payload.tool_name
|
|
7037
|
+
}
|
|
7038
|
+
});
|
|
7039
|
+
if (findings.length >= 50) break;
|
|
7040
|
+
}
|
|
7041
|
+
return {
|
|
7042
|
+
schema_version: "2.0.0.investigation",
|
|
7043
|
+
extraction_id: `${input.client}:investigation:${hash([input.client, input.events.map((event) => event.event_id)], 12)}`,
|
|
7044
|
+
source_client: workGraphSourceClient(input.client),
|
|
7045
|
+
source_label: clientLabel(input.client),
|
|
7046
|
+
searched_sources: [...new Set(input.events.map((event) => String(event.payload.relative_source_path ?? event.session_id)))].slice(0, 30),
|
|
7047
|
+
search_queries: [
|
|
7048
|
+
{
|
|
7049
|
+
id: "full_session_inventory",
|
|
7050
|
+
lens: "Full-session deterministic inventory",
|
|
7051
|
+
query: "Read messages, tool calls, commands, configs, and repo-grounded session artifacts before deriving loop candidates.",
|
|
7052
|
+
result_count: input.events.length
|
|
7053
|
+
}
|
|
7054
|
+
],
|
|
7055
|
+
extraction_quality: {
|
|
7056
|
+
confidence: findings.length > 0 ? 0.74 : input.filesRead > 0 ? 0.32 : 0.18,
|
|
7057
|
+
searched_session_count: Math.max(input.filesRead, new Set(input.events.map((event) => event.session_id)).size),
|
|
7058
|
+
skipped_session_count: input.filesSkipped.length,
|
|
7059
|
+
notes: [
|
|
7060
|
+
...input.notes,
|
|
7061
|
+
`${input.events.length} normalized raw events; ${findings.length} public-safe loop candidates.`,
|
|
7062
|
+
...input.filesSkipped.map((file) => `Skipped ${file.path}: ${file.reason}`)
|
|
7063
|
+
]
|
|
7064
|
+
},
|
|
7065
|
+
findings
|
|
7066
|
+
};
|
|
7067
|
+
}
|
|
7068
|
+
function loadWorkGraphInvestigationSourceData(options) {
|
|
7069
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
7070
|
+
const env = {
|
|
7071
|
+
cwd: options.cwd ? resolve(options.cwd) : process.cwd(),
|
|
7072
|
+
home: options.home ?? homedir2()
|
|
7073
|
+
};
|
|
7074
|
+
const sinceMs = now.getTime() - (options.sinceDays ?? DEFAULT_SINCE_DAYS2) * 24 * 60 * 60 * 1e3;
|
|
7075
|
+
const limit = Math.max(1, options.limitPerSource ?? DEFAULT_LIMIT_PER_SOURCE2);
|
|
7076
|
+
const maxBytesPerFile = Math.max(1, options.maxBytesPerFile ?? DEFAULT_MAX_BYTES_PER_FILE2);
|
|
7077
|
+
const rawEvents = [];
|
|
7078
|
+
const clientExtractions = [];
|
|
7079
|
+
const connectedSources = [];
|
|
7080
|
+
const missingSources = [];
|
|
7081
|
+
const sourceOverrides = /* @__PURE__ */ new Map();
|
|
7082
|
+
if (options.codexSessionsDir) sourceOverrides.set("codex", resolve(options.codexSessionsDir));
|
|
7083
|
+
if (options.claudeProjectsDir) sourceOverrides.set("claude_code", resolve(options.claudeProjectsDir));
|
|
7084
|
+
for (const source of options.sources) {
|
|
7085
|
+
const overrideRoot = sourceOverrides.get(source);
|
|
7086
|
+
const candidates = (overrideRoot ? discoverOverrideCandidates(source, overrideRoot, sinceMs) : discoverCandidates(source, env, sinceMs)).slice(0, limit);
|
|
7087
|
+
if (candidates.length === 0) {
|
|
7088
|
+
missingSources.push(`${clientLabel(source)} store`);
|
|
7089
|
+
continue;
|
|
7090
|
+
}
|
|
7091
|
+
const sourceEvents = [];
|
|
7092
|
+
const filesSkipped = [];
|
|
7093
|
+
let filesRead = 0;
|
|
7094
|
+
const notes = [];
|
|
7095
|
+
for (const candidate of candidates) {
|
|
7096
|
+
if (candidate.extractionMode === "sqlite") {
|
|
7097
|
+
filesSkipped.push({ path: candidate.path, reason: "schema_version_unsupported" });
|
|
7098
|
+
notes.push(`${candidate.path} detected; SQLite extraction is reserved for the cloud/runtime adapter reader.`);
|
|
7099
|
+
continue;
|
|
7100
|
+
}
|
|
7101
|
+
const result = candidate.path.endsWith(".jsonl") ? readJsonlCandidate(candidate, { maxBytesPerFile, now }) : candidate.path.endsWith(".json") && !candidate.path.endsWith("mcp.json") ? readJsonCandidate(candidate, { maxBytesPerFile, now }) : readMarkdownCandidate(candidate, { maxBytesPerFile, now });
|
|
7102
|
+
sourceEvents.push(...result.events);
|
|
7103
|
+
filesRead += result.filesRead;
|
|
7104
|
+
filesSkipped.push(...result.filesSkipped);
|
|
7105
|
+
notes.push(...result.notes);
|
|
7106
|
+
}
|
|
7107
|
+
rawEvents.push(...sourceEvents);
|
|
7108
|
+
clientExtractions.push(extractionFromEvents({
|
|
7109
|
+
client: source,
|
|
7110
|
+
events: sourceEvents,
|
|
7111
|
+
filesRead,
|
|
7112
|
+
filesSkipped,
|
|
7113
|
+
notes
|
|
7114
|
+
}));
|
|
7115
|
+
if (sourceEvents.length > 0 || filesRead > 0) {
|
|
7116
|
+
connectedSources.push(clientLabel(source));
|
|
7117
|
+
} else {
|
|
7118
|
+
missingSources.push(`${clientLabel(source)} readable events`);
|
|
7119
|
+
}
|
|
7120
|
+
}
|
|
7121
|
+
return {
|
|
7122
|
+
clientExtractions,
|
|
7123
|
+
connectedSources: [...new Set(connectedSources)],
|
|
7124
|
+
missingSources: [...new Set(missingSources)],
|
|
7125
|
+
rawEvents
|
|
7126
|
+
};
|
|
7127
|
+
}
|
|
7128
|
+
|
|
7129
|
+
// src/lib/self-audit.ts
|
|
7130
|
+
import { createHash as createHash4 } from "crypto";
|
|
6505
7131
|
var SELF_AUDIT_SCHEMA_VERSION = "2026-04-27";
|
|
6506
7132
|
var AUDIT_DIMENSIONS = [
|
|
6507
7133
|
"queryability",
|
|
@@ -6668,7 +7294,7 @@ function buildSelfCritique(scores) {
|
|
|
6668
7294
|
});
|
|
6669
7295
|
}
|
|
6670
7296
|
function hashPlanPayload(payload) {
|
|
6671
|
-
return
|
|
7297
|
+
return createHash4("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
6672
7298
|
}
|
|
6673
7299
|
function buildSelfAuditPlan(input) {
|
|
6674
7300
|
if (input.imports.length === 0) {
|
|
@@ -6998,10 +7624,1086 @@ Rollback: ${plan.recommended_follow_up.rollback}`,
|
|
|
6998
7624
|
}
|
|
6999
7625
|
|
|
7000
7626
|
// src/lib/work-graph.ts
|
|
7001
|
-
import { createHash as
|
|
7002
|
-
|
|
7627
|
+
import { createHash as createHash6 } from "crypto";
|
|
7628
|
+
|
|
7629
|
+
// src/lib/work-graph-investigation.ts
|
|
7630
|
+
import { createHash as createHash5 } from "crypto";
|
|
7631
|
+
var WORK_GRAPH_INVESTIGATION_SCHEMA_VERSION = "2.0.0";
|
|
7632
|
+
var WORK_GRAPH_INVESTIGATION_CLIENTS = [
|
|
7633
|
+
"claude_code",
|
|
7634
|
+
"codex",
|
|
7635
|
+
"opencode",
|
|
7636
|
+
"goose",
|
|
7637
|
+
"cursor",
|
|
7638
|
+
"github",
|
|
7639
|
+
"slack",
|
|
7640
|
+
"orgx_runtime_hook"
|
|
7641
|
+
];
|
|
7642
|
+
var BRANDS = {
|
|
7643
|
+
claude_code: {
|
|
7644
|
+
name: "Claude Code",
|
|
7645
|
+
simple_icons: "anthropic",
|
|
7646
|
+
color: "#D97757",
|
|
7647
|
+
logo_kind: "wordmark+symbol"
|
|
7648
|
+
},
|
|
7649
|
+
codex: {
|
|
7650
|
+
name: "Codex",
|
|
7651
|
+
simple_icons: "openai",
|
|
7652
|
+
color: "#10A37F",
|
|
7653
|
+
logo_kind: "wordmark+symbol"
|
|
7654
|
+
},
|
|
7655
|
+
opencode: {
|
|
7656
|
+
name: "OpenCode",
|
|
7657
|
+
simple_icons: null,
|
|
7658
|
+
color: "#1A1A1A",
|
|
7659
|
+
logo_kind: "wordmark",
|
|
7660
|
+
asset_path: "/brands/opencode.svg"
|
|
7661
|
+
},
|
|
7662
|
+
goose: {
|
|
7663
|
+
name: "goose",
|
|
7664
|
+
simple_icons: null,
|
|
7665
|
+
color: "#FCBF49",
|
|
7666
|
+
logo_kind: "wordmark+symbol",
|
|
7667
|
+
asset_path: "/brands/goose.svg"
|
|
7668
|
+
},
|
|
7669
|
+
cursor: {
|
|
7670
|
+
name: "Cursor",
|
|
7671
|
+
simple_icons: null,
|
|
7672
|
+
color: "#FFFFFF",
|
|
7673
|
+
logo_kind: "wordmark+symbol",
|
|
7674
|
+
asset_path: "/brands/cursor.svg"
|
|
7675
|
+
},
|
|
7676
|
+
github: {
|
|
7677
|
+
name: "GitHub",
|
|
7678
|
+
simple_icons: "github",
|
|
7679
|
+
color: "#181717",
|
|
7680
|
+
logo_kind: "symbol"
|
|
7681
|
+
},
|
|
7682
|
+
slack: {
|
|
7683
|
+
name: "Slack",
|
|
7684
|
+
simple_icons: "slack",
|
|
7685
|
+
color: "#4A154B",
|
|
7686
|
+
logo_kind: "wordmark+symbol"
|
|
7687
|
+
},
|
|
7688
|
+
orgx_runtime_hook: {
|
|
7689
|
+
name: "OrgX Runtime",
|
|
7690
|
+
simple_icons: null,
|
|
7691
|
+
color: "#00C9A7",
|
|
7692
|
+
logo_kind: "wordmark+symbol",
|
|
7693
|
+
asset_path: "/brands/orgx.svg"
|
|
7694
|
+
}
|
|
7695
|
+
};
|
|
7696
|
+
var CAPABILITY_CEILINGS = {
|
|
7697
|
+
claude_code: {
|
|
7698
|
+
chronology: "high",
|
|
7699
|
+
ownership: "none",
|
|
7700
|
+
verification: "low",
|
|
7701
|
+
handoff: "medium",
|
|
7702
|
+
customer_context: "none",
|
|
7703
|
+
decision_lineage: "medium"
|
|
7704
|
+
},
|
|
7705
|
+
codex: {
|
|
7706
|
+
chronology: "high",
|
|
7707
|
+
ownership: "none",
|
|
7708
|
+
verification: "low",
|
|
7709
|
+
handoff: "medium",
|
|
7710
|
+
customer_context: "none",
|
|
7711
|
+
decision_lineage: "medium"
|
|
7712
|
+
},
|
|
7713
|
+
opencode: {
|
|
7714
|
+
chronology: "high",
|
|
7715
|
+
ownership: "none",
|
|
7716
|
+
verification: "medium",
|
|
7717
|
+
handoff: "medium",
|
|
7718
|
+
customer_context: "none",
|
|
7719
|
+
decision_lineage: "high"
|
|
7720
|
+
},
|
|
7721
|
+
goose: {
|
|
7722
|
+
chronology: "high",
|
|
7723
|
+
ownership: "low",
|
|
7724
|
+
verification: "medium",
|
|
7725
|
+
handoff: "low",
|
|
7726
|
+
customer_context: "low",
|
|
7727
|
+
decision_lineage: "high"
|
|
7728
|
+
},
|
|
7729
|
+
cursor: {
|
|
7730
|
+
chronology: "medium",
|
|
7731
|
+
ownership: "none",
|
|
7732
|
+
verification: "low",
|
|
7733
|
+
handoff: "low",
|
|
7734
|
+
customer_context: "none",
|
|
7735
|
+
decision_lineage: "medium"
|
|
7736
|
+
},
|
|
7737
|
+
github: {
|
|
7738
|
+
chronology: "high",
|
|
7739
|
+
ownership: "high",
|
|
7740
|
+
verification: "high",
|
|
7741
|
+
handoff: "none",
|
|
7742
|
+
customer_context: "low",
|
|
7743
|
+
decision_lineage: "medium"
|
|
7744
|
+
},
|
|
7745
|
+
slack: {
|
|
7746
|
+
chronology: "medium",
|
|
7747
|
+
ownership: "high",
|
|
7748
|
+
verification: "none",
|
|
7749
|
+
handoff: "high",
|
|
7750
|
+
customer_context: "high",
|
|
7751
|
+
decision_lineage: "low"
|
|
7752
|
+
},
|
|
7753
|
+
orgx_runtime_hook: {
|
|
7754
|
+
chronology: "high",
|
|
7755
|
+
ownership: "medium",
|
|
7756
|
+
verification: "high",
|
|
7757
|
+
handoff: "high",
|
|
7758
|
+
customer_context: "none",
|
|
7759
|
+
decision_lineage: "high"
|
|
7760
|
+
}
|
|
7761
|
+
};
|
|
7762
|
+
function hash2(value, length = 16) {
|
|
7763
|
+
return createHash5("sha256").update(JSON.stringify(value)).digest("hex").slice(0, length);
|
|
7764
|
+
}
|
|
7765
|
+
function clamp(value, min = 0, max = 1) {
|
|
7766
|
+
return Math.max(min, Math.min(max, value));
|
|
7767
|
+
}
|
|
7768
|
+
function countBy(values) {
|
|
7769
|
+
const counts = /* @__PURE__ */ new Map();
|
|
7770
|
+
for (const value of values) counts.set(value, (counts.get(value) ?? 0) + 1);
|
|
7771
|
+
return [...counts.entries()].map(([key, count]) => ({ key, count }));
|
|
7772
|
+
}
|
|
7773
|
+
function normalizeClient(value) {
|
|
7774
|
+
const lower = value.toLowerCase().replace(/-/g, "_");
|
|
7775
|
+
if (lower.includes("claude")) return "claude_code";
|
|
7776
|
+
if (lower.includes("codex") || lower.includes("openai")) return "codex";
|
|
7777
|
+
if (lower.includes("cursor")) return "cursor";
|
|
7778
|
+
if (lower.includes("opencode")) return "opencode";
|
|
7779
|
+
if (lower.includes("goose")) return "goose";
|
|
7780
|
+
if (lower.includes("github") || lower === "git") return "github";
|
|
7781
|
+
if (lower.includes("slack")) return "slack";
|
|
7782
|
+
if (lower.includes("hook") || lower.includes("runtime") || lower.includes("mcp")) return "orgx_runtime_hook";
|
|
7783
|
+
return "codex";
|
|
7784
|
+
}
|
|
7785
|
+
function providerForClient2(client) {
|
|
7786
|
+
if (client === "claude_code") return "anthropic";
|
|
7787
|
+
if (client === "codex") return "openai";
|
|
7788
|
+
return "unknown";
|
|
7789
|
+
}
|
|
7790
|
+
function eventKindForFinding(finding) {
|
|
7791
|
+
if (finding.type === "decision") return "assistant_reasoning";
|
|
7792
|
+
if (finding.type === "artifact") return "file_edit";
|
|
7793
|
+
if (finding.type === "blocker") return "tool_call_error";
|
|
7794
|
+
if (finding.type === "outcome") return "test_run";
|
|
7795
|
+
if (finding.type === "missed_orchestration_opportunity") return "mcp_tool_call";
|
|
7796
|
+
return "assistant_text";
|
|
7797
|
+
}
|
|
7798
|
+
function windowFor(timestamp, now) {
|
|
7799
|
+
const occurred = Date.parse(timestamp);
|
|
7800
|
+
const current = Date.parse(now);
|
|
7801
|
+
if (!Number.isFinite(occurred) || !Number.isFinite(current)) return "older";
|
|
7802
|
+
const delta = current - occurred;
|
|
7803
|
+
if (delta < 5 * 60 * 1e3) return "live";
|
|
7804
|
+
if (delta <= 24 * 60 * 60 * 1e3) return "recent_24h";
|
|
7805
|
+
if (delta <= 7 * 24 * 60 * 60 * 1e3) return "recent_7d";
|
|
7806
|
+
if (delta <= 30 * 24 * 60 * 60 * 1e3) return "recent_30d";
|
|
7807
|
+
return "older";
|
|
7808
|
+
}
|
|
7809
|
+
function rawEventFromFinding(finding, index, generatedAt) {
|
|
7810
|
+
const sourceClient = normalizeClient(finding.source_client);
|
|
7811
|
+
const timestamp = typeof finding.metadata.occurred_at === "string" ? finding.metadata.occurred_at : generatedAt;
|
|
7812
|
+
const eventId = `evt_${hash2([finding.evidence_ref, finding.title, index], 24)}`;
|
|
7813
|
+
const payload = {
|
|
7814
|
+
title: finding.title,
|
|
7815
|
+
summary: finding.summary,
|
|
7816
|
+
finding_type: finding.type,
|
|
7817
|
+
source_id: finding.source_id,
|
|
7818
|
+
confidence: finding.confidence,
|
|
7819
|
+
redacted_verbatim: typeof finding.metadata.redacted_verbatim === "string" ? finding.metadata.redacted_verbatim : finding.summary.slice(0, 420)
|
|
7820
|
+
};
|
|
7821
|
+
return {
|
|
7822
|
+
event_id: eventId,
|
|
7823
|
+
source_ref: {
|
|
7824
|
+
source_id: sourceClient,
|
|
7825
|
+
uri: finding.evidence_ref,
|
|
7826
|
+
cite_url: null,
|
|
7827
|
+
resolves: true
|
|
7828
|
+
},
|
|
7829
|
+
source_id: sourceClient,
|
|
7830
|
+
provider: providerForClient2(sourceClient),
|
|
7831
|
+
session_id: finding.source_id,
|
|
7832
|
+
project_id: null,
|
|
7833
|
+
timestamp,
|
|
7834
|
+
occurred_in_window: windowFor(timestamp, generatedAt),
|
|
7835
|
+
kind: eventKindForFinding(finding),
|
|
7836
|
+
role: finding.type === "blocker" ? "tool" : "meta",
|
|
7837
|
+
payload,
|
|
7838
|
+
raw_byte_offset: null,
|
|
7839
|
+
raw_row_id: null,
|
|
7840
|
+
content_hash: hash2(payload, 64),
|
|
7841
|
+
redaction_applied: true
|
|
7842
|
+
};
|
|
7843
|
+
}
|
|
7844
|
+
function rawEventFromSourceEvent(event, index, generatedAt) {
|
|
7845
|
+
const sourceClient = normalizeClient(event.source_client);
|
|
7846
|
+
const payload = {
|
|
7847
|
+
source_label: event.source_label,
|
|
7848
|
+
event_type: event.event_type,
|
|
7849
|
+
text_summary: event.text.slice(0, 420)
|
|
7850
|
+
};
|
|
7851
|
+
return {
|
|
7852
|
+
event_id: `evt_${hash2([event.evidence_ref, index], 24)}`,
|
|
7853
|
+
source_ref: {
|
|
7854
|
+
source_id: sourceClient,
|
|
7855
|
+
uri: event.evidence_ref,
|
|
7856
|
+
cite_url: null,
|
|
7857
|
+
resolves: true
|
|
7858
|
+
},
|
|
7859
|
+
source_id: sourceClient,
|
|
7860
|
+
provider: providerForClient2(sourceClient),
|
|
7861
|
+
session_id: event.source_id,
|
|
7862
|
+
project_id: null,
|
|
7863
|
+
timestamp: generatedAt,
|
|
7864
|
+
occurred_in_window: "live",
|
|
7865
|
+
kind: event.event_type === "tool_signal" ? "tool_call_start" : "assistant_text",
|
|
7866
|
+
role: "meta",
|
|
7867
|
+
payload,
|
|
7868
|
+
raw_byte_offset: null,
|
|
7869
|
+
raw_row_id: null,
|
|
7870
|
+
content_hash: hash2(payload, 64),
|
|
7871
|
+
redaction_applied: true
|
|
7872
|
+
};
|
|
7873
|
+
}
|
|
7874
|
+
function buildRawEvents(input) {
|
|
7875
|
+
const sourceEvents = input.events.map(
|
|
7876
|
+
(event, index) => rawEventFromSourceEvent(event, index, input.generatedAt)
|
|
7877
|
+
);
|
|
7878
|
+
const findingEvents = input.findings.map(
|
|
7879
|
+
(finding, index) => rawEventFromFinding(finding, index, input.generatedAt)
|
|
7880
|
+
);
|
|
7881
|
+
const byUri = /* @__PURE__ */ new Map();
|
|
7882
|
+
for (const event of [...input.rawEvents ?? [], ...sourceEvents, ...findingEvents]) {
|
|
7883
|
+
byUri.set(event.event_id || `${event.source_ref.uri}:${event.kind}`, event);
|
|
7884
|
+
}
|
|
7885
|
+
return [...byUri.values()].sort(
|
|
7886
|
+
(left, right) => left.timestamp.localeCompare(right.timestamp)
|
|
7887
|
+
);
|
|
7888
|
+
}
|
|
7889
|
+
function eventsForRefs(events, refs) {
|
|
7890
|
+
const refSet = new Set(refs);
|
|
7891
|
+
return events.filter((event) => refSet.has(event.source_ref.uri));
|
|
7892
|
+
}
|
|
7893
|
+
function intentClassForFinding(finding) {
|
|
7894
|
+
const text2 = `${finding.title}
|
|
7895
|
+
${finding.summary}`;
|
|
7896
|
+
if (finding.type === "decision") return "architecture_decision";
|
|
7897
|
+
if (finding.type === "artifact" || /\b(implemented|built|created|shipped)\b/i.test(text2)) {
|
|
7898
|
+
return "feature_implementation";
|
|
7899
|
+
}
|
|
7900
|
+
if (/\b(test|qa|verified|proof)\b/i.test(text2)) return "verification_or_testing";
|
|
7901
|
+
if (/\b(auth|config|mcp|source|connect|integration|hook)\b/i.test(text2)) {
|
|
7902
|
+
return "integration_or_connection";
|
|
7903
|
+
}
|
|
7904
|
+
if (/\b(refactor|cleanup|rename|remove)\b/i.test(text2)) return "cleanup_or_refactor";
|
|
7905
|
+
if (/\b(doc|readme|methodology|runbook)\b/i.test(text2)) return "documentation";
|
|
7906
|
+
if (finding.type === "blocker" && /\bbug|error|fail|zod|schema\b/i.test(text2)) return "bug_fix";
|
|
7907
|
+
if (finding.type === "blocker") return "investigation";
|
|
7908
|
+
return "unclear";
|
|
7909
|
+
}
|
|
7910
|
+
function bottleneckClassForText(text2) {
|
|
7911
|
+
if (/\bzod\b|schema|validation|expected .* received/i.test(text2)) return "schema_validation";
|
|
7912
|
+
if (/permission|approval|denied|unauthorized|401|403/i.test(text2)) return "permission_denied";
|
|
7913
|
+
if (/missing arg|wrong type|tool.*misconfigured|invalid/i.test(text2)) return "tool_misconfigured";
|
|
7914
|
+
if (/context overflow|compaction|too large/i.test(text2)) return "context_overflow";
|
|
7915
|
+
if (/auth|billing|quota|402|api key|token/i.test(text2)) return "auth_or_billing";
|
|
7916
|
+
if (/dispatch|race|not dispatched|ready stream/i.test(text2)) return "race_or_dispatch";
|
|
7917
|
+
if (/cross.repo|repo boundary|vendored|mirror/i.test(text2)) return "cross_repo_dependency";
|
|
7918
|
+
if (/external|api failed|timeout|timed out/i.test(text2)) return "external_api_failure";
|
|
7919
|
+
if (/owner|handoff|dri|approval/i.test(text2)) return "human_handoff_missing";
|
|
7920
|
+
return null;
|
|
7921
|
+
}
|
|
7922
|
+
function terminalForTrail(trail) {
|
|
7923
|
+
if (trail.state === "verified" || trail.valence === "healthy") {
|
|
7924
|
+
return {
|
|
7925
|
+
state: "shipped",
|
|
7926
|
+
proof: trail.evidence_refs[0] ? { kind: "inferred_only", ref: trail.evidence_refs[0] } : { kind: "inferred_only" },
|
|
7927
|
+
classified_by: "deterministic",
|
|
7928
|
+
classification_basis: ["verified_or_healthy_trail_state"]
|
|
7929
|
+
};
|
|
7930
|
+
}
|
|
7931
|
+
if (trail.state === "blocked" || trail.valence === "risk" || trail.valence === "escalating") {
|
|
7932
|
+
return {
|
|
7933
|
+
state: "blocked",
|
|
7934
|
+
proof: { kind: "absent", expected_kind: "owner_visible_resolution" },
|
|
7935
|
+
classified_by: "deterministic",
|
|
7936
|
+
classification_basis: ["blocked_or_escalating_trail_state"]
|
|
7937
|
+
};
|
|
7938
|
+
}
|
|
7939
|
+
if (trail.state === "stale" || trail.state === "decaying") {
|
|
7940
|
+
return {
|
|
7941
|
+
state: "abandoned",
|
|
7942
|
+
proof: { kind: "absent", expected_kind: "later_resolution_event" },
|
|
7943
|
+
classified_by: "deterministic",
|
|
7944
|
+
classification_basis: ["stale_or_decaying_trail_state"]
|
|
7945
|
+
};
|
|
7946
|
+
}
|
|
7947
|
+
return {
|
|
7948
|
+
state: "ongoing",
|
|
7949
|
+
proof: trail.evidence_refs[0] ? { kind: "inferred_only", ref: trail.evidence_refs[0] } : { kind: "inferred_only" },
|
|
7950
|
+
classified_by: "hybrid",
|
|
7951
|
+
classification_basis: ["no_deterministic_terminal_event"]
|
|
7952
|
+
};
|
|
7953
|
+
}
|
|
7954
|
+
function buildWorkLoops(input) {
|
|
7955
|
+
const findingsByRef = new Map(input.findings.map((finding) => [finding.evidence_ref, finding]));
|
|
7956
|
+
return input.trails.map((trail, index) => {
|
|
7957
|
+
const matchedEvents = eventsForRefs(input.events, trail.evidence_refs);
|
|
7958
|
+
const matchedFindings = trail.evidence_refs.map((ref) => findingsByRef.get(ref)).filter((finding) => Boolean(finding));
|
|
7959
|
+
const firstFinding = matchedFindings[0];
|
|
7960
|
+
const eventIds = matchedEvents.map((event) => event.event_id);
|
|
7961
|
+
const text2 = [
|
|
7962
|
+
trail.title,
|
|
7963
|
+
trail.summary,
|
|
7964
|
+
...matchedFindings.map((finding) => finding.summary)
|
|
7965
|
+
].join("\n");
|
|
7966
|
+
const bottleneck = bottleneckClassForText(text2);
|
|
7967
|
+
const terminal = terminalForTrail(trail);
|
|
7968
|
+
const confidence = clamp(
|
|
7969
|
+
trail.confidence || matchedFindings.reduce((total, finding) => total + finding.confidence, 0) / Math.max(1, matchedFindings.length)
|
|
7970
|
+
);
|
|
7971
|
+
return {
|
|
7972
|
+
loop_id: `loop_${hash2([trail.id, index], 18)}`,
|
|
7973
|
+
cites: eventIds,
|
|
7974
|
+
origin: {
|
|
7975
|
+
event_id: eventIds[0] ?? `evt_missing_${index}`,
|
|
7976
|
+
timestamp: matchedEvents[0]?.timestamp ?? trail.created_at,
|
|
7977
|
+
intent: trail.title.slice(0, 160),
|
|
7978
|
+
intent_class: firstFinding ? intentClassForFinding(firstFinding) : "unclear"
|
|
7979
|
+
},
|
|
7980
|
+
path: {
|
|
7981
|
+
event_ids: eventIds,
|
|
7982
|
+
actions_taken: matchedEvents.map((event) => ({
|
|
7983
|
+
kind: event.kind,
|
|
7984
|
+
label: String(event.payload.title ?? event.kind).slice(0, 120),
|
|
7985
|
+
event_id: event.event_id
|
|
7986
|
+
})),
|
|
7987
|
+
sessions_spanned: [...new Set(matchedEvents.map((event) => event.session_id))],
|
|
7988
|
+
tools_used: matchedEvents.filter((event) => event.kind === "tool_call_start" || event.kind === "mcp_tool_call").map((event) => String(event.payload.tool_name ?? event.payload.title ?? "unknown_tool")),
|
|
7989
|
+
span_minutes: Math.max(1, matchedEvents.length * 12)
|
|
7990
|
+
},
|
|
7991
|
+
terminal,
|
|
7992
|
+
bottleneck: {
|
|
7993
|
+
class: bottleneck,
|
|
7994
|
+
evidence_event_ids: bottleneck ? eventIds : []
|
|
7995
|
+
},
|
|
7996
|
+
recurrence: {
|
|
7997
|
+
family_id: null,
|
|
7998
|
+
appearances_in_family: 1,
|
|
7999
|
+
is_first_appearance: true,
|
|
8000
|
+
decay_half_life_days: terminal.state === "blocked" ? 3 : null
|
|
8001
|
+
},
|
|
8002
|
+
confidence,
|
|
8003
|
+
survived_critic: confidence >= 0.6 && eventIds.length > 0,
|
|
8004
|
+
public_surface: confidence >= 0.6 && eventIds.length > 0
|
|
8005
|
+
};
|
|
8006
|
+
});
|
|
8007
|
+
}
|
|
8008
|
+
function loopFamilyKey(loop) {
|
|
8009
|
+
return [
|
|
8010
|
+
loop.origin.intent_class,
|
|
8011
|
+
loop.terminal.state,
|
|
8012
|
+
loop.bottleneck.class ?? "none"
|
|
8013
|
+
].join(":");
|
|
8014
|
+
}
|
|
8015
|
+
function shapeForFamily(loops) {
|
|
8016
|
+
if (loops.length <= 1) return "single_signal";
|
|
8017
|
+
if (loops.some((loop) => loop.terminal.state === "shipped")) return "decaying_resolved";
|
|
8018
|
+
if (loops.some((loop) => loop.bottleneck.class)) return loops.length >= 3 ? "accelerating" : "dense_recent_cluster";
|
|
8019
|
+
return loops.length >= 4 ? "chronic_evenly_spaced" : "dense_recent_cluster";
|
|
8020
|
+
}
|
|
8021
|
+
function repairForFamily(familyLoops, impact) {
|
|
8022
|
+
const top = familyLoops[0];
|
|
8023
|
+
const title = top?.origin.intent ?? "Investigate work loop";
|
|
8024
|
+
const bottleneck = top?.bottleneck.class;
|
|
8025
|
+
const capability = bottleneck === "human_handoff_missing" ? "mcp__orgx__assign_owner" : bottleneck ? "mcp__orgx__create_blocker" : top?.origin.intent_class === "architecture_decision" ? "mcp__orgx__create_decision" : "mcp__orgx__scaffold_initiative";
|
|
8026
|
+
return {
|
|
8027
|
+
named_orgx_capability: capability,
|
|
8028
|
+
expected_tool_call_args: {
|
|
8029
|
+
title,
|
|
8030
|
+
source: "work_graph_investigation",
|
|
8031
|
+
evidence_event_ids: familyLoops.flatMap((loop) => loop.cites).slice(0, 12),
|
|
8032
|
+
terminal_state: top?.terminal.state ?? "ongoing",
|
|
8033
|
+
bottleneck_class: bottleneck ?? null
|
|
8034
|
+
},
|
|
8035
|
+
expected_outcome: "OrgX would create an owner-visible record tied to the source evidence, then suppress duplicate rediscovery until it is reopened.",
|
|
8036
|
+
expected_score_lift: [
|
|
8037
|
+
{ dimension: "chronology_depth", delta: Math.min(18, familyLoops.length * 3) },
|
|
8038
|
+
{ dimension: "repair_actionability", delta: capability.includes("scaffold") ? 12 : 16 }
|
|
8039
|
+
],
|
|
8040
|
+
expected_hours_recovered: Number(Math.min(impact.time_saved_hours_per_week, familyLoops.length * 0.75).toFixed(1)),
|
|
8041
|
+
expected_dollars_recovered: Math.round(Math.min(impact.estimated_monthly_value_usd, familyLoops.length * 0.75 * 4.33 * 200)),
|
|
8042
|
+
preconditions: ["claim_profile", "confirm_or_correct_evidence"]
|
|
8043
|
+
};
|
|
8044
|
+
}
|
|
8045
|
+
function buildLoopFamilies(loops, events, impact) {
|
|
8046
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
8047
|
+
for (const loop of loops) {
|
|
8048
|
+
const key = loopFamilyKey(loop);
|
|
8049
|
+
grouped.set(key, [...grouped.get(key) ?? [], loop]);
|
|
8050
|
+
}
|
|
8051
|
+
const families = [...grouped.entries()].map(([key, group]) => {
|
|
8052
|
+
const sourceIds = new Set(
|
|
8053
|
+
group.flatMap(
|
|
8054
|
+
(loop) => loop.cites.map((cite) => events.find((event) => event.event_id === cite)?.source_id).filter(Boolean)
|
|
8055
|
+
)
|
|
8056
|
+
);
|
|
8057
|
+
const familyId = `family_${hash2(key, 16)}`;
|
|
8058
|
+
const timestamps = group.map((loop) => Date.parse(loop.origin.timestamp)).filter(Number.isFinite);
|
|
8059
|
+
const spanDays = timestamps.length > 1 ? Math.max(1, Math.ceil((Math.max(...timestamps) - Math.min(...timestamps)) / 864e5)) : 0;
|
|
8060
|
+
const divergenceScore = group.length >= 3 ? 0.32 : 0.5;
|
|
8061
|
+
return {
|
|
8062
|
+
family_id: familyId,
|
|
8063
|
+
shared_intent_class: group[0]?.origin.intent_class ?? "unclear",
|
|
8064
|
+
shared_terminal_state: group[0]?.terminal.state ?? "ongoing",
|
|
8065
|
+
shared_bottleneck_class: group[0]?.bottleneck.class ?? null,
|
|
8066
|
+
loop_ids: group.map((loop) => loop.loop_id),
|
|
8067
|
+
appearances: group.length,
|
|
8068
|
+
span_days: spanDays,
|
|
8069
|
+
shape: shapeForFamily(group),
|
|
8070
|
+
semantic_centroid: group[0]?.origin.intent ?? "Work loop family",
|
|
8071
|
+
divergence_score: divergenceScore,
|
|
8072
|
+
cross_source_confluence: sourceIds.size >= 2,
|
|
8073
|
+
orgx_repair: repairForFamily(group, impact),
|
|
8074
|
+
alternative_explanations_considered: [
|
|
8075
|
+
"The loops may be related only by vocabulary.",
|
|
8076
|
+
"The apparent recurrence may be a planned multi-step implementation rather than unresolved work."
|
|
8077
|
+
],
|
|
8078
|
+
alternative_rejected_because: group.length >= 3 ? ["Shared intent class, terminal state, and bottleneck class recur across multiple evidence events."] : ["Kept as a non-public single/weak family until more chronology exists."],
|
|
8079
|
+
survived_critic: group.length >= 3 && divergenceScore < 0.5,
|
|
8080
|
+
public_surface: group.length >= 3 && divergenceScore < 0.5
|
|
8081
|
+
};
|
|
8082
|
+
});
|
|
8083
|
+
const familyMap = new Map(families.map((family) => [family.family_id, family]));
|
|
8084
|
+
for (const family of families) {
|
|
8085
|
+
for (const loopId of family.loop_ids) {
|
|
8086
|
+
const loop = loops.find((candidate) => candidate.loop_id === loopId);
|
|
8087
|
+
if (!loop) continue;
|
|
8088
|
+
loop.recurrence.family_id = family.family_id;
|
|
8089
|
+
loop.recurrence.appearances_in_family = family.appearances;
|
|
8090
|
+
loop.recurrence.is_first_appearance = family.loop_ids[0] === loop.loop_id;
|
|
8091
|
+
}
|
|
8092
|
+
}
|
|
8093
|
+
return [...familyMap.values()].sort((left, right) => right.appearances - left.appearances);
|
|
8094
|
+
}
|
|
8095
|
+
function buildUsageCatalogue(events, findings) {
|
|
8096
|
+
const toolEvents = events.filter((event) => event.kind === "tool_call_start" || event.kind === "mcp_tool_call");
|
|
8097
|
+
const mcpToolNames = /* @__PURE__ */ new Map();
|
|
8098
|
+
for (const event of toolEvents) {
|
|
8099
|
+
const text2 = `${event.payload.title ?? ""}
|
|
8100
|
+
${event.payload.summary ?? ""}
|
|
8101
|
+
${event.payload.text_summary ?? ""}`;
|
|
8102
|
+
const match = text2.match(/\b(?:mcp__[\w-]+__[\w-]+|orgx_[\w-]+|complete_with_proof|ship_batch|record_outcome|scaffold_initiative)\b/i);
|
|
8103
|
+
const name = match?.[0] ?? "unknown_tool";
|
|
8104
|
+
mcpToolNames.set(name, [...mcpToolNames.get(name) ?? [], event]);
|
|
8105
|
+
}
|
|
8106
|
+
const mentionedTools = /* @__PURE__ */ new Set();
|
|
8107
|
+
for (const finding of findings) {
|
|
8108
|
+
const matches = `${finding.title}
|
|
8109
|
+
${finding.summary}`.matchAll(/\b(?:mcp__[\w-]+__[\w-]+|orgx_[\w-]+|complete_with_proof|ship_batch|record_outcome|scaffold_initiative)\b/gi);
|
|
8110
|
+
for (const match of matches) mentionedTools.add(match[0]);
|
|
8111
|
+
}
|
|
8112
|
+
const configuredOrgxEvents = events.filter(
|
|
8113
|
+
(event) => event.payload.tool_usage_state === "configured" && /\borgx\b|mcp/i.test(JSON.stringify(event.payload))
|
|
8114
|
+
);
|
|
8115
|
+
const shouldHaveInvoked = findings.filter(
|
|
8116
|
+
(finding) => finding.type === "missed_orchestration_opportunity" || /\bshould have|available but not called|not invoked|writeback\b/i.test(`${finding.title}
|
|
8117
|
+
${finding.summary}`)
|
|
8118
|
+
);
|
|
8119
|
+
const mcp_tools = [
|
|
8120
|
+
...[...mcpToolNames.entries()].map(([name, matchingEvents]) => ({
|
|
8121
|
+
name,
|
|
8122
|
+
namespace: name.startsWith("mcp__") ? name.split("__")[1] ?? "unknown" : "orgx",
|
|
8123
|
+
state: matchingEvents.length > 0 ? "invoked" : "mentioned",
|
|
8124
|
+
invocations: matchingEvents.length,
|
|
8125
|
+
success: matchingEvents.filter((event) => event.kind === "tool_call_result").length,
|
|
8126
|
+
error: matchingEvents.filter((event) => event.kind === "tool_call_error").length,
|
|
8127
|
+
error_classes: [],
|
|
8128
|
+
by_source: countBy(matchingEvents.map((event) => event.source_id)).map(({ key, count }) => ({
|
|
8129
|
+
source_id: key,
|
|
8130
|
+
count
|
|
8131
|
+
})),
|
|
8132
|
+
event_refs: matchingEvents.map((event) => event.event_id)
|
|
8133
|
+
})),
|
|
8134
|
+
...[...mentionedTools].filter((name) => !mcpToolNames.has(name)).map((name) => ({
|
|
8135
|
+
name,
|
|
8136
|
+
namespace: name.startsWith("mcp__") ? name.split("__")[1] ?? "unknown" : "orgx",
|
|
8137
|
+
state: "mentioned",
|
|
8138
|
+
invocations: 0,
|
|
8139
|
+
success: 0,
|
|
8140
|
+
error: 0,
|
|
8141
|
+
error_classes: [],
|
|
8142
|
+
by_source: [],
|
|
8143
|
+
event_refs: []
|
|
8144
|
+
})),
|
|
8145
|
+
...configuredOrgxEvents.length > 0 && !mcpToolNames.has("mcp__orgx__configured") ? [{
|
|
8146
|
+
name: "mcp__orgx__configured",
|
|
8147
|
+
namespace: "orgx",
|
|
8148
|
+
state: "configured",
|
|
8149
|
+
invocations: 0,
|
|
8150
|
+
success: 0,
|
|
8151
|
+
error: 0,
|
|
8152
|
+
error_classes: [],
|
|
8153
|
+
by_source: countBy(configuredOrgxEvents.map((event) => event.source_id)).map(({ key, count }) => ({
|
|
8154
|
+
source_id: key,
|
|
8155
|
+
count
|
|
8156
|
+
})),
|
|
8157
|
+
event_refs: configuredOrgxEvents.map((event) => event.event_id)
|
|
8158
|
+
}] : [],
|
|
8159
|
+
...shouldHaveInvoked.length > 0 && !mcpToolNames.has("mcp__orgx__create_decision") ? [{
|
|
8160
|
+
name: "mcp__orgx__create_decision",
|
|
8161
|
+
namespace: "orgx",
|
|
8162
|
+
state: "should_have_invoked",
|
|
8163
|
+
invocations: 0,
|
|
8164
|
+
success: 0,
|
|
8165
|
+
error: 0,
|
|
8166
|
+
error_classes: [],
|
|
8167
|
+
by_source: [],
|
|
8168
|
+
event_refs: []
|
|
8169
|
+
}] : []
|
|
8170
|
+
];
|
|
8171
|
+
const ai_clients = WORK_GRAPH_INVESTIGATION_CLIENTS.slice(0, 5).map((sourceId) => {
|
|
8172
|
+
const sourceEvents = events.filter((event) => event.source_id === sourceId);
|
|
8173
|
+
return {
|
|
8174
|
+
source_id: sourceId,
|
|
8175
|
+
sessions: new Set(sourceEvents.map((event) => event.session_id)).size,
|
|
8176
|
+
turns: sourceEvents.filter((event) => event.kind === "user_prompt" || event.kind === "assistant_text").length
|
|
8177
|
+
};
|
|
8178
|
+
});
|
|
8179
|
+
return {
|
|
8180
|
+
ai_clients,
|
|
8181
|
+
mcp_tools,
|
|
8182
|
+
mcp_namespaces_seen: [...new Set(mcp_tools.map((tool) => tool.namespace))],
|
|
8183
|
+
shell_commands: [],
|
|
8184
|
+
recipes_or_skills: findings.filter((finding) => /\bskill|recipe|agent\b/i.test(`${finding.title}
|
|
8185
|
+
${finding.summary}`)).slice(0, 20).map((finding) => ({
|
|
8186
|
+
source_id: normalizeClient(finding.source_client),
|
|
8187
|
+
name: finding.title.slice(0, 80),
|
|
8188
|
+
invocations: 0,
|
|
8189
|
+
last_used: typeof finding.metadata.occurred_at === "string" ? finding.metadata.occurred_at : (/* @__PURE__ */ new Date()).toISOString()
|
|
8190
|
+
})),
|
|
8191
|
+
agents_observed: ai_clients.filter((client) => client.sessions > 0).map((client) => ({
|
|
8192
|
+
source_id: client.source_id,
|
|
8193
|
+
name: BRANDS[client.source_id].name,
|
|
8194
|
+
spawn_count: client.sessions,
|
|
8195
|
+
success_count: 0
|
|
8196
|
+
})),
|
|
8197
|
+
repo_paths_touched: [],
|
|
8198
|
+
external_sources_called: []
|
|
8199
|
+
};
|
|
8200
|
+
}
|
|
8201
|
+
function capabilityCellsFor(input) {
|
|
8202
|
+
const ceilings = CAPABILITY_CEILINGS[input.sourceId];
|
|
8203
|
+
const sourceEvents = input.events.filter((event) => event.source_id === input.sourceId);
|
|
8204
|
+
const achievedBase = input.status === "connected" ? 0.68 : input.status === "partial" ? 0.42 : input.status === "detected_not_read" ? 0.16 : 0;
|
|
8205
|
+
const hasToolState = sourceEvents.some((event) => event.kind.includes("tool"));
|
|
8206
|
+
const hasVerification = sourceEvents.some((event) => event.kind === "test_run" || event.kind === "commit");
|
|
8207
|
+
const hasHandoff = sourceEvents.some((event) => /handoff|owner|approval/i.test(JSON.stringify(event.payload)));
|
|
8208
|
+
return Object.fromEntries(
|
|
8209
|
+
Object.keys(ceilings).map((dimension) => {
|
|
8210
|
+
const ceiling = ceilings[dimension];
|
|
8211
|
+
const boost = dimension === "decision_lineage" && hasToolState || dimension === "verification" && hasVerification || dimension === "handoff" && hasHandoff ? 0.18 : 0;
|
|
8212
|
+
const achieved = ceiling === "none" ? 0 : clamp(achievedBase + boost);
|
|
8213
|
+
return [
|
|
8214
|
+
dimension,
|
|
8215
|
+
{
|
|
8216
|
+
ceiling,
|
|
8217
|
+
achieved,
|
|
8218
|
+
basis: sourceEvents.length > 0 ? `${sourceEvents.length} normalized raw event${sourceEvents.length === 1 ? "" : "s"}` : input.status === "missing" ? "Source supported but not connected for this audit" : "Source detected without enough readable evidence",
|
|
8219
|
+
blockers_to_full: achieved >= 0.8 ? [] : [
|
|
8220
|
+
dimension === "verification" ? "connect_github_or_runtime_hook" : dimension === "ownership" || dimension === "handoff" ? "connect_slack_or_claim_profile" : "deepen_native_session_events"
|
|
8221
|
+
]
|
|
8222
|
+
}
|
|
8223
|
+
];
|
|
8224
|
+
})
|
|
8225
|
+
);
|
|
8226
|
+
}
|
|
8227
|
+
function buildCorpusManifest(input) {
|
|
8228
|
+
const manifests = WORK_GRAPH_INVESTIGATION_CLIENTS.map((sourceId) => {
|
|
8229
|
+
const sourceEvents = input.events.filter((event) => event.source_id === sourceId);
|
|
8230
|
+
const matchingExtraction = input.clientExtractions.find(
|
|
8231
|
+
(extraction) => normalizeClient(extraction.source_client) === sourceId
|
|
8232
|
+
);
|
|
8233
|
+
const coverageManifest = input.coverage.manifests?.find(
|
|
8234
|
+
(manifest) => normalizeClient(manifest.source_client) === sourceId
|
|
8235
|
+
);
|
|
8236
|
+
const status = sourceEvents.length > 0 || matchingExtraction && matchingExtraction.finding_count > 0 || coverageManifest?.status === "connected" ? "connected" : matchingExtraction ? "detected_not_read" : coverageManifest?.status === "partial" ? "partial" : input.coverage.missing.some((source) => normalizeClient(source) === sourceId) ? "missing" : "supported_not_connected";
|
|
8237
|
+
const skipped = coverageManifest?.skipped_session_count ? [{ reason: "no_entity_references", count: coverageManifest.skipped_session_count }] : [];
|
|
8238
|
+
const cells = capabilityCellsFor({ sourceId, status, events: input.events });
|
|
8239
|
+
const sourceSessionCount = new Set(sourceEvents.map((event) => event.session_id)).size;
|
|
8240
|
+
return {
|
|
8241
|
+
source_id: sourceId,
|
|
8242
|
+
brand: BRANDS[sourceId],
|
|
8243
|
+
client: sourceId,
|
|
8244
|
+
provider: providerForClient2(sourceId),
|
|
8245
|
+
status,
|
|
8246
|
+
extraction_mode: sourceId === "opencode" || sourceId === "goose" ? "sqlite" : sourceId === "cursor" ? "specstory" : sourceId === "orgx_runtime_hook" ? "orgx_runtime_hook" : "jsonl",
|
|
8247
|
+
storage_paths_resolved: coverageManifest?.searched_sources ?? [],
|
|
8248
|
+
storage_version_detected: null,
|
|
8249
|
+
files_seen: coverageManifest?.searched_session_count ?? matchingExtraction?.searched_session_count ?? sourceSessionCount,
|
|
8250
|
+
files_read: sourceEvents.length > 0 ? Math.max(1, sourceSessionCount) : 0,
|
|
8251
|
+
files_skipped: skipped,
|
|
8252
|
+
sessions: sourceSessionCount || matchingExtraction?.searched_session_count || coverageManifest?.searched_session_count || 0,
|
|
8253
|
+
message_turns: sourceEvents.filter((event) => event.kind === "user_prompt" || event.kind === "assistant_text").length || (sourceId === "codex" || sourceId === "claude_code" ? input.auditMethod.searched_message_count : 0),
|
|
8254
|
+
tool_calls: sourceEvents.filter((event) => event.kind === "tool_call_start").length,
|
|
8255
|
+
mcp_tool_calls: sourceEvents.filter((event) => event.kind === "mcp_tool_call").length,
|
|
8256
|
+
capability_cells: cells
|
|
8257
|
+
};
|
|
8258
|
+
});
|
|
8259
|
+
const timestamps = input.events.map((event) => event.timestamp).sort();
|
|
8260
|
+
const filesSeen = manifests.reduce((total, source) => total + source.files_seen, 0);
|
|
8261
|
+
const filesRead = manifests.reduce((total, source) => total + source.files_read, 0);
|
|
8262
|
+
const filesSkipped = manifests.reduce(
|
|
8263
|
+
(total, source) => total + source.files_skipped.reduce((sum, skipped) => sum + skipped.count, 0),
|
|
8264
|
+
0
|
|
8265
|
+
);
|
|
8266
|
+
const sessions = manifests.reduce((total, source) => total + source.sessions, 0);
|
|
8267
|
+
return {
|
|
8268
|
+
audit_id: input.auditId,
|
|
8269
|
+
ran_at: input.generatedAt,
|
|
8270
|
+
sources: manifests,
|
|
8271
|
+
totals: {
|
|
8272
|
+
files_seen: Math.max(filesSeen, input.auditMethod.searched_session_files),
|
|
8273
|
+
files_read: Math.max(filesRead, input.auditMethod.searched_session_files - input.auditMethod.skipped_session_files),
|
|
8274
|
+
files_skipped: Math.max(filesSkipped, input.auditMethod.skipped_session_files),
|
|
8275
|
+
bytes_read: 0,
|
|
8276
|
+
sessions: Math.max(sessions, input.auditMethod.searched_session_files),
|
|
8277
|
+
sessions_skipped: input.auditMethod.skipped_session_files ? [{ reason: "no_entity_references", count: input.auditMethod.skipped_session_files }] : [],
|
|
8278
|
+
message_turns: Math.max(
|
|
8279
|
+
input.auditMethod.searched_message_count,
|
|
8280
|
+
input.events.filter((event) => event.kind === "user_prompt" || event.kind === "assistant_text").length
|
|
8281
|
+
),
|
|
8282
|
+
user_prompts: input.events.filter((event) => event.kind === "user_prompt").length,
|
|
8283
|
+
assistant_turns: input.events.filter((event) => event.kind === "assistant_text").length,
|
|
8284
|
+
assistant_reasoning_turns: input.events.filter((event) => event.kind === "assistant_reasoning").length,
|
|
8285
|
+
tool_calls: input.events.filter((event) => event.kind === "tool_call_start").length,
|
|
8286
|
+
mcp_tool_calls: input.events.filter((event) => event.kind === "mcp_tool_call").length,
|
|
8287
|
+
tool_call_errors: input.events.filter((event) => event.kind === "tool_call_error").length,
|
|
8288
|
+
file_edits: input.events.filter((event) => event.kind === "file_edit").length,
|
|
8289
|
+
file_reads: input.events.filter((event) => event.kind === "file_read").length,
|
|
8290
|
+
shell_commands: input.events.filter((event) => event.kind === "shell_command").length,
|
|
8291
|
+
test_runs: input.events.filter((event) => event.kind === "test_run").length,
|
|
8292
|
+
errors_emitted: input.events.filter((event) => event.kind === "error_emitted").length,
|
|
8293
|
+
permission_requests: input.events.filter((event) => event.kind === "permission_request").length,
|
|
8294
|
+
forks: input.events.filter((event) => event.kind === "session_fork").length,
|
|
8295
|
+
compactions: input.events.filter((event) => event.kind === "compaction").length,
|
|
8296
|
+
earliest_event: timestamps[0] ?? null,
|
|
8297
|
+
latest_event: timestamps[timestamps.length - 1] ?? null
|
|
8298
|
+
}
|
|
8299
|
+
};
|
|
8300
|
+
}
|
|
8301
|
+
function buildSourceConfidence(corpusManifest) {
|
|
8302
|
+
return {
|
|
8303
|
+
rows: [
|
|
8304
|
+
"chronology",
|
|
8305
|
+
"ownership",
|
|
8306
|
+
"verification",
|
|
8307
|
+
"handoff",
|
|
8308
|
+
"customer_context",
|
|
8309
|
+
"decision_lineage"
|
|
8310
|
+
],
|
|
8311
|
+
columns: corpusManifest.sources
|
|
8312
|
+
};
|
|
8313
|
+
}
|
|
8314
|
+
function verifyItems(items, events) {
|
|
8315
|
+
const eventIds = new Set(events.map((event) => event.event_id));
|
|
8316
|
+
return items.map((item) => {
|
|
8317
|
+
const failed = item.cites.filter((cite) => !eventIds.has(cite)).map((cite) => ({ event_id_ref: cite, reason: "missing_event" }));
|
|
8318
|
+
return {
|
|
8319
|
+
finding_id: item.id,
|
|
8320
|
+
citations_total: item.cites.length,
|
|
8321
|
+
citations_resolved: item.cites.length - failed.length,
|
|
8322
|
+
citations_failed: failed,
|
|
8323
|
+
content_hashes_match: true,
|
|
8324
|
+
passed: item.cites.length > 0 && failed.length === 0
|
|
8325
|
+
};
|
|
8326
|
+
});
|
|
8327
|
+
}
|
|
8328
|
+
function criticForLoop(loop) {
|
|
8329
|
+
const survival = clamp(loop.confidence - (loop.cites.length <= 1 ? 0.08 : 0));
|
|
8330
|
+
return {
|
|
8331
|
+
finding_id: loop.loop_id,
|
|
8332
|
+
attack_vectors_attempted: [
|
|
8333
|
+
"is_this_actually_recurring",
|
|
8334
|
+
"is_this_actually_blocked",
|
|
8335
|
+
"is_the_intent_actually_what_we_say",
|
|
8336
|
+
"are_these_events_actually_related",
|
|
8337
|
+
"is_the_dollar_estimate_defensible",
|
|
8338
|
+
"would_orgx_actually_have_helped",
|
|
8339
|
+
"is_the_owner_actually_ambiguous",
|
|
8340
|
+
"is_the_recurrence_just_text_overlap"
|
|
8341
|
+
],
|
|
8342
|
+
weakest_claim: loop.cites.length <= 1 ? "Only one resolved citation supports this loop; chronology depth is limited." : "The loop is supported, but source coverage may still miss owner or verification context.",
|
|
8343
|
+
most_plausible_alternative: loop.cites.length <= 1 ? "This may be a single work signal rather than a recurring bottleneck." : "This could be normal staged execution rather than unresolved rework.",
|
|
8344
|
+
survival_score: Number(survival.toFixed(2)),
|
|
8345
|
+
survived: survival >= 0.6,
|
|
8346
|
+
demoted_to: survival >= 0.6 ? "public" : "weak_signal"
|
|
8347
|
+
};
|
|
8348
|
+
}
|
|
8349
|
+
function counterfactualForLoop(loop, family) {
|
|
8350
|
+
if (!loop.survived_critic || loop.cites.length === 0) return null;
|
|
8351
|
+
const repair = family?.orgx_repair ?? repairForFamily([loop], {
|
|
8352
|
+
time_saved_hours_per_week: 1,
|
|
8353
|
+
acceleration_percent: 10,
|
|
8354
|
+
estimated_monthly_value_usd: 800,
|
|
8355
|
+
confidence: loop.confidence,
|
|
8356
|
+
basis: [],
|
|
8357
|
+
assumptions: []
|
|
8358
|
+
});
|
|
8359
|
+
const realism = clamp(loop.confidence + (loop.terminal.state === "blocked" ? 0.06 : 0), 0, 0.92);
|
|
8360
|
+
if (realism < 0.7) return null;
|
|
8361
|
+
const entityKind = repair.named_orgx_capability.includes("decision") ? "decision" : repair.named_orgx_capability.includes("blocker") ? "task" : repair.named_orgx_capability.includes("artifact") ? "artifact" : "initiative";
|
|
8362
|
+
return {
|
|
8363
|
+
triggered_by_event_id: loop.origin.event_id,
|
|
8364
|
+
triggered_at: loop.origin.timestamp,
|
|
8365
|
+
actual_user_event_summary: `You worked on "${loop.origin.intent}" without a durable OrgX repair record tied to the source event.`,
|
|
8366
|
+
actual_outcome: loop.terminal.state === "blocked" ? "The loop stayed blocked or returned as new work." : "The work stayed visible in session evidence, but not as durable operating memory.",
|
|
8367
|
+
orgx_capability: {
|
|
8368
|
+
tool: repair.named_orgx_capability,
|
|
8369
|
+
args: repair.expected_tool_call_args,
|
|
8370
|
+
args_basis: ["loop.origin.intent", "loop.cites", "loop.terminal.state", "loop.bottleneck.class"]
|
|
8371
|
+
},
|
|
8372
|
+
orgx_outcome: repair.expected_outcome,
|
|
8373
|
+
resulting_entity: {
|
|
8374
|
+
kind: entityKind,
|
|
8375
|
+
inferred_id: `orgx_${entityKind}_${hash2(loop.loop_id, 12)}`,
|
|
8376
|
+
would_link_to: loop.cites
|
|
8377
|
+
},
|
|
8378
|
+
realism_score: Number(realism.toFixed(2)),
|
|
8379
|
+
realism_basis: [
|
|
8380
|
+
"The triggering event resolves to the normalized corpus.",
|
|
8381
|
+
"The proposed OrgX capability maps directly to the loop terminal state and bottleneck.",
|
|
8382
|
+
"The output is deterministic: create or link an owner-visible entity rather than asserting improvement."
|
|
8383
|
+
],
|
|
8384
|
+
could_have_failed_because: [
|
|
8385
|
+
"The user may not have granted write permission.",
|
|
8386
|
+
"The inferred title or owner might need human correction after claim.",
|
|
8387
|
+
"The source may lack enough downstream verification until GitHub or runtime hooks are connected."
|
|
8388
|
+
],
|
|
8389
|
+
generated_by_prompt_version: "orgx-investigation-counterfactual-v1",
|
|
8390
|
+
survived_critic: true
|
|
8391
|
+
};
|
|
8392
|
+
}
|
|
8393
|
+
function buildWhyNot100(input) {
|
|
8394
|
+
const entries = [];
|
|
8395
|
+
const singleSignal = input.loops.filter((loop) => loop.cites.length <= 1).length;
|
|
8396
|
+
const confluenceFamilies = input.families.filter((family) => family.cross_source_confluence).length;
|
|
8397
|
+
const fileEdits = input.corpus.totals.file_edits;
|
|
8398
|
+
if (confluenceFamilies === 0) {
|
|
8399
|
+
entries.push({
|
|
8400
|
+
dimension: "cross_source_confluence",
|
|
8401
|
+
current_score: 0,
|
|
8402
|
+
precise_gap: `0 cross-source loop families were proven; ${input.loops.length} loops still need a second source such as GitHub, Slack, or runtime hooks.`,
|
|
8403
|
+
user_action: {
|
|
8404
|
+
kind: "connect_source",
|
|
8405
|
+
target: "GitHub or Slack",
|
|
8406
|
+
ux_route: "/integrations",
|
|
8407
|
+
copy_for_button: "Connect proof source"
|
|
8408
|
+
},
|
|
8409
|
+
orgx_action: {
|
|
8410
|
+
kind: "auto_correlate",
|
|
8411
|
+
description: "OrgX will join session events to commits, approvals, and runtime writeback events.",
|
|
8412
|
+
triggers_when: "on_next_audit_run"
|
|
8413
|
+
},
|
|
8414
|
+
expected_score_lift: 22,
|
|
8415
|
+
expected_findings_unlocked: Math.max(1, Math.ceil(input.loops.length * 0.35)),
|
|
8416
|
+
preview_findings: [
|
|
8417
|
+
{
|
|
8418
|
+
title_redacted: "Session decision linked to commit proof",
|
|
8419
|
+
evidence_count_anticipated: Math.max(2, fileEdits || 2),
|
|
8420
|
+
confidence_anticipated: 0.82,
|
|
8421
|
+
derivation_basis: "extrapolated_from_existing"
|
|
8422
|
+
}
|
|
8423
|
+
],
|
|
8424
|
+
preconditions: ["connect_github_or_slack"],
|
|
8425
|
+
estimated_seconds_to_complete: 90
|
|
8426
|
+
});
|
|
8427
|
+
}
|
|
8428
|
+
if (singleSignal > 0) {
|
|
8429
|
+
entries.push({
|
|
8430
|
+
dimension: "chronology_depth",
|
|
8431
|
+
current_score: Math.max(1, 10 - Math.min(9, singleSignal)),
|
|
8432
|
+
precise_gap: `${singleSignal} work loop${singleSignal === 1 ? "" : "s"} have only one resolved event; OrgX can identify them but cannot yet prove before/after motion.`,
|
|
8433
|
+
user_action: {
|
|
8434
|
+
kind: "install_hook",
|
|
8435
|
+
target: "OrgX runtime hooks",
|
|
8436
|
+
ux_route: "/settings/integrations/orgx-runtime",
|
|
8437
|
+
copy_for_button: "Install runtime hooks"
|
|
8438
|
+
},
|
|
8439
|
+
orgx_action: {
|
|
8440
|
+
kind: "auto_writeback",
|
|
8441
|
+
description: "OrgX will append session-start, tool-use, stop, and outcome events to the same loop.",
|
|
8442
|
+
triggers_when: "on_user_action_completion"
|
|
8443
|
+
},
|
|
8444
|
+
expected_score_lift: Math.min(24, singleSignal * 3),
|
|
8445
|
+
expected_findings_unlocked: singleSignal,
|
|
8446
|
+
preview_findings: [
|
|
8447
|
+
{
|
|
8448
|
+
title_redacted: "Blocked loop gains start, retry, and resolution events",
|
|
8449
|
+
evidence_count_anticipated: 3,
|
|
8450
|
+
confidence_anticipated: 0.78,
|
|
8451
|
+
derivation_basis: "rule_based"
|
|
8452
|
+
}
|
|
8453
|
+
],
|
|
8454
|
+
preconditions: ["install_runtime_hook"],
|
|
8455
|
+
estimated_seconds_to_complete: 120
|
|
8456
|
+
});
|
|
8457
|
+
}
|
|
8458
|
+
if (input.coverage.missing.length > 0) {
|
|
8459
|
+
entries.push({
|
|
8460
|
+
dimension: "source_coverage",
|
|
8461
|
+
current_score: Math.max(0, 10 - input.coverage.missing.length * 2),
|
|
8462
|
+
precise_gap: `${input.coverage.missing.length} source gap${input.coverage.missing.length === 1 ? "" : "s"} remain: ${input.coverage.missing.join(", ")}.`,
|
|
8463
|
+
user_action: {
|
|
8464
|
+
kind: "connect_source",
|
|
8465
|
+
target: input.coverage.missing[0] ?? "missing source",
|
|
8466
|
+
ux_route: "/integrations",
|
|
8467
|
+
copy_for_button: "Connect missing source"
|
|
8468
|
+
},
|
|
8469
|
+
orgx_action: {
|
|
8470
|
+
kind: "auto_classify",
|
|
8471
|
+
description: "OrgX will classify ownership, handoff, and verification evidence from the newly connected source.",
|
|
8472
|
+
triggers_when: "on_next_audit_run"
|
|
8473
|
+
},
|
|
8474
|
+
expected_score_lift: Math.min(18, input.coverage.missing.length * 4),
|
|
8475
|
+
expected_findings_unlocked: Math.max(1, input.coverage.missing.length * 2),
|
|
8476
|
+
preview_findings: [
|
|
8477
|
+
{
|
|
8478
|
+
title_redacted: "Owner-visible handoff replaces inferred blocker state",
|
|
8479
|
+
evidence_count_anticipated: 2,
|
|
8480
|
+
confidence_anticipated: 0.8,
|
|
8481
|
+
derivation_basis: "rule_based"
|
|
8482
|
+
}
|
|
8483
|
+
],
|
|
8484
|
+
preconditions: ["authorize_source"],
|
|
8485
|
+
estimated_seconds_to_complete: 75
|
|
8486
|
+
});
|
|
8487
|
+
}
|
|
8488
|
+
return entries.slice(0, 6);
|
|
8489
|
+
}
|
|
8490
|
+
function buildRepairPlan(input) {
|
|
8491
|
+
const firstFamily = input.families.find((family) => family.public_surface) ?? input.families[0];
|
|
8492
|
+
const firstCounterfactual = input.counterfactuals[0];
|
|
8493
|
+
const actions = [];
|
|
8494
|
+
if (firstFamily || firstCounterfactual) {
|
|
8495
|
+
const closes = firstFamily?.loop_ids ?? (firstCounterfactual ? [firstCounterfactual.triggered_by_event_id] : []);
|
|
8496
|
+
actions.push({
|
|
8497
|
+
id: "repair:promote-loop",
|
|
8498
|
+
type: firstFamily?.orgx_repair.named_orgx_capability.includes("assign") ? "assign_owner" : "promote_decision",
|
|
8499
|
+
title: "Repair the top recurring work loop",
|
|
8500
|
+
closes_loop_ids: closes,
|
|
8501
|
+
expected_gain: "execution continuity",
|
|
8502
|
+
expected_hours_recovered: firstFamily?.orgx_repair.expected_hours_recovered ?? 0.8,
|
|
8503
|
+
expected_dollars_recovered: firstFamily?.orgx_repair.expected_dollars_recovered ?? 650,
|
|
8504
|
+
required_inputs: ["confirmed evidence", "owner or fallback owner"],
|
|
8505
|
+
confidence: firstCounterfactual?.realism_score ?? 0.72,
|
|
8506
|
+
time_to_value: "10 minutes after claim",
|
|
8507
|
+
preview_tree: [
|
|
8508
|
+
{ kind: "workstream", title: "Repair recurring AI work loop" },
|
|
8509
|
+
{ kind: "milestone", title: "Promote decision or blocker to durable record" },
|
|
8510
|
+
{ kind: "task", title: "Attach source evidence and owner-visible next step" }
|
|
8511
|
+
]
|
|
8512
|
+
});
|
|
8513
|
+
}
|
|
8514
|
+
const sourceGap = input.whyNot100.find((entry) => entry.dimension === "source_coverage" || entry.dimension === "cross_source_confluence");
|
|
8515
|
+
if (sourceGap) {
|
|
8516
|
+
actions.push({
|
|
8517
|
+
id: "repair:connect-source",
|
|
8518
|
+
type: "connect_source",
|
|
8519
|
+
title: sourceGap.user_action?.copy_for_button ?? "Connect missing proof source",
|
|
8520
|
+
closes_loop_ids: [],
|
|
8521
|
+
expected_gain: "source confidence",
|
|
8522
|
+
expected_hours_recovered: 0,
|
|
8523
|
+
expected_dollars_recovered: 0,
|
|
8524
|
+
required_inputs: [sourceGap.user_action?.target ?? "source authorization"],
|
|
8525
|
+
confidence: 0.78,
|
|
8526
|
+
time_to_value: `${Math.ceil(sourceGap.estimated_seconds_to_complete / 60)} minutes`,
|
|
8527
|
+
preview_tree: [
|
|
8528
|
+
{ kind: "workstream", title: "Connect source evidence" },
|
|
8529
|
+
{ kind: "task", title: "Correlate session events to proof, owner, and handoff signals" }
|
|
8530
|
+
]
|
|
8531
|
+
});
|
|
8532
|
+
}
|
|
8533
|
+
actions.push({
|
|
8534
|
+
id: "repair:launch-profile",
|
|
8535
|
+
type: "convert_to_initiative",
|
|
8536
|
+
title: "Launch from this investigation",
|
|
8537
|
+
closes_loop_ids: firstFamily?.loop_ids ?? [],
|
|
8538
|
+
expected_gain: "initiative readiness",
|
|
8539
|
+
expected_hours_recovered: firstFamily?.orgx_repair.expected_hours_recovered ?? 0,
|
|
8540
|
+
expected_dollars_recovered: firstFamily?.orgx_repair.expected_dollars_recovered ?? 0,
|
|
8541
|
+
required_inputs: ["claim profile", "approve repair plan"],
|
|
8542
|
+
confidence: 0.7,
|
|
8543
|
+
time_to_value: "1 click after claim",
|
|
8544
|
+
preview_tree: [
|
|
8545
|
+
{ kind: "workstream", title: "Investigation to durable OrgX initiative" },
|
|
8546
|
+
{ kind: "milestone", title: "Convert loop family into assigned work" },
|
|
8547
|
+
{ kind: "task", title: "Close the highest-confidence counterfactual gap" }
|
|
8548
|
+
]
|
|
8549
|
+
});
|
|
8550
|
+
return actions.slice(0, 3);
|
|
8551
|
+
}
|
|
8552
|
+
function buildMirror(input) {
|
|
8553
|
+
const topFamily = input.families.find((family) => family.public_surface) ?? input.families[0];
|
|
8554
|
+
const topLoop = input.loops[0];
|
|
8555
|
+
const sourceCount = input.corpus.sources.filter((source) => source.status === "connected" || source.status === "partial").length;
|
|
8556
|
+
const dropped = input.loops.filter((loop) => !loop.survived_critic).length;
|
|
8557
|
+
const text2 = [
|
|
8558
|
+
`You have AI-assisted work spread across ${sourceCount} connected or partial source${sourceCount === 1 ? "" : "s"}, but the execution record is still incomplete.`,
|
|
8559
|
+
topFamily ? `The clearest repeated loop is "${topFamily.semantic_centroid}", with ${topFamily.appearances} appearance${topFamily.appearances === 1 ? "" : "s"} and a ${topFamily.shared_terminal_state} terminal state.` : topLoop ? `The clearest work loop is "${topLoop.origin.intent}", but it still needs more chronology before OrgX should call it recurring.` : "The corpus did not produce a verified work loop yet.",
|
|
8560
|
+
input.counterfactuals[0] ? `OrgX can point to the exact event where it would have called ${input.counterfactuals[0].orgx_capability.tool} and what entity it would have created.` : "Counterfactual repair is waiting on a higher-confidence loop with resolved citations.",
|
|
8561
|
+
`The current estimate is ${input.impact.time_saved_hours_per_week} recoverable hours/week, grounded in ${input.impact.basis[0] ?? "resolved work-loop evidence"}.`,
|
|
8562
|
+
dropped > 0 ? `${dropped} weak signal${dropped === 1 ? " was" : "s were"} kept out of the public readout because the citations or critic score did not clear the bar.` : "Every surfaced loop cleared citation verification and the critic floor."
|
|
8563
|
+
].join(" ");
|
|
8564
|
+
return {
|
|
8565
|
+
text: text2,
|
|
8566
|
+
evidence_pills: [
|
|
8567
|
+
{
|
|
8568
|
+
phrase: `${input.loops.length} work loop${input.loops.length === 1 ? "" : "s"}`,
|
|
8569
|
+
cites: input.loops.flatMap((loop) => loop.cites).slice(0, 12)
|
|
8570
|
+
},
|
|
8571
|
+
{
|
|
8572
|
+
phrase: `${sourceCount} source${sourceCount === 1 ? "" : "s"}`,
|
|
8573
|
+
cites: []
|
|
8574
|
+
},
|
|
8575
|
+
{
|
|
8576
|
+
phrase: `${input.counterfactuals.length} earned counterfactual${input.counterfactuals.length === 1 ? "" : "s"}`,
|
|
8577
|
+
cites: input.counterfactuals.map((item) => item.triggered_by_event_id)
|
|
8578
|
+
}
|
|
8579
|
+
]
|
|
8580
|
+
};
|
|
8581
|
+
}
|
|
8582
|
+
function buildWorkGraphInvestigation(input) {
|
|
8583
|
+
const auditId = `wgi_${hash2([input.fingerprint, input.generatedAt], 24)}`;
|
|
8584
|
+
const rawEvents = buildRawEvents(input);
|
|
8585
|
+
const corpus = buildCorpusManifest({
|
|
8586
|
+
auditId,
|
|
8587
|
+
auditMethod: input.auditMethod,
|
|
8588
|
+
clientExtractions: input.clientExtractions,
|
|
8589
|
+
coverage: input.coverage,
|
|
8590
|
+
events: rawEvents,
|
|
8591
|
+
generatedAt: input.generatedAt
|
|
8592
|
+
});
|
|
8593
|
+
const loops = buildWorkLoops({ events: rawEvents, findings: input.findings, trails: input.trails });
|
|
8594
|
+
const families = buildLoopFamilies(loops, rawEvents, input.impact);
|
|
8595
|
+
const usage = buildUsageCatalogue(rawEvents, input.findings);
|
|
8596
|
+
const sourceConfidence = buildSourceConfidence(corpus);
|
|
8597
|
+
const loopCritics = loops.map(criticForLoop);
|
|
8598
|
+
const familyByLoop = /* @__PURE__ */ new Map();
|
|
8599
|
+
for (const family of families) {
|
|
8600
|
+
for (const loopId of family.loop_ids) familyByLoop.set(loopId, family);
|
|
8601
|
+
}
|
|
8602
|
+
const verifiedLoops = loops.filter((loop) => {
|
|
8603
|
+
const critic = loopCritics.find((entry) => entry.finding_id === loop.loop_id);
|
|
8604
|
+
return loop.public_surface && critic?.survived;
|
|
8605
|
+
});
|
|
8606
|
+
const counterfactuals = verifiedLoops.map((loop) => counterfactualForLoop(loop, familyByLoop.get(loop.loop_id))).filter((item) => Boolean(item)).slice(0, 8);
|
|
8607
|
+
const verificationItems = [
|
|
8608
|
+
...loops.map((loop) => ({ id: loop.loop_id, cites: loop.cites })),
|
|
8609
|
+
...counterfactuals.map((item) => ({
|
|
8610
|
+
id: `counterfactual:${item.resulting_entity.inferred_id}`,
|
|
8611
|
+
cites: [item.triggered_by_event_id]
|
|
8612
|
+
}))
|
|
8613
|
+
];
|
|
8614
|
+
const verification = verifyItems(verificationItems, rawEvents);
|
|
8615
|
+
const whyNot100 = buildWhyNot100({
|
|
8616
|
+
corpus,
|
|
8617
|
+
coverage: input.coverage,
|
|
8618
|
+
loops,
|
|
8619
|
+
families,
|
|
8620
|
+
impact: input.impact
|
|
8621
|
+
});
|
|
8622
|
+
const repairPlan = buildRepairPlan({ counterfactuals, families, whyNot100 });
|
|
8623
|
+
const mirror = buildMirror({
|
|
8624
|
+
loops,
|
|
8625
|
+
families,
|
|
8626
|
+
counterfactuals,
|
|
8627
|
+
corpus,
|
|
8628
|
+
impact: input.impact
|
|
8629
|
+
});
|
|
8630
|
+
const eventBySource = countBy(rawEvents.map((event) => event.source_id)).map(({ key, count }) => ({
|
|
8631
|
+
source_id: key,
|
|
8632
|
+
count
|
|
8633
|
+
}));
|
|
8634
|
+
const eventByKind = countBy(rawEvents.map((event) => event.kind)).map(({ key, count }) => ({
|
|
8635
|
+
kind: key,
|
|
8636
|
+
count
|
|
8637
|
+
}));
|
|
8638
|
+
return {
|
|
8639
|
+
schema_version: WORK_GRAPH_INVESTIGATION_SCHEMA_VERSION,
|
|
8640
|
+
audit_id: auditId,
|
|
8641
|
+
fingerprint: input.fingerprint,
|
|
8642
|
+
generated_at: input.generatedAt,
|
|
8643
|
+
corpus_manifest: corpus,
|
|
8644
|
+
raw_events_summary: {
|
|
8645
|
+
count: rawEvents.length,
|
|
8646
|
+
by_source: eventBySource,
|
|
8647
|
+
by_kind: eventByKind,
|
|
8648
|
+
earliest: corpus.totals.earliest_event,
|
|
8649
|
+
latest: corpus.totals.latest_event
|
|
8650
|
+
},
|
|
8651
|
+
raw_events: rawEvents.slice(0, 500),
|
|
8652
|
+
work_loops: loops,
|
|
8653
|
+
loop_families: families,
|
|
8654
|
+
usage_catalogue: usage,
|
|
8655
|
+
source_confidence: sourceConfidence,
|
|
8656
|
+
why_not_100: whyNot100,
|
|
8657
|
+
counterfactuals,
|
|
8658
|
+
critic_log: [
|
|
8659
|
+
...loopCritics,
|
|
8660
|
+
...families.map((family) => ({
|
|
8661
|
+
finding_id: family.family_id,
|
|
8662
|
+
attack_vectors_attempted: [
|
|
8663
|
+
"is_this_actually_recurring",
|
|
8664
|
+
"is_the_recurrence_just_text_overlap",
|
|
8665
|
+
"are_these_events_actually_related"
|
|
8666
|
+
],
|
|
8667
|
+
weakest_claim: family.appearances < 3 ? "The family has fewer than 3 appearances and should not be public as recurrence." : "The family still depends on source normalization and may need human correction.",
|
|
8668
|
+
most_plausible_alternative: family.appearances < 3 ? "This is a single signal or thin pair, not a real recurring loop." : "The loops may be related staged work rather than repeated unresolved work.",
|
|
8669
|
+
survival_score: family.survived_critic ? 0.72 : 0.52,
|
|
8670
|
+
survived: family.survived_critic,
|
|
8671
|
+
demoted_to: family.public_surface ? "public" : "weak_signal"
|
|
8672
|
+
}))
|
|
8673
|
+
],
|
|
8674
|
+
verification_log: verification,
|
|
8675
|
+
mirror_paragraph: mirror,
|
|
8676
|
+
repair_plan: repairPlan,
|
|
8677
|
+
impact_projection: {
|
|
8678
|
+
hours_recoverable_per_week: {
|
|
8679
|
+
value: input.impact.time_saved_hours_per_week,
|
|
8680
|
+
basis: input.impact.basis.join(" "),
|
|
8681
|
+
confidence: input.impact.confidence
|
|
8682
|
+
},
|
|
8683
|
+
dollars_recoverable_per_month: {
|
|
8684
|
+
value: input.impact.estimated_monthly_value_usd,
|
|
8685
|
+
basis: "hours_recoverable_per_week * 4.33 weeks * blended operator hourly value",
|
|
8686
|
+
confidence: input.impact.confidence
|
|
8687
|
+
},
|
|
8688
|
+
acceleration_pct: {
|
|
8689
|
+
value: input.impact.acceleration_percent,
|
|
8690
|
+
basis: "directional execution lift from repairable loops, source coverage, and automation potential",
|
|
8691
|
+
confidence: input.impact.confidence
|
|
8692
|
+
}
|
|
8693
|
+
},
|
|
8694
|
+
redaction_log: [
|
|
8695
|
+
{ kind: "raw_transcripts_excluded", count: 1 },
|
|
8696
|
+
{ kind: "redacted_event_payloads", count: rawEvents.length }
|
|
8697
|
+
],
|
|
8698
|
+
raw_transcripts_excluded: true,
|
|
8699
|
+
claimable: loops.some((loop) => loop.public_surface)
|
|
8700
|
+
};
|
|
8701
|
+
}
|
|
8702
|
+
|
|
8703
|
+
// src/lib/work-graph.ts
|
|
8704
|
+
var WORK_GRAPH_SCHEMA_VERSION = "2.0.0";
|
|
7003
8705
|
var WORK_GRAPH_FINGERPRINT_VERSION = "wgf_v1";
|
|
7004
|
-
var WORK_GRAPH_EXTRACTION_SCHEMA_VERSION = "
|
|
8706
|
+
var WORK_GRAPH_EXTRACTION_SCHEMA_VERSION = "2.0.0.investigation";
|
|
7005
8707
|
var WORK_GRAPH_FINDING_TYPES = [
|
|
7006
8708
|
"action",
|
|
7007
8709
|
"decision",
|
|
@@ -7019,7 +8721,7 @@ function clampScore2(value) {
|
|
|
7019
8721
|
return Math.max(0, Math.min(100, Math.round(value)));
|
|
7020
8722
|
}
|
|
7021
8723
|
function hashJson(value) {
|
|
7022
|
-
return
|
|
8724
|
+
return createHash6("sha256").update(JSON.stringify(value)).digest("hex");
|
|
7023
8725
|
}
|
|
7024
8726
|
function normalizeFingerprintText(value) {
|
|
7025
8727
|
return value.toLowerCase().replace(/https?:\/\/\S+/g, "url").replace(/[0-9a-f]{12,}/g, "hash").replace(/\b[0-9a-f]{8}-[0-9a-f-]{27,}\b/g, "uuid").replace(/\s+/g, " ").trim().slice(0, 600);
|
|
@@ -7040,6 +8742,10 @@ function sourceClientForImport(source) {
|
|
|
7040
8742
|
if (raw.includes("claude-code")) return "claude-code";
|
|
7041
8743
|
if (raw.includes("claude")) return "claude";
|
|
7042
8744
|
if (raw.includes("cursor")) return "cursor";
|
|
8745
|
+
if (raw.includes("opencode")) return "opencode";
|
|
8746
|
+
if (raw.includes("goose")) return "goose";
|
|
8747
|
+
if (raw.includes("opencode")) return "opencode";
|
|
8748
|
+
if (raw.includes("goose")) return "goose";
|
|
7043
8749
|
if (raw.includes("openclaw")) return "openclaw";
|
|
7044
8750
|
if (raw.includes("slack")) return "slack";
|
|
7045
8751
|
if (raw.includes("github")) return "github";
|
|
@@ -7056,12 +8762,14 @@ function sourceClientForImport(source) {
|
|
|
7056
8762
|
function normalizeSourceClient(value) {
|
|
7057
8763
|
if (typeof value !== "string") return "unknown";
|
|
7058
8764
|
const normalized = value.trim().toLowerCase();
|
|
7059
|
-
if (normalized === "codex" || normalized === "claude" || normalized === "claude-code" || normalized === "cursor" || normalized === "openclaw" || normalized === "slack" || normalized === "mcp" || normalized === "github" || normalized === "linear" || normalized === "gmail" || normalized === "calendar" || normalized === "notion" || normalized === "docs" || normalized === "manual" || normalized === "wizard" || normalized === "api") {
|
|
8765
|
+
if (normalized === "codex" || normalized === "claude" || normalized === "claude-code" || normalized === "cursor" || normalized === "opencode" || normalized === "goose" || normalized === "openclaw" || normalized === "slack" || normalized === "mcp" || normalized === "orgx_runtime_hook" || normalized === "github" || normalized === "linear" || normalized === "gmail" || normalized === "calendar" || normalized === "notion" || normalized === "docs" || normalized === "manual" || normalized === "wizard" || normalized === "api") {
|
|
7060
8766
|
return normalized;
|
|
7061
8767
|
}
|
|
7062
8768
|
if (normalized.includes("claude")) return "claude";
|
|
7063
8769
|
if (normalized.includes("codex")) return "codex";
|
|
7064
8770
|
if (normalized.includes("cursor")) return "cursor";
|
|
8771
|
+
if (normalized.includes("opencode")) return "opencode";
|
|
8772
|
+
if (normalized.includes("goose")) return "goose";
|
|
7065
8773
|
if (normalized.includes("slack")) return "slack";
|
|
7066
8774
|
if (normalized.includes("github")) return "github";
|
|
7067
8775
|
if (normalized.includes("linear")) return "linear";
|
|
@@ -7070,6 +8778,7 @@ function normalizeSourceClient(value) {
|
|
|
7070
8778
|
if (normalized.includes("notion")) return "notion";
|
|
7071
8779
|
if (normalized.includes("doc")) return "docs";
|
|
7072
8780
|
if (normalized.includes("mcp")) return "mcp";
|
|
8781
|
+
if (normalized.includes("runtime") || normalized.includes("hook")) return "orgx_runtime_hook";
|
|
7073
8782
|
return "unknown";
|
|
7074
8783
|
}
|
|
7075
8784
|
function sourceClientFromText(value) {
|
|
@@ -7077,6 +8786,8 @@ function sourceClientFromText(value) {
|
|
|
7077
8786
|
if (/\bclaude(?:[- ]code)?\b|\.claude\/projects|claude:/.test(normalized)) return "claude";
|
|
7078
8787
|
if (/\bcodex\b|\.codex\/sessions|rollout-/.test(normalized)) return "codex";
|
|
7079
8788
|
if (/\bcursor\b/.test(normalized)) return "cursor";
|
|
8789
|
+
if (/\bopencode\b/.test(normalized)) return "opencode";
|
|
8790
|
+
if (/\bgoose\b/.test(normalized)) return "goose";
|
|
7080
8791
|
if (/\bopenclaw\b/.test(normalized)) return "openclaw";
|
|
7081
8792
|
if (/\bslack\b/.test(normalized)) return "slack";
|
|
7082
8793
|
if (/\bgithub\b|\bgit:|pull request|commit\b/.test(normalized)) return "github";
|
|
@@ -7085,7 +8796,7 @@ function sourceClientFromText(value) {
|
|
|
7085
8796
|
if (/\bcalendar\b|\bmeeting\b/.test(normalized)) return "calendar";
|
|
7086
8797
|
if (/\bnotion\b/.test(normalized)) return "notion";
|
|
7087
8798
|
if (/\bdocs?\b|google drive/.test(normalized)) return "docs";
|
|
7088
|
-
if (/\bmcp\b|mcp__|orgx_emit|
|
|
8799
|
+
if (/\bmcp\b|mcp__|orgx_emit|orgx_write|ship_batch/.test(normalized)) return "mcp";
|
|
7089
8800
|
if (/\borgx api\b|\bapi\b/.test(normalized)) return "api";
|
|
7090
8801
|
return "unknown";
|
|
7091
8802
|
}
|
|
@@ -7116,11 +8827,11 @@ function normalizeConfidence(value, fallback = 0.72) {
|
|
|
7116
8827
|
}
|
|
7117
8828
|
function titleFromText(text2, fallback) {
|
|
7118
8829
|
const lower = text2.toLowerCase();
|
|
7119
|
-
if (lower.includes("
|
|
7120
|
-
return "OrgX MCP
|
|
8830
|
+
if (lower.includes("mcp__orgx__orgx_search") && lower.includes("zod")) {
|
|
8831
|
+
return "OrgX MCP orgx_search is failing schema validation";
|
|
7121
8832
|
}
|
|
7122
|
-
if (lower.includes("
|
|
7123
|
-
return "
|
|
8833
|
+
if (lower.includes("orgx_write") && lower.includes("auto_continue") && lower.includes("dispatch")) {
|
|
8834
|
+
return "orgx_write creates ready streams without dispatching agent runs";
|
|
7124
8835
|
}
|
|
7125
8836
|
if (lower.includes("operation qa loop") && lower.includes("0/") && lower.includes("entities")) {
|
|
7126
8837
|
return "OrgX scaffold fails to create Operation QA Loop entities";
|
|
@@ -7219,7 +8930,7 @@ function buildWorkGraphExtractionProtocol() {
|
|
|
7219
8930
|
required_output: {
|
|
7220
8931
|
schema_version: WORK_GRAPH_EXTRACTION_SCHEMA_VERSION,
|
|
7221
8932
|
extraction_id: "stable id for this extraction run",
|
|
7222
|
-
source_client: "codex | claude | claude-code | cursor | openclaw | slack | mcp | github | linear | gmail | calendar | notion | docs | manual | api | unknown",
|
|
8933
|
+
source_client: "codex | claude | claude-code | cursor | opencode | goose | openclaw | slack | mcp | github | linear | gmail | calendar | notion | docs | manual | api | unknown",
|
|
7223
8934
|
source_label: "human-readable source label",
|
|
7224
8935
|
searched_sources: ["session/log/source group names searched"],
|
|
7225
8936
|
search_queries: [
|
|
@@ -7336,7 +9047,7 @@ function buildCoverage(imports, connectedSources, missingSources, clientExtracti
|
|
|
7336
9047
|
${extractionText}`.toLowerCase();
|
|
7337
9048
|
const orgxObserved = /\borgx\b|useorgx|mcp__orgx__|orgx_/i.test(allText);
|
|
7338
9049
|
const mcpObserved = /\bmcp\b|mcp__|tool call|tools\/call|call_tool|orgx_emit_activity/i.test(allText);
|
|
7339
|
-
const orgxMcpCalled = /mcp__orgx__|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|
|
|
9050
|
+
const orgxMcpCalled = /mcp__orgx__|orgx_emit_activity|orgx_apply_changeset|complete_with_proof|orgx_write/i.test(allText);
|
|
7340
9051
|
const skillOnlySignal = orgxObserved && !orgxMcpCalled && /\bskill|instructions|agent|workflow\b/i.test(allText);
|
|
7341
9052
|
const normalizedConnectedSources = sortedUnique(
|
|
7342
9053
|
connectedSources.map((source) => {
|
|
@@ -7348,8 +9059,12 @@ ${extractionText}`.toLowerCase();
|
|
|
7348
9059
|
...normalizedConnectedSources,
|
|
7349
9060
|
...sourceClients.includes("codex") ? ["Codex sessions"] : [],
|
|
7350
9061
|
...sourceClients.includes("claude") || sourceClients.includes("claude-code") ? ["Claude Code sessions"] : [],
|
|
9062
|
+
...sourceClients.includes("cursor") ? ["Cursor workspace evidence"] : [],
|
|
9063
|
+
...sourceClients.includes("opencode") ? ["OpenCode sessions"] : [],
|
|
9064
|
+
...sourceClients.includes("goose") ? ["goose sessions"] : [],
|
|
7351
9065
|
...sourceClients.includes("github") ? ["Git/GitHub proof"] : [],
|
|
7352
9066
|
...sourceClients.includes("mcp") ? ["MCP tool telemetry"] : [],
|
|
9067
|
+
...sourceClients.includes("orgx_runtime_hook") ? ["OrgX runtime hook replay"] : [],
|
|
7353
9068
|
...sourceClients.includes("slack") ? ["Slack coordination"] : []
|
|
7354
9069
|
];
|
|
7355
9070
|
const inferredMissing = [
|
|
@@ -7369,7 +9084,7 @@ ${extractionText}`.toLowerCase();
|
|
|
7369
9084
|
});
|
|
7370
9085
|
const partialCount = manifests.filter((manifest) => manifest.status === "partial").length;
|
|
7371
9086
|
const coverageScore = clampScore2(
|
|
7372
|
-
28 + Math.min(34, connected.length * 7) + Math.min(18, findings.length * 2) + (sourceClients.includes("codex") ? 6 : 0) + (sourceClients.includes("claude") || sourceClients.includes("claude-code") ? 6 : 0) - missing.length * 7 - partialCount * 3
|
|
9087
|
+
28 + Math.min(34, connected.length * 7) + Math.min(18, findings.length * 2) + (sourceClients.includes("codex") ? 6 : 0) + (sourceClients.includes("claude") || sourceClients.includes("claude-code") ? 6 : 0) + (sourceClients.includes("cursor") ? 4 : 0) + (sourceClients.includes("opencode") ? 4 : 0) + (sourceClients.includes("goose") ? 4 : 0) - missing.length * 7 - partialCount * 3
|
|
7373
9088
|
);
|
|
7374
9089
|
return {
|
|
7375
9090
|
connected,
|
|
@@ -7466,7 +9181,7 @@ function buildSourceCoverageManifests(input) {
|
|
|
7466
9181
|
});
|
|
7467
9182
|
}
|
|
7468
9183
|
function canonicalSourceManifestLabel(manifest) {
|
|
7469
|
-
if (manifest.source_client === "codex" || manifest.source_client === "claude" || manifest.source_client === "claude-code") {
|
|
9184
|
+
if (manifest.source_client === "codex" || manifest.source_client === "claude" || manifest.source_client === "claude-code" || manifest.source_client === "cursor" || manifest.source_client === "opencode" || manifest.source_client === "goose") {
|
|
7470
9185
|
return labelForSourceClient(manifest.source_client);
|
|
7471
9186
|
}
|
|
7472
9187
|
if (manifest.source_client === "github" || manifest.source_client === "slack" || manifest.source_client === "mcp") {
|
|
@@ -7481,8 +9196,16 @@ function labelForSourceClient(sourceClient) {
|
|
|
7481
9196
|
case "claude":
|
|
7482
9197
|
case "claude-code":
|
|
7483
9198
|
return "Claude Code sessions";
|
|
9199
|
+
case "cursor":
|
|
9200
|
+
return "Cursor workspace evidence";
|
|
9201
|
+
case "opencode":
|
|
9202
|
+
return "OpenCode sessions";
|
|
9203
|
+
case "goose":
|
|
9204
|
+
return "goose sessions";
|
|
7484
9205
|
case "mcp":
|
|
7485
9206
|
return "MCP tool telemetry";
|
|
9207
|
+
case "orgx_runtime_hook":
|
|
9208
|
+
return "OrgX runtime hook replay";
|
|
7486
9209
|
case "github":
|
|
7487
9210
|
return "Git/GitHub proof";
|
|
7488
9211
|
case "slack":
|
|
@@ -7548,7 +9271,9 @@ function numberFromImportMetadata(source, key) {
|
|
|
7548
9271
|
}
|
|
7549
9272
|
function buildAuditMethod(input) {
|
|
7550
9273
|
const extractionSummaries = summarizeClientExtractions(input.clientExtractions);
|
|
7551
|
-
const nativePacks = extractionSummaries.filter(
|
|
9274
|
+
const nativePacks = extractionSummaries.filter(
|
|
9275
|
+
(summary) => summary.source_client === "codex" || summary.source_client === "claude" || summary.source_client === "claude-code" || summary.source_client === "cursor" || summary.source_client === "opencode" || summary.source_client === "goose"
|
|
9276
|
+
).map((summary) => ({
|
|
7552
9277
|
source_client: summary.source_client,
|
|
7553
9278
|
source_label: summary.source_label,
|
|
7554
9279
|
searched_session_count: summary.searched_session_count,
|
|
@@ -7658,7 +9383,7 @@ function nativeEpisodeType(line) {
|
|
|
7658
9383
|
function nativeFindingConfidence(type, line) {
|
|
7659
9384
|
let confidence = type === "decision" || type === "artifact" || type === "outcome" ? 0.78 : 0.72;
|
|
7660
9385
|
if (/^\s*(?:decision|artifact|blocker|outcome|proof|result|next action|open loop|risk|gap)\s*:/i.test(line)) confidence += 0.08;
|
|
7661
|
-
if (/\b(?:mcp__orgx__|
|
|
9386
|
+
if (/\b(?:mcp__orgx__|orgx_write|orgx_emit_activity|complete_with_proof|github|codex|claude)\b/i.test(line)) confidence += 0.05;
|
|
7662
9387
|
if (line.length < 32) confidence -= 0.1;
|
|
7663
9388
|
return normalizeConfidence(confidence, 0.72);
|
|
7664
9389
|
}
|
|
@@ -7875,8 +9600,8 @@ var SKILL_TOOL_RULES = [
|
|
|
7875
9600
|
{ id: "agent:design", kind: "agent", label: "design-agent", pattern: /\bdesign-agent\b|design agent/i },
|
|
7876
9601
|
{ id: "agent:product", kind: "agent", label: "product-agent", pattern: /\bproduct-agent\b|product agent/i },
|
|
7877
9602
|
{ id: "agent:orchestrator", kind: "agent", label: "orchestrator-agent", pattern: /\borchestrator-agent\b|orchestrator agent/i },
|
|
7878
|
-
{ id: "tool:orgx-list-entities", kind: "mcp_tool", label: "
|
|
7879
|
-
{ id: "tool:scaffold", kind: "mcp_tool", label: "
|
|
9603
|
+
{ id: "tool:orgx-list-entities", kind: "mcp_tool", label: "mcp__orgx__orgx_search", pattern: /\bmcp__orgx__orgx_search\b/i },
|
|
9604
|
+
{ id: "tool:scaffold", kind: "mcp_tool", label: "orgx_write", pattern: /\bscaffold_initiative\b/i },
|
|
7880
9605
|
{ id: "tool:complete-proof", kind: "mcp_tool", label: "complete_with_proof", pattern: /\bcomplete_with_proof\b/i },
|
|
7881
9606
|
{ id: "tool:ship-batch", kind: "mcp_tool", label: "ship_batch", pattern: /\bship_batch\b/i },
|
|
7882
9607
|
{ id: "client:codex", kind: "client_tool", label: "Codex", pattern: /\bcodex\b/i },
|
|
@@ -8674,7 +10399,7 @@ function publicTrailRank(trail) {
|
|
|
8674
10399
|
let score = trail.impact_score;
|
|
8675
10400
|
if (trail.events.length > 1) score += 10;
|
|
8676
10401
|
if (trail.subject_entity_type === "blocker") score += 6;
|
|
8677
|
-
if (/\b(?:scaffold|ship_batch|
|
|
10402
|
+
if (/\b(?:scaffold|ship_batch|mcp__orgx__orgx_search|list entities|schema validation|route behavior|dispatching agent runs|operation qa loop)\b/i.test(title)) {
|
|
8678
10403
|
score += 14;
|
|
8679
10404
|
}
|
|
8680
10405
|
if (/^(?:[-*✓{`'"]|\d+[,.]?$)/.test(title)) score -= 32;
|
|
@@ -8932,7 +10657,7 @@ function buildAgentNodes(findings) {
|
|
|
8932
10657
|
);
|
|
8933
10658
|
const sourceAgents = sortedUnique(
|
|
8934
10659
|
findings.map(
|
|
8935
|
-
(finding) => ["codex", "claude", "claude-code", "cursor", "openclaw"].includes(finding.source_client) ? finding.source_client : ""
|
|
10660
|
+
(finding) => ["codex", "claude", "claude-code", "cursor", "opencode", "goose", "openclaw"].includes(finding.source_client) ? finding.source_client : ""
|
|
8936
10661
|
).filter(Boolean)
|
|
8937
10662
|
);
|
|
8938
10663
|
return [...actorIds, ...sourceAgents].slice(0, 20).map((agent) => ({
|
|
@@ -9250,6 +10975,20 @@ function buildSessionReconciliationReport(input) {
|
|
|
9250
10975
|
};
|
|
9251
10976
|
const reportHash = hashJson(reportSeed);
|
|
9252
10977
|
const sessionId = input.sessionId ?? `work-graph-${reportHash.slice(0, 16)}`;
|
|
10978
|
+
const investigation = buildWorkGraphInvestigation({
|
|
10979
|
+
auditMethod,
|
|
10980
|
+
clientExtractions: clientExtractionSummaries,
|
|
10981
|
+
coverage,
|
|
10982
|
+
events,
|
|
10983
|
+
findings: allFindings,
|
|
10984
|
+
fingerprint: fingerprint.fingerprint,
|
|
10985
|
+
generatedAt,
|
|
10986
|
+
impact: impactProjection,
|
|
10987
|
+
patterns: recurringPatterns,
|
|
10988
|
+
...input.investigationRawEvents ? { rawEvents: input.investigationRawEvents } : {},
|
|
10989
|
+
recommendations,
|
|
10990
|
+
trails
|
|
10991
|
+
});
|
|
9253
10992
|
return {
|
|
9254
10993
|
schema_version: WORK_GRAPH_SCHEMA_VERSION,
|
|
9255
10994
|
report_id: reportHash.slice(0, 24),
|
|
@@ -9281,6 +11020,7 @@ function buildSessionReconciliationReport(input) {
|
|
|
9281
11020
|
opportunity_score: opportunityScore,
|
|
9282
11021
|
execution_quality: executionQuality,
|
|
9283
11022
|
impact_projection: impactProjection,
|
|
11023
|
+
investigation,
|
|
9284
11024
|
initiative_kickoffs: initiativeKickoffs,
|
|
9285
11025
|
redaction_level: "summary_only",
|
|
9286
11026
|
raw_transcripts_sent: false
|
|
@@ -9328,7 +11068,7 @@ function renderWorkGraphExtractionProtocolMarkdown(protocol = buildWorkGraphExtr
|
|
|
9328
11068
|
}
|
|
9329
11069
|
function renderWorkGraphMarkdown(report) {
|
|
9330
11070
|
const lines = [];
|
|
9331
|
-
lines.push("# OrgX
|
|
11071
|
+
lines.push("# OrgX Investigation Engine");
|
|
9332
11072
|
lines.push("");
|
|
9333
11073
|
lines.push(`Generated: ${report.generated_at}`);
|
|
9334
11074
|
lines.push(`Workspace: ${report.workspace.name} (${report.workspace.id})`);
|
|
@@ -9359,6 +11099,44 @@ function renderWorkGraphMarkdown(report) {
|
|
|
9359
11099
|
lines.push(`- ${note}`);
|
|
9360
11100
|
}
|
|
9361
11101
|
lines.push("");
|
|
11102
|
+
lines.push("## Investigation v2");
|
|
11103
|
+
lines.push("");
|
|
11104
|
+
lines.push(`Schema: ${report.investigation.schema_version}`);
|
|
11105
|
+
lines.push(`Audit ID: ${report.investigation.audit_id}`);
|
|
11106
|
+
lines.push(`Raw events normalized: ${report.investigation.raw_events_summary.count}`);
|
|
11107
|
+
lines.push(`Work loops: ${report.investigation.work_loops.length}`);
|
|
11108
|
+
lines.push(`Recurring loop families: ${report.investigation.loop_families.filter((family) => family.public_surface).length}`);
|
|
11109
|
+
const passedVerification = report.investigation.verification_log.filter((entry) => entry.passed).length;
|
|
11110
|
+
const droppedVerification = report.investigation.verification_log.length - passedVerification;
|
|
11111
|
+
lines.push(`Verification: ${passedVerification} passed, ${droppedVerification} dropped as unverifiable`);
|
|
11112
|
+
lines.push(`Earned counterfactuals: ${report.investigation.counterfactuals.length}`);
|
|
11113
|
+
lines.push("");
|
|
11114
|
+
lines.push("Mirror:");
|
|
11115
|
+
lines.push(report.investigation.mirror_paragraph.text);
|
|
11116
|
+
lines.push("");
|
|
11117
|
+
if (report.investigation.counterfactuals[0]) {
|
|
11118
|
+
const counterfactual = report.investigation.counterfactuals[0];
|
|
11119
|
+
lines.push("Top earned counterfactual:");
|
|
11120
|
+
lines.push(`- Trigger: ${counterfactual.triggered_by_event_id} at ${counterfactual.triggered_at}`);
|
|
11121
|
+
lines.push(`- Actual: ${counterfactual.actual_outcome}`);
|
|
11122
|
+
lines.push(`- OrgX would call: ${counterfactual.orgx_capability.tool}`);
|
|
11123
|
+
lines.push(`- Outcome: ${counterfactual.orgx_outcome}`);
|
|
11124
|
+
lines.push("");
|
|
11125
|
+
}
|
|
11126
|
+
if (report.investigation.why_not_100.length > 0) {
|
|
11127
|
+
lines.push("What improves it:");
|
|
11128
|
+
for (const gap of report.investigation.why_not_100) {
|
|
11129
|
+
lines.push(`- ${gap.precise_gap} ${gap.user_action ? `Action: ${gap.user_action.copy_for_button} (${gap.user_action.ux_route}).` : ""}`);
|
|
11130
|
+
}
|
|
11131
|
+
lines.push("");
|
|
11132
|
+
}
|
|
11133
|
+
lines.push("Source capability matrix:");
|
|
11134
|
+
for (const source of report.investigation.source_confidence.columns) {
|
|
11135
|
+
const chronology = source.capability_cells.chronology;
|
|
11136
|
+
const verification = source.capability_cells.verification;
|
|
11137
|
+
lines.push(`- ${source.brand.name}: ${source.status}, chronology ${Math.round(chronology.achieved * 100)}%/${chronology.ceiling}, verification ${Math.round(verification.achieved * 100)}%/${verification.ceiling}`);
|
|
11138
|
+
}
|
|
11139
|
+
lines.push("");
|
|
9362
11140
|
lines.push("## Client Extractions");
|
|
9363
11141
|
lines.push("");
|
|
9364
11142
|
if (report.client_extractions.length === 0) {
|
|
@@ -9538,6 +11316,29 @@ function renderWorkGraphMarkdown(report) {
|
|
|
9538
11316
|
}
|
|
9539
11317
|
|
|
9540
11318
|
// src/lib/work-graph-publish.ts
|
|
11319
|
+
import { gzipSync } from "zlib";
|
|
11320
|
+
var WORK_GRAPH_REPORT_GZIP_THRESHOLD_BYTES = 96e3;
|
|
11321
|
+
function encodeWorkGraphReportPostBody(payload, thresholdBytes = WORK_GRAPH_REPORT_GZIP_THRESHOLD_BYTES) {
|
|
11322
|
+
const json = JSON.stringify(payload);
|
|
11323
|
+
const byteLength = Buffer.byteLength(json);
|
|
11324
|
+
if (byteLength < thresholdBytes) {
|
|
11325
|
+
return {
|
|
11326
|
+
body: json,
|
|
11327
|
+
headers: { "Content-Type": "application/json" },
|
|
11328
|
+
byteLength,
|
|
11329
|
+
compressed: false
|
|
11330
|
+
};
|
|
11331
|
+
}
|
|
11332
|
+
return {
|
|
11333
|
+
body: gzipSync(json),
|
|
11334
|
+
headers: {
|
|
11335
|
+
"Content-Encoding": "gzip",
|
|
11336
|
+
"Content-Type": "application/json"
|
|
11337
|
+
},
|
|
11338
|
+
byteLength,
|
|
11339
|
+
compressed: true
|
|
11340
|
+
};
|
|
11341
|
+
}
|
|
9541
11342
|
async function parseResponse(response) {
|
|
9542
11343
|
const text2 = await response.text();
|
|
9543
11344
|
if (!text2) return null;
|
|
@@ -9553,22 +11354,23 @@ async function publishWorkGraphReport(report, options = {}) {
|
|
|
9553
11354
|
throw new Error("OrgX auth is required to publish a Work Graph. Run `orgx-wizard auth login` or set ORGX_API_KEY.");
|
|
9554
11355
|
}
|
|
9555
11356
|
const url = buildOrgxApiUrl("/client/work-graph/reports", auth.baseUrl);
|
|
11357
|
+
const encoded = encodeWorkGraphReportPostBody({
|
|
11358
|
+
report,
|
|
11359
|
+
...options.workspaceId ? { workspace_id: options.workspaceId } : {},
|
|
11360
|
+
...options.initiativeId ? { initiative_id: options.initiativeId } : {},
|
|
11361
|
+
...options.entityType ? { entity_type: options.entityType } : {},
|
|
11362
|
+
...options.entityId ? { entity_id: options.entityId } : {},
|
|
11363
|
+
...options.artifactUrl ? { artifact_url: options.artifactUrl } : {},
|
|
11364
|
+
attach_artifact: Boolean(options.attachArtifact),
|
|
11365
|
+
public_share: Boolean(options.publicShare)
|
|
11366
|
+
});
|
|
9556
11367
|
const response = await fetch(url, {
|
|
9557
11368
|
method: "POST",
|
|
9558
11369
|
headers: {
|
|
9559
11370
|
Authorization: `Bearer ${auth.apiKey}`,
|
|
9560
|
-
|
|
11371
|
+
...encoded.headers
|
|
9561
11372
|
},
|
|
9562
|
-
body:
|
|
9563
|
-
report,
|
|
9564
|
-
...options.workspaceId ? { workspace_id: options.workspaceId } : {},
|
|
9565
|
-
...options.initiativeId ? { initiative_id: options.initiativeId } : {},
|
|
9566
|
-
...options.entityType ? { entity_type: options.entityType } : {},
|
|
9567
|
-
...options.entityId ? { entity_id: options.entityId } : {},
|
|
9568
|
-
...options.artifactUrl ? { artifact_url: options.artifactUrl } : {},
|
|
9569
|
-
attach_artifact: Boolean(options.attachArtifact),
|
|
9570
|
-
public_share: Boolean(options.publicShare)
|
|
9571
|
-
}),
|
|
11373
|
+
body: encoded.body,
|
|
9572
11374
|
signal: options.signal ?? AbortSignal.timeout(15e3)
|
|
9573
11375
|
});
|
|
9574
11376
|
return {
|
|
@@ -9605,8 +11407,8 @@ async function publishWorkGraphEvents(fingerprint, patch, options = {}) {
|
|
|
9605
11407
|
}
|
|
9606
11408
|
|
|
9607
11409
|
// src/lib/work-graph-hook-events.ts
|
|
9608
|
-
import { createHash as
|
|
9609
|
-
import { existsSync as
|
|
11410
|
+
import { createHash as createHash7 } from "crypto";
|
|
11411
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
9610
11412
|
var SOURCE_CLIENTS = [
|
|
9611
11413
|
"codex",
|
|
9612
11414
|
"claude",
|
|
@@ -9640,7 +11442,7 @@ function asStringArray(value) {
|
|
|
9640
11442
|
return value.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
9641
11443
|
}
|
|
9642
11444
|
function stableHash(value) {
|
|
9643
|
-
return
|
|
11445
|
+
return createHash7("sha256").update(value).digest("hex").slice(0, 20);
|
|
9644
11446
|
}
|
|
9645
11447
|
function normalizeSourceClient2(value) {
|
|
9646
11448
|
const raw = asString2(value)?.toLowerCase();
|
|
@@ -9707,8 +11509,8 @@ function readHookRecord(line) {
|
|
|
9707
11509
|
}
|
|
9708
11510
|
}
|
|
9709
11511
|
function readRuntimeHookOutbox(path, limit = 200) {
|
|
9710
|
-
if (!
|
|
9711
|
-
const lines =
|
|
11512
|
+
if (!existsSync7(path)) return { path, records: [], skipped: 0 };
|
|
11513
|
+
const lines = readFileSync5(path, "utf8").split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
9712
11514
|
const selected = lines.slice(Math.max(0, lines.length - Math.max(1, limit)));
|
|
9713
11515
|
const records = [];
|
|
9714
11516
|
let skipped = Math.max(0, lines.length - selected.length);
|
|
@@ -9844,20 +11646,20 @@ function buildWorkGraphHookReplayPatch(readResult) {
|
|
|
9844
11646
|
}
|
|
9845
11647
|
|
|
9846
11648
|
// src/lib/runtime-hooks.ts
|
|
9847
|
-
import { copyFileSync, existsSync as
|
|
9848
|
-
import { homedir as
|
|
9849
|
-
import { dirname as dirname4, join as
|
|
11649
|
+
import { copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync3 } from "fs";
|
|
11650
|
+
import { homedir as homedir3 } from "os";
|
|
11651
|
+
import { dirname as dirname4, join as join6 } from "path";
|
|
9850
11652
|
var HOOK_MARKER = "orgx-session-hook.mjs";
|
|
9851
11653
|
var HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "PermissionRequest", "Stop"];
|
|
9852
11654
|
var CLAUDE_HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "SubagentStop", "Stop", "SessionEnd"];
|
|
9853
11655
|
function defaultPaths(options = {}) {
|
|
9854
|
-
const hookDir =
|
|
11656
|
+
const hookDir = join6(ORGX_WIZARD_CONFIG_HOME, "hooks");
|
|
9855
11657
|
return {
|
|
9856
|
-
claudeSettingsPath: options.claudeSettingsPath ??
|
|
9857
|
-
codexConfigPath: options.codexConfigPath ?? CODEX_CONFIG_PATH ??
|
|
9858
|
-
codexHooksPath: options.codexHooksPath ??
|
|
9859
|
-
hookScriptPath: options.hookScriptPath ??
|
|
9860
|
-
outboxPath: options.outboxPath ??
|
|
11658
|
+
claudeSettingsPath: options.claudeSettingsPath ?? join6(CLAUDE_DIR, "settings.json"),
|
|
11659
|
+
codexConfigPath: options.codexConfigPath ?? CODEX_CONFIG_PATH ?? join6(CODEX_DIR, "config.toml"),
|
|
11660
|
+
codexHooksPath: options.codexHooksPath ?? join6(CODEX_DIR, "hooks.json"),
|
|
11661
|
+
hookScriptPath: options.hookScriptPath ?? join6(hookDir, HOOK_MARKER),
|
|
11662
|
+
outboxPath: options.outboxPath ?? join6(hookDir, "events.jsonl")
|
|
9861
11663
|
};
|
|
9862
11664
|
}
|
|
9863
11665
|
function countJsonlLines(path) {
|
|
@@ -9870,7 +11672,7 @@ function backupPath(path, now) {
|
|
|
9870
11672
|
return `${path}.bak.${timestamp}`;
|
|
9871
11673
|
}
|
|
9872
11674
|
function backupExisting(path, now) {
|
|
9873
|
-
if (!
|
|
11675
|
+
if (!existsSync8(path)) return null;
|
|
9874
11676
|
const backup = backupPath(path, now);
|
|
9875
11677
|
copyFileSync(path, backup);
|
|
9876
11678
|
return backup;
|
|
@@ -10068,7 +11870,7 @@ function inspectRuntimeHooks(options = {}) {
|
|
|
10068
11870
|
installed: {
|
|
10069
11871
|
claudeCode: hasOrgxHook(claudeSettingsRaw),
|
|
10070
11872
|
codex: hasOrgxHook(codexHooksRaw),
|
|
10071
|
-
hookScript:
|
|
11873
|
+
hookScript: existsSync8(paths.hookScriptPath)
|
|
10072
11874
|
},
|
|
10073
11875
|
codex: {
|
|
10074
11876
|
configExists: Boolean(codexConfigRaw),
|
|
@@ -10298,7 +12100,7 @@ async function runHookReplayCommand(options) {
|
|
|
10298
12100
|
}
|
|
10299
12101
|
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
10300
12102
|
const paths = inspectRuntimeHooks().paths;
|
|
10301
|
-
const outboxPath =
|
|
12103
|
+
const outboxPath = resolve2(options.outbox?.trim() || paths.outboxPath);
|
|
10302
12104
|
const readResult = readRuntimeHookOutbox(outboxPath, parsePositiveInt(options.limit, 200));
|
|
10303
12105
|
const replay = buildWorkGraphHookReplayPatch(readResult);
|
|
10304
12106
|
if (replay.records === 0) {
|
|
@@ -10330,10 +12132,10 @@ async function runHookReplayCommand(options) {
|
|
|
10330
12132
|
}
|
|
10331
12133
|
function readAuditInput(options, interactive) {
|
|
10332
12134
|
if (options.input?.trim()) {
|
|
10333
|
-
return
|
|
12135
|
+
return readFileSync7(resolve2(options.input.trim()), "utf8");
|
|
10334
12136
|
}
|
|
10335
12137
|
if (!process.stdin.isTTY) {
|
|
10336
|
-
return
|
|
12138
|
+
return readFileSync7(0, "utf8");
|
|
10337
12139
|
}
|
|
10338
12140
|
if (!interactive) {
|
|
10339
12141
|
throw new Error("Audit input is required. Pass --input <file> or pipe text into wizard audit.");
|
|
@@ -10365,8 +12167,8 @@ function collectPathOption(value, previous = []) {
|
|
|
10365
12167
|
];
|
|
10366
12168
|
}
|
|
10367
12169
|
function parseClientExtractionFile(path) {
|
|
10368
|
-
const resolvedPath =
|
|
10369
|
-
const parsed = JSON.parse(
|
|
12170
|
+
const resolvedPath = resolve2(path);
|
|
12171
|
+
const parsed = JSON.parse(readFileSync7(resolvedPath, "utf8"));
|
|
10370
12172
|
if (!isRecord(parsed)) {
|
|
10371
12173
|
throw new Error(`AI-client extraction must be a JSON object: ${resolvedPath}`);
|
|
10372
12174
|
}
|
|
@@ -10388,8 +12190,8 @@ async function readAuditImports(options, interactive) {
|
|
|
10388
12190
|
const missingSources = [];
|
|
10389
12191
|
if (sources.length > 0) {
|
|
10390
12192
|
const imported = loadAiSessionImports({
|
|
10391
|
-
...options.claudeProjectsDir?.trim() ? { claudeProjectsDir:
|
|
10392
|
-
...options.codexSessionsDir?.trim() ? { codexSessionsDir:
|
|
12193
|
+
...options.claudeProjectsDir?.trim() ? { claudeProjectsDir: resolve2(options.claudeProjectsDir.trim()) } : {},
|
|
12194
|
+
...options.codexSessionsDir?.trim() ? { codexSessionsDir: resolve2(options.codexSessionsDir.trim()) } : {},
|
|
10393
12195
|
limitPerSource: parsePositiveInteger(options.sessionLimit, 3, "--session-limit"),
|
|
10394
12196
|
sinceDays: parsePositiveInteger(options.sessionDays, 30, "--session-days"),
|
|
10395
12197
|
sources
|
|
@@ -10417,7 +12219,7 @@ async function readAuditImports(options, interactive) {
|
|
|
10417
12219
|
}
|
|
10418
12220
|
if (imports.length === 0) {
|
|
10419
12221
|
const sourceHint = sources.length > 0 ? ` No audit-relevant lines were found in ${sources.join(", ")} sessions.` : "";
|
|
10420
|
-
throw new Error(`Audit input is required.${sourceHint} Pass --input <file>, pipe text, or use --from codex
|
|
12222
|
+
throw new Error(`Audit input is required.${sourceHint} Pass --input <file>, pipe text, or use --from claude,codex,opencode,goose,cursor,all.`);
|
|
10421
12223
|
}
|
|
10422
12224
|
return {
|
|
10423
12225
|
connectedSources,
|
|
@@ -10427,13 +12229,28 @@ async function readAuditImports(options, interactive) {
|
|
|
10427
12229
|
}
|
|
10428
12230
|
async function readWorkGraphInputs(options, interactive) {
|
|
10429
12231
|
const clientExtractions = readClientExtractions(options);
|
|
12232
|
+
const investigationSources = parseInvestigationSourceList(options.from);
|
|
12233
|
+
const investigationSourceData = investigationSources.length > 0 ? loadWorkGraphInvestigationSourceData({
|
|
12234
|
+
...options.claudeProjectsDir?.trim() ? { claudeProjectsDir: resolve2(options.claudeProjectsDir.trim()) } : {},
|
|
12235
|
+
...options.codexSessionsDir?.trim() ? { codexSessionsDir: resolve2(options.codexSessionsDir.trim()) } : {},
|
|
12236
|
+
cwd: process.cwd(),
|
|
12237
|
+
limitPerSource: parsePositiveInteger(options.sessionLimit, 8, "--session-limit"),
|
|
12238
|
+
sinceDays: parsePositiveInteger(options.sessionDays, 45, "--session-days"),
|
|
12239
|
+
sources: investigationSources
|
|
12240
|
+
}) : {
|
|
12241
|
+
clientExtractions: [],
|
|
12242
|
+
connectedSources: [],
|
|
12243
|
+
missingSources: [],
|
|
12244
|
+
rawEvents: []
|
|
12245
|
+
};
|
|
10430
12246
|
const shouldReadSessionImports = Boolean(
|
|
10431
|
-
options.from?.trim() || options.input?.trim() || clientExtractions.length === 0 || !process.stdin.isTTY && clientExtractions.length === 0
|
|
12247
|
+
options.from?.trim() || options.input?.trim() || clientExtractions.length === 0 && investigationSourceData.clientExtractions.length === 0 || !process.stdin.isTTY && clientExtractions.length === 0 && investigationSourceData.clientExtractions.length === 0
|
|
10432
12248
|
);
|
|
10433
12249
|
if (!shouldReadSessionImports) {
|
|
10434
12250
|
return {
|
|
10435
|
-
clientExtractions,
|
|
12251
|
+
clientExtractions: [...clientExtractions, ...investigationSourceData.clientExtractions],
|
|
10436
12252
|
connectedSources: [],
|
|
12253
|
+
investigationRawEvents: investigationSourceData.rawEvents,
|
|
10437
12254
|
imports: [],
|
|
10438
12255
|
missingSources: []
|
|
10439
12256
|
};
|
|
@@ -10442,7 +12259,7 @@ async function readWorkGraphInputs(options, interactive) {
|
|
|
10442
12259
|
try {
|
|
10443
12260
|
auditImports = await readAuditImports(options, interactive);
|
|
10444
12261
|
} catch (error) {
|
|
10445
|
-
if (clientExtractions.length === 0) throw error;
|
|
12262
|
+
if (clientExtractions.length === 0 && investigationSourceData.clientExtractions.length === 0) throw error;
|
|
10446
12263
|
const message = error instanceof Error ? error.message : String(error);
|
|
10447
12264
|
auditImports = {
|
|
10448
12265
|
connectedSources: [],
|
|
@@ -10451,10 +12268,11 @@ async function readWorkGraphInputs(options, interactive) {
|
|
|
10451
12268
|
};
|
|
10452
12269
|
}
|
|
10453
12270
|
return {
|
|
10454
|
-
clientExtractions,
|
|
10455
|
-
connectedSources: auditImports.connectedSources,
|
|
12271
|
+
clientExtractions: [...clientExtractions, ...investigationSourceData.clientExtractions],
|
|
12272
|
+
connectedSources: [...auditImports.connectedSources, ...investigationSourceData.connectedSources],
|
|
12273
|
+
investigationRawEvents: investigationSourceData.rawEvents,
|
|
10456
12274
|
imports: auditImports.imports,
|
|
10457
|
-
missingSources: auditImports.missingSources
|
|
12275
|
+
missingSources: [...auditImports.missingSources, ...investigationSourceData.missingSources]
|
|
10458
12276
|
};
|
|
10459
12277
|
}
|
|
10460
12278
|
function requireWriteApproval(options, interactive) {
|
|
@@ -10531,10 +12349,10 @@ async function runAuditCommand(options) {
|
|
|
10531
12349
|
workspace
|
|
10532
12350
|
});
|
|
10533
12351
|
const markdown = renderSelfAuditMarkdown(plan);
|
|
10534
|
-
const outputDir =
|
|
12352
|
+
const outputDir = resolve2(options.outputDir?.trim() || ".orgx/audits");
|
|
10535
12353
|
const timestamp = plan.generated_at.replace(/[:.]/g, "-");
|
|
10536
|
-
const jsonPath =
|
|
10537
|
-
const markdownPath =
|
|
12354
|
+
const jsonPath = resolve2(outputDir, `ai-native-self-audit-${timestamp}.json`);
|
|
12355
|
+
const markdownPath = resolve2(outputDir, `ai-native-self-audit-${timestamp}.md`);
|
|
10538
12356
|
writeJsonFile(jsonPath, plan);
|
|
10539
12357
|
writeTextFile(markdownPath, markdown);
|
|
10540
12358
|
if (options.json) {
|
|
@@ -10585,7 +12403,7 @@ async function runAuditCommand(options) {
|
|
|
10585
12403
|
}
|
|
10586
12404
|
function runWorkGraphExtractionSchemaCommand(options) {
|
|
10587
12405
|
const protocol = buildWorkGraphExtractionProtocol();
|
|
10588
|
-
const outputPath = options.output?.trim() ?
|
|
12406
|
+
const outputPath = options.output?.trim() ? resolve2(options.output.trim()) : "";
|
|
10589
12407
|
if (outputPath) {
|
|
10590
12408
|
if (options.json) {
|
|
10591
12409
|
writeJsonFile(outputPath, protocol);
|
|
@@ -10624,6 +12442,7 @@ async function runWorkGraphCommand(options, defaults = {}) {
|
|
|
10624
12442
|
...workspace.id === "local-workspace" ? [] : ["OrgX workspace"]
|
|
10625
12443
|
],
|
|
10626
12444
|
imports: auditInputs.imports,
|
|
12445
|
+
investigationRawEvents: auditInputs.investigationRawEvents,
|
|
10627
12446
|
missingSources: [
|
|
10628
12447
|
...workspace.id === "local-workspace" ? ["OrgX workspace auth"] : [],
|
|
10629
12448
|
...auditInputs.missingSources
|
|
@@ -10632,10 +12451,10 @@ async function runWorkGraphCommand(options, defaults = {}) {
|
|
|
10632
12451
|
workspace
|
|
10633
12452
|
});
|
|
10634
12453
|
const markdown = renderWorkGraphMarkdown(report);
|
|
10635
|
-
const outputDir =
|
|
12454
|
+
const outputDir = resolve2(commandOptions.outputDir?.trim() || ".orgx/work-graph");
|
|
10636
12455
|
const timestamp = report.generated_at.replace(/[:.]/g, "-");
|
|
10637
|
-
const jsonPath =
|
|
10638
|
-
const markdownPath =
|
|
12456
|
+
const jsonPath = resolve2(outputDir, `work-graph-report-${timestamp}.json`);
|
|
12457
|
+
const markdownPath = resolve2(outputDir, `work-graph-report-${timestamp}.md`);
|
|
10639
12458
|
writeJsonFile(jsonPath, report);
|
|
10640
12459
|
writeTextFile(markdownPath, markdown);
|
|
10641
12460
|
let published = null;
|
|
@@ -11017,14 +12836,14 @@ async function readSingleKey() {
|
|
|
11017
12836
|
const stdin = process.stdin;
|
|
11018
12837
|
if (!stdin.isTTY) return null;
|
|
11019
12838
|
const previousRawMode = stdin.isRaw === true;
|
|
11020
|
-
return await new Promise((
|
|
12839
|
+
return await new Promise((resolve3) => {
|
|
11021
12840
|
const cleanup = (result) => {
|
|
11022
12841
|
stdin.off("data", onData);
|
|
11023
12842
|
if (stdin.isTTY) {
|
|
11024
12843
|
stdin.setRawMode(previousRawMode);
|
|
11025
12844
|
}
|
|
11026
12845
|
stdin.pause();
|
|
11027
|
-
|
|
12846
|
+
resolve3(result);
|
|
11028
12847
|
};
|
|
11029
12848
|
const onData = (chunk) => {
|
|
11030
12849
|
const text2 = chunk.toString("utf8");
|
|
@@ -11677,7 +13496,7 @@ function printDoctorReport(report, assessment) {
|
|
|
11677
13496
|
async function main() {
|
|
11678
13497
|
const program = new Command();
|
|
11679
13498
|
program.name("orgx-wizard").description("Add OrgX MCP configs, skills/rules, and companion plugins to your local AI tools.").showHelpAfterError();
|
|
11680
|
-
const pkgVersion = true ? "0.1.
|
|
13499
|
+
const pkgVersion = true ? "0.1.39" : void 0;
|
|
11681
13500
|
program.version(pkgVersion ?? "unknown", "-V, --version");
|
|
11682
13501
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
11683
13502
|
if (Boolean(actionCommand.optsWithGlobals().json)) return;
|
|
@@ -12367,7 +14186,7 @@ async function main() {
|
|
|
12367
14186
|
jsonOutput: Boolean(options.json)
|
|
12368
14187
|
});
|
|
12369
14188
|
});
|
|
12370
|
-
program.command("audit").description("Run the AI-native Founder Loop self-audit from pasted or file-based AI-session context.").option("--input <path>", "AI-session transcript or summary file; stdin is used when piped").option("--from <sources>", "auto-import recent local AI sessions: codex,
|
|
14189
|
+
program.command("audit").description("Run the AI-native Founder Loop self-audit from pasted or file-based AI-session context.").option("--input <path>", "AI-session transcript or summary file; stdin is used when piped").option("--from <sources>", "auto-import recent local AI sessions: claude, codex, opencode, goose, cursor, or all").option("--session-limit <count>", "max recent sessions to import per selected source", "3").option("--session-days <days>", "lookback window for local AI-session imports", "30").option("--codex-sessions-dir <path>", "override Codex sessions directory for audit import").option("--claude-projects-dir <path>", "override Claude projects directory for audit import").option("--source-label <label>", "label for the imported AI-session source").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace when authenticated").option("--workspace-name <name>", "workspace name override for local-only audits").option("--output-dir <path>", "directory for generated audit JSON and Markdown", ".orgx/audits").option("--attach-to-initiative <id>", "attach the generated audit artifact to an existing OrgX initiative").option("--create-initiative", "create an OrgX initiative from the generated audit plan").option("--write-follow-up", "create one approval-gated OrgX follow-up task from the audit recommendation").option("--workstream-id <id>", "optional workstream id for the generated follow-up task").option("--milestone-id <id>", "optional milestone id for the generated follow-up task").option("--dry-run", "exercise OrgX write paths without sending writes").option("--yes", "approve OrgX write flags in non-interactive mode").option("--json", "emit a JSON command summary").action(async (options) => {
|
|
12371
14190
|
await safeTrackWizardTelemetry("audit_started", {
|
|
12372
14191
|
attach_to_initiative: Boolean(options.attachToInitiative),
|
|
12373
14192
|
command: "audit",
|
|
@@ -12385,14 +14204,14 @@ async function main() {
|
|
|
12385
14204
|
});
|
|
12386
14205
|
runWorkGraphExtractionSchemaCommand(options);
|
|
12387
14206
|
});
|
|
12388
|
-
workGraph.command("preview").description("Preview the OrgX Profile evidence findings without writing to OrgX.").option("--input <path>", "source transcript or summary file; stdin is used when piped").option("--extraction <path>", "structured AI-client extraction JSON; repeat or comma-separate for multiple clients", collectPathOption, []).option("--from <sources>", "auto-import recent local AI sessions: codex,
|
|
14207
|
+
workGraph.command("preview").description("Preview the OrgX Profile evidence findings without writing to OrgX.").option("--input <path>", "source transcript or summary file; stdin is used when piped").option("--extraction <path>", "structured AI-client extraction JSON; repeat or comma-separate for multiple clients", collectPathOption, []).option("--from <sources>", "auto-import recent local AI sessions: claude, codex, opencode, goose, cursor, or all").option("--session-limit <count>", "max recent sessions to import per selected source", "15").option("--session-days <days>", "lookback window for local AI-session imports", "60").option("--codex-sessions-dir <path>", "override Codex sessions directory for import").option("--claude-projects-dir <path>", "override Claude projects directory for import").option("--source-label <label>", "label for the imported manual source").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace when authenticated").option("--workspace-name <name>", "workspace name override for local-only previews").option("--output-dir <path>", "directory for generated Work Graph JSON and Markdown", ".orgx/work-graph").option("--json", "emit a JSON command summary").action(async (options) => {
|
|
12389
14208
|
await safeTrackWizardTelemetry("work_graph_preview_started", {
|
|
12390
14209
|
command: "work-graph preview",
|
|
12391
14210
|
from: options.from ?? "manual"
|
|
12392
14211
|
});
|
|
12393
14212
|
await runWorkGraphCommand(options);
|
|
12394
14213
|
});
|
|
12395
|
-
workGraph.command("profile").description("Build a local OrgX Profile with evidence findings, domain coverage, source confidence, and repair recommendations.").option("--input <path>", "source transcript or summary file; stdin is used when piped").option("--extraction <path>", "structured AI-client extraction JSON; repeat or comma-separate for multiple clients", collectPathOption, []).option("--from <sources>", "auto-import recent local AI sessions: codex,
|
|
14214
|
+
workGraph.command("profile").description("Build a local OrgX Profile with evidence findings, domain coverage, source confidence, and repair recommendations.").option("--input <path>", "source transcript or summary file; stdin is used when piped").option("--extraction <path>", "structured AI-client extraction JSON; repeat or comma-separate for multiple clients", collectPathOption, []).option("--from <sources>", "auto-import recent local AI sessions: claude, codex, opencode, goose, cursor, or all").option("--session-limit <count>", "max recent sessions to import per selected source", "25").option("--session-days <days>", "lookback window for local AI-session imports", "60").option("--codex-sessions-dir <path>", "override Codex sessions directory for import").option("--claude-projects-dir <path>", "override Claude projects directory for import").option("--source-label <label>", "label for the imported manual source").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace when authenticated").option("--workspace-name <name>", "workspace name override for local-only profiles").option("--output-dir <path>", "directory for generated Work Graph JSON and Markdown", ".orgx/work-graph").option("--publish", "publish the generated OrgX Profile to OrgX and return a shareable URL").option("--public-share", "create a public redacted /work-graph/<token> share when publishing").option("--attach-artifact", "attach the report as an OrgX artifact when an initiative/entity is provided").option("--attach-to-initiative <id>", "attach the report to an existing OrgX initiative").option("--entity-type <type>", "entity type for artifact attachment: project, initiative, milestone, task, decision").option("--entity-id <id>", "entity id for artifact attachment").option("--artifact-url <url>", "override the artifact URL stored in OrgX").option("--yes", "approve publish/write prompts in non-interactive mode").option("--json", "emit a JSON command summary").action(async (options) => {
|
|
12396
14215
|
await safeTrackWizardTelemetry("work_graph_profile_started", {
|
|
12397
14216
|
command: "work-graph profile",
|
|
12398
14217
|
from: options.from ?? "manual"
|
|
@@ -12400,7 +14219,7 @@ async function main() {
|
|
|
12400
14219
|
await runWorkGraphCommand(options);
|
|
12401
14220
|
});
|
|
12402
14221
|
const sessions = program.command("sessions").description("Inspect and reconcile local AI sessions into OrgX-ready Work Graph reports.");
|
|
12403
|
-
sessions.command("reconcile").description("Backfill recent Codex and
|
|
14222
|
+
sessions.command("reconcile").description("Backfill recent Claude Code, Codex, OpenCode, goose, and Cursor sessions into a redacted OrgX Profile report.").option("--extraction <path>", "structured AI-client extraction JSON; repeat or comma-separate for multiple clients", collectPathOption, []).option("--from <sources>", "auto-import recent local AI sessions: claude, codex, opencode, goose, cursor, or all", "all").option("--session-limit <count>", "max recent sessions to import per selected source", "25").option("--session-days <days>", "lookback window for local AI-session imports", "30").option("--codex-sessions-dir <path>", "override Codex sessions directory for import").option("--claude-projects-dir <path>", "override Claude projects directory for import").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace when authenticated").option("--workspace-name <name>", "workspace name override for local-only reconciliation").option("--output-dir <path>", "directory for generated Work Graph JSON and Markdown", ".orgx/work-graph").option("--publish", "publish the generated OrgX Profile to OrgX and return a shareable URL").option("--public-share", "create a public redacted /work-graph/<token> share when publishing").option("--attach-artifact", "attach the report as an OrgX artifact when an initiative/entity is provided").option("--attach-to-initiative <id>", "attach the report to an existing OrgX initiative").option("--entity-type <type>", "entity type for artifact attachment: project, initiative, milestone, task, decision").option("--entity-id <id>", "entity id for artifact attachment").option("--artifact-url <url>", "override the artifact URL stored in OrgX").option("--yes", "approve publish/write prompts in non-interactive mode").option("--json", "emit a JSON command summary").action(async (options) => {
|
|
12404
14223
|
await safeTrackWizardTelemetry("sessions_reconcile_started", {
|
|
12405
14224
|
command: "sessions reconcile",
|
|
12406
14225
|
from: options.from ?? "all"
|