@bragi-gmbh/codebus 1.4.0 → 1.6.1
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/ci-hooks/ci-hooks.js +126 -0
- package/dist/ci-hooks/ci-hooks.js.map +1 -0
- package/dist/commands/adr.js +30 -0
- package/dist/commands/adr.js.map +1 -0
- package/dist/commands/agent.js +175 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/as.js +1 -1
- package/dist/commands/as.js.map +1 -1
- package/dist/commands/ask.js +1 -1
- package/dist/commands/ask.js.map +1 -1
- package/dist/commands/checkin.js +1 -1
- package/dist/commands/checkin.js.map +1 -1
- package/dist/commands/ci-findings.js +129 -0
- package/dist/commands/ci-findings.js.map +1 -0
- package/dist/commands/ci-reply.js +117 -0
- package/dist/commands/ci-reply.js.map +1 -0
- package/dist/commands/ci-steer-escalate.js +65 -0
- package/dist/commands/ci-steer-escalate.js.map +1 -0
- package/dist/commands/cli-mcp-correlation.js +131 -0
- package/dist/commands/cli-mcp-correlation.js.map +1 -0
- package/dist/commands/connector-attach-detach.js +542 -0
- package/dist/commands/connector-attach-detach.js.map +1 -0
- package/dist/commands/connector.js +513 -0
- package/dist/commands/connector.js.map +1 -0
- package/dist/commands/contract.js +33 -0
- package/dist/commands/contract.js.map +1 -0
- package/dist/commands/correlation.js +194 -0
- package/dist/commands/correlation.js.map +1 -0
- package/dist/commands/decision.js +63 -0
- package/dist/commands/decision.js.map +1 -1
- package/dist/commands/digest.js +14 -3
- package/dist/commands/digest.js.map +1 -1
- package/dist/commands/do.js +127 -0
- package/dist/commands/do.js.map +1 -0
- package/dist/commands/factory-attention.js +106 -0
- package/dist/commands/factory-attention.js.map +1 -0
- package/dist/commands/factory-context-read.js +171 -0
- package/dist/commands/factory-context-read.js.map +1 -0
- package/dist/commands/factory-interventions.js +102 -0
- package/dist/commands/factory-interventions.js.map +1 -0
- package/dist/commands/factory.js +187 -0
- package/dist/commands/factory.js.map +1 -1
- package/dist/commands/github-login.js +109 -53
- package/dist/commands/github-login.js.map +1 -1
- package/dist/commands/graph-pull.js +130 -0
- package/dist/commands/graph-pull.js.map +1 -0
- package/dist/commands/graph.js +5 -1
- package/dist/commands/graph.js.map +1 -1
- package/dist/commands/inbox.js +7 -7
- package/dist/commands/inbox.js.map +1 -1
- package/dist/commands/ingest.js +1 -1
- package/dist/commands/ingest.js.map +1 -1
- package/dist/commands/init.js +10 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.js +1160 -55
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/integration-ledger.js +81 -0
- package/dist/commands/integration-ledger.js.map +1 -0
- package/dist/commands/knowledge.js +194 -0
- package/dist/commands/knowledge.js.map +1 -0
- package/dist/commands/links.js +1 -1
- package/dist/commands/links.js.map +1 -1
- package/dist/commands/login.js +1 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/morning.js +50 -1
- package/dist/commands/morning.js.map +1 -1
- package/dist/commands/plan-compiler.js +260 -0
- package/dist/commands/plan-compiler.js.map +1 -0
- package/dist/commands/plan-lint.js +275 -0
- package/dist/commands/plan-lint.js.map +1 -0
- package/dist/commands/plan-score.js +203 -0
- package/dist/commands/plan-score.js.map +1 -0
- package/dist/commands/plan.js +481 -15
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/product-validity.js +168 -0
- package/dist/commands/product-validity.js.map +1 -0
- package/dist/commands/question.js +1 -1
- package/dist/commands/question.js.map +1 -1
- package/dist/commands/read-policy.js +131 -0
- package/dist/commands/read-policy.js.map +1 -0
- package/dist/commands/read.js +1 -1
- package/dist/commands/read.js.map +1 -1
- package/dist/commands/repo.js +106 -8
- package/dist/commands/repo.js.map +1 -1
- package/dist/commands/repository-protection.js +209 -0
- package/dist/commands/repository-protection.js.map +1 -0
- package/dist/commands/resolve.js +2 -2
- package/dist/commands/resolve.js.map +1 -1
- package/dist/commands/self-healing.js +26 -0
- package/dist/commands/self-healing.js.map +1 -0
- package/dist/commands/send.js +1 -1
- package/dist/commands/send.js.map +1 -1
- package/dist/commands/serial-merge.js +303 -0
- package/dist/commands/serial-merge.js.map +1 -0
- package/dist/commands/session.js +1 -1
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/spend.js +31 -0
- package/dist/commands/spend.js.map +1 -0
- package/dist/commands/task.js +92 -1
- package/dist/commands/task.js.map +1 -1
- package/dist/commands/taxonomy.js +21 -0
- package/dist/commands/taxonomy.js.map +1 -0
- package/dist/commands/verify.js +77 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/config/self-healing-analysis.json +158 -0
- package/dist/errors.js +18 -4
- package/dist/errors.js.map +1 -1
- package/dist/execution/client.js +53 -0
- package/dist/execution/client.js.map +1 -0
- package/dist/execution/local.js +24 -0
- package/dist/execution/local.js.map +1 -0
- package/dist/execution/ssh.js +38 -0
- package/dist/execution/ssh.js.map +1 -0
- package/dist/graph.js +78 -16
- package/dist/graph.js.map +1 -1
- package/dist/index.js +40 -2
- package/dist/index.js.map +1 -1
- package/dist/json-lite.js +248 -0
- package/dist/json-lite.js.map +1 -0
- package/dist/knowledge-drift.js +40 -0
- package/dist/knowledge-drift.js.map +1 -0
- package/dist/lint/parallelism.js +414 -0
- package/dist/lint/parallelism.js.map +1 -0
- package/dist/mail-latency.js +11 -1
- package/dist/mail-latency.js.map +1 -1
- package/dist/mcp-ci-findings.js +31 -0
- package/dist/mcp-ci-findings.js.map +1 -0
- package/dist/mcp-correlation.js +290 -0
- package/dist/mcp-correlation.js.map +1 -0
- package/dist/mcp-factory-context-read.js +81 -0
- package/dist/mcp-factory-context-read.js.map +1 -0
- package/dist/mcp-registry.js +147 -1
- package/dist/mcp-registry.js.map +1 -1
- package/dist/mcp.js +94 -5
- package/dist/mcp.js.map +1 -1
- package/dist/openrouter-reservation-guard.js +97 -0
- package/dist/openrouter-reservation-guard.js.map +1 -0
- package/dist/self-healing-analysis-loader.js +150 -0
- package/dist/self-healing-analysis-loader.js.map +1 -0
- package/dist/sender.js +11 -9
- package/dist/sender.js.map +1 -1
- package/dist/toml-lite.js +546 -0
- package/dist/toml-lite.js.map +1 -0
- package/dist/version-check.js +23 -7
- package/dist/version-check.js.map +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ci-findings — CLI command core for CI findings (ci_finding work-orders).
|
|
3
|
+
*
|
|
4
|
+
* Implements com.bragi.contract.ci-finding@1.0.0-proposed (pinned definition:
|
|
5
|
+
* contracts/ci-finding.v1.schema.json). Every check emits findings, not logs.
|
|
6
|
+
*
|
|
7
|
+
* Transport rule: this module is the single core. The MCP transport
|
|
8
|
+
* (../mcp-ci-findings.js) re-exports these functions so CLI and MCP return
|
|
9
|
+
* identical findings (parity positive fixture).
|
|
10
|
+
*/
|
|
11
|
+
import { readFile } from "node:fs/promises";
|
|
12
|
+
export const CI_FINDING_KINDS = [
|
|
13
|
+
"assertion",
|
|
14
|
+
"compile",
|
|
15
|
+
"lint",
|
|
16
|
+
"migration",
|
|
17
|
+
"coverage-gap",
|
|
18
|
+
"test-quality",
|
|
19
|
+
"flake",
|
|
20
|
+
"infra",
|
|
21
|
+
"main-is-red",
|
|
22
|
+
];
|
|
23
|
+
export const CI_FINDING_NEXT_ACTIONS = ["fix", "rerun", "rebase", "escalate", "stop"];
|
|
24
|
+
/** Validate one finding against the pinned ci-finding v1 shape. Returns error strings (empty = valid). */
|
|
25
|
+
export function validateFinding(f) {
|
|
26
|
+
const errors = [];
|
|
27
|
+
if (typeof f !== "object" || f === null)
|
|
28
|
+
return ["finding must be an object"];
|
|
29
|
+
const r = f;
|
|
30
|
+
const required = [
|
|
31
|
+
"check", "kind", "location", "expected", "actual", "repro",
|
|
32
|
+
"caused_by", "main_status", "history", "coverage", "artifacts", "next_action",
|
|
33
|
+
];
|
|
34
|
+
for (const k of required) {
|
|
35
|
+
if (!(k in r))
|
|
36
|
+
errors.push(`missing required field: ${k}`);
|
|
37
|
+
}
|
|
38
|
+
if (typeof r.check !== "string" || r.check.length === 0)
|
|
39
|
+
errors.push("check must be a non-empty string");
|
|
40
|
+
if (typeof r.kind === "string" && !CI_FINDING_KINDS.includes(r.kind)) {
|
|
41
|
+
errors.push(`kind must be one of ${CI_FINDING_KINDS.join(",")}`);
|
|
42
|
+
}
|
|
43
|
+
if (typeof r.location === "string" && !/.+:[0-9]+/.test(r.location)) {
|
|
44
|
+
errors.push("location must match .+:[0-9]+");
|
|
45
|
+
}
|
|
46
|
+
if (typeof r.repro !== "string" || r.repro.length === 0)
|
|
47
|
+
errors.push("repro must be a non-empty string");
|
|
48
|
+
if (typeof r.next_action === "string" && !CI_FINDING_NEXT_ACTIONS.includes(r.next_action)) {
|
|
49
|
+
errors.push(`next_action must be one of ${CI_FINDING_NEXT_ACTIONS.join(",")}`);
|
|
50
|
+
}
|
|
51
|
+
const cb = r.caused_by;
|
|
52
|
+
if (cb !== undefined) {
|
|
53
|
+
if (!Array.isArray(cb.hunks) || cb.hunks.length === 0)
|
|
54
|
+
errors.push("caused_by.hunks must be a non-empty array");
|
|
55
|
+
if (typeof cb.blame !== "string" || cb.blame.length === 0)
|
|
56
|
+
errors.push("caused_by.blame must be a non-empty string");
|
|
57
|
+
}
|
|
58
|
+
const ms = r.main_status;
|
|
59
|
+
if (ms !== undefined && !["pass", "fail", "unknown"].includes(ms.status)) {
|
|
60
|
+
errors.push("main_status.status must be pass|fail|unknown");
|
|
61
|
+
}
|
|
62
|
+
const disallowed = Object.keys(r).filter((k) => !required.includes(k));
|
|
63
|
+
if (disallowed.length > 0)
|
|
64
|
+
errors.push(`additional properties not allowed: ${disallowed.join(",")}`);
|
|
65
|
+
return errors;
|
|
66
|
+
}
|
|
67
|
+
/** Parse a JSON payload (array of findings, or {findings:[...]}). Throws on invalid JSON. */
|
|
68
|
+
export function parseFindings(text) {
|
|
69
|
+
const parsed = JSON.parse(text);
|
|
70
|
+
if (Array.isArray(parsed))
|
|
71
|
+
return parsed;
|
|
72
|
+
if (typeof parsed === "object" && parsed !== null && Array.isArray(parsed.findings)) {
|
|
73
|
+
return parsed.findings;
|
|
74
|
+
}
|
|
75
|
+
throw new Error("findings payload must be a JSON array or {findings:[...]}");
|
|
76
|
+
}
|
|
77
|
+
/** Filter findings by kind and/or next_action. */
|
|
78
|
+
export function filterFindings(findings, opts) {
|
|
79
|
+
return findings.filter((f) => (opts.kind === undefined || f.kind === opts.kind) &&
|
|
80
|
+
(opts.nextAction === undefined || f.next_action === opts.nextAction));
|
|
81
|
+
}
|
|
82
|
+
/** Validate a list; returns {valid, invalid} split with per-item errors. */
|
|
83
|
+
export function splitValid(findings) {
|
|
84
|
+
const valid = [];
|
|
85
|
+
const invalid = [];
|
|
86
|
+
findings.forEach((f, index) => {
|
|
87
|
+
const errors = validateFinding(f);
|
|
88
|
+
if (errors.length === 0)
|
|
89
|
+
valid.push(f);
|
|
90
|
+
else
|
|
91
|
+
invalid.push({ index, errors });
|
|
92
|
+
});
|
|
93
|
+
return { valid, invalid };
|
|
94
|
+
}
|
|
95
|
+
/** Render findings as human-readable text (one block per finding). */
|
|
96
|
+
export function formatFindings(findings) {
|
|
97
|
+
if (findings.length === 0)
|
|
98
|
+
return "No CI findings.";
|
|
99
|
+
return findings
|
|
100
|
+
.map((f) => `[${f.kind}] ${f.check}\n location: ${f.location}\n expected: ${f.expected}\n actual: ${f.actual}\n repro: ${f.repro}\n next_action: ${f.next_action}`)
|
|
101
|
+
.join("\n");
|
|
102
|
+
}
|
|
103
|
+
/** Shared core: filter + validate + emit. Used by BOTH CLI and MCP transports. */
|
|
104
|
+
export function listFindings(findings, opts = {}) {
|
|
105
|
+
const filtered = filterFindings(findings, opts);
|
|
106
|
+
const { valid, invalid } = splitValid(filtered);
|
|
107
|
+
return { findings: valid, invalid };
|
|
108
|
+
}
|
|
109
|
+
/** Load findings from a JSON file on disk. */
|
|
110
|
+
export async function loadFindingsFile(path) {
|
|
111
|
+
const text = await readFile(path, "utf8");
|
|
112
|
+
return parseFindings(text);
|
|
113
|
+
}
|
|
114
|
+
/** CLI entry point: `codebus ci-findings [--file <path>] [--kind k] [--next-action a] [--json]`. */
|
|
115
|
+
export async function ciFindingsCmd(o) {
|
|
116
|
+
const findings = o.file ? await loadFindingsFile(o.file) : [];
|
|
117
|
+
const { findings: valid, invalid } = listFindings(findings, o);
|
|
118
|
+
if (invalid.length > 0) {
|
|
119
|
+
for (const inv of invalid) {
|
|
120
|
+
console.error(`invalid finding #${inv.index}: ${inv.errors.join("; ")}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (o.json) {
|
|
124
|
+
console.log(JSON.stringify({ findings: valid, invalid: invalid.length }, null, 2));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
console.log(formatFindings(valid));
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=ci-findings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci-findings.js","sourceRoot":"","sources":["../../src/commands/ci-findings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ci-reply — CLI command: record the agent's reply closing a ci_finding work-order.
|
|
3
|
+
*
|
|
4
|
+
* Consumes the pinned contract com.bragi.contract.ci-decision@1.0.0-proposed
|
|
5
|
+
* (advisory receipts) and the ci_finding work-order directive produced by
|
|
6
|
+
* com.bragi.work.ci-a.ci-message-type. The reply closes the finding via the
|
|
7
|
+
* ci_outcome_record() RPC (supabase/migrations/*_ci_outcomes.sql): exactly one
|
|
8
|
+
* outcome row per ci_finding message; a second reply is refused. The outcome
|
|
9
|
+
* carries disposition + fix commit plus was_flaky (feeds the flake DB) and
|
|
10
|
+
* hint_helpful (feeds hint-accuracy evaluation).
|
|
11
|
+
*
|
|
12
|
+
* Input: reply fields via --file <path> or --reply <json>.
|
|
13
|
+
* Output: the outcome record printed as text or --json. Exits non-zero on
|
|
14
|
+
* invalid input. DB writes happen through the injected recordOutcome
|
|
15
|
+
* function so unit tests run without a database.
|
|
16
|
+
*/
|
|
17
|
+
import { readFile } from "node:fs/promises";
|
|
18
|
+
export const CI_OUTCOME_DISPOSITIONS = [
|
|
19
|
+
"fixed",
|
|
20
|
+
"rerun-passed",
|
|
21
|
+
"rerun-failed",
|
|
22
|
+
"escalated",
|
|
23
|
+
"wont-fix",
|
|
24
|
+
];
|
|
25
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
26
|
+
/** Validate a reply input against the ci_outcomes shape. Returns error strings (empty = valid). */
|
|
27
|
+
export function validateReply(r) {
|
|
28
|
+
const errors = [];
|
|
29
|
+
if (typeof r !== "object" || r === null)
|
|
30
|
+
return ["reply must be an object"];
|
|
31
|
+
const o = r;
|
|
32
|
+
if (typeof o.messageId !== "string" || !UUID_RE.test(o.messageId))
|
|
33
|
+
errors.push("messageId must be a uuid");
|
|
34
|
+
if (typeof o.disposition !== "string" || !CI_OUTCOME_DISPOSITIONS.includes(o.disposition))
|
|
35
|
+
errors.push(`disposition must be one of ${CI_OUTCOME_DISPOSITIONS.join(", ")}`);
|
|
36
|
+
if (o.fixCommitSha !== undefined && (typeof o.fixCommitSha !== "string" || o.fixCommitSha.length > 64))
|
|
37
|
+
errors.push("fixCommitSha must be a string of at most 64 chars");
|
|
38
|
+
if (o.note !== undefined && (typeof o.note !== "string" || o.note.length > 2000))
|
|
39
|
+
errors.push("note must be a string of at most 2000 chars");
|
|
40
|
+
if (o.wasFlaky !== undefined && typeof o.wasFlaky !== "boolean")
|
|
41
|
+
errors.push("wasFlaky must be a boolean");
|
|
42
|
+
if (o.hintHelpful !== undefined && o.hintHelpful !== null && typeof o.hintHelpful !== "boolean")
|
|
43
|
+
errors.push("hintHelpful must be a boolean or null");
|
|
44
|
+
return errors;
|
|
45
|
+
}
|
|
46
|
+
/** Resolve the reply payload from --file or --reply. Throws on missing/invalid input. */
|
|
47
|
+
export async function resolveReplyInput(o) {
|
|
48
|
+
let text;
|
|
49
|
+
if (o.reply !== undefined)
|
|
50
|
+
text = o.reply;
|
|
51
|
+
else if (o.file !== undefined)
|
|
52
|
+
text = await readFile(o.file, "utf8");
|
|
53
|
+
else
|
|
54
|
+
throw new Error("ci-reply requires --file <path> or --reply <json>");
|
|
55
|
+
let parsed;
|
|
56
|
+
try {
|
|
57
|
+
parsed = JSON.parse(text);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw new Error("reply input must be valid JSON");
|
|
61
|
+
}
|
|
62
|
+
const reply = (typeof parsed === "object" && parsed !== null && "reply" in parsed
|
|
63
|
+
? parsed.reply
|
|
64
|
+
: parsed);
|
|
65
|
+
const errors = validateReply(reply);
|
|
66
|
+
if (errors.length > 0)
|
|
67
|
+
throw new Error(`invalid reply: ${errors.join("; ")}`);
|
|
68
|
+
return reply;
|
|
69
|
+
}
|
|
70
|
+
/** Build the outcome record (pure; testable without I/O or DB). */
|
|
71
|
+
export function buildOutcome(reply, repliedBy) {
|
|
72
|
+
return {
|
|
73
|
+
messageId: reply.messageId,
|
|
74
|
+
disposition: reply.disposition,
|
|
75
|
+
fixCommitSha: reply.fixCommitSha ?? null,
|
|
76
|
+
note: reply.note ?? "",
|
|
77
|
+
wasFlaky: reply.wasFlaky ?? false,
|
|
78
|
+
hintHelpful: reply.hintHelpful ?? null,
|
|
79
|
+
repliedBy: repliedBy ?? null,
|
|
80
|
+
at: new Date().toISOString(),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Record the outcome. The default writer is a stub that returns the outcome
|
|
85
|
+
* unchanged (no DB in unit tests); wire the real ci_outcome_record() RPC call
|
|
86
|
+
* at the integration layer by passing recordOutcome.
|
|
87
|
+
*/
|
|
88
|
+
export async function recordReply(reply, opts = {}) {
|
|
89
|
+
const errors = validateReply(reply);
|
|
90
|
+
if (errors.length > 0)
|
|
91
|
+
throw new Error(`invalid reply: ${errors.join("; ")}`);
|
|
92
|
+
const outcome = buildOutcome(reply, opts.repliedBy);
|
|
93
|
+
if (opts.recordOutcome)
|
|
94
|
+
return opts.recordOutcome(outcome);
|
|
95
|
+
return outcome;
|
|
96
|
+
}
|
|
97
|
+
/** CLI entry point: `codebus ci-reply --file <path> [--replied-by id] [--json]`. */
|
|
98
|
+
export async function ciReplyCmd(o) {
|
|
99
|
+
let reply;
|
|
100
|
+
try {
|
|
101
|
+
reply = await resolveReplyInput(o);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
105
|
+
process.exitCode = 1;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const outcome = buildOutcome(reply, o.repliedBy);
|
|
109
|
+
if (o.json) {
|
|
110
|
+
console.log(JSON.stringify(outcome, null, 2));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
console.log(`Replied [${outcome.disposition}] ${outcome.messageId}` +
|
|
114
|
+
(outcome.fixCommitSha ? ` fix=${outcome.fixCommitSha}` : "") +
|
|
115
|
+
(outcome.wasFlaky ? " (flaky)" : ""));
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=ci-reply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci-reply.js","sourceRoot":"","sources":["../../src/commands/ci-reply.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ci-steer-escalate — CLI command: escalate a CI finding to a human owner.
|
|
3
|
+
*
|
|
4
|
+
* Input: a single ci-finding v1 object (via --file <path> or --finding <json>).
|
|
5
|
+
* Output: an escalation record printed as text or --json. Exits non-zero when
|
|
6
|
+
* the input finding is invalid.
|
|
7
|
+
*/
|
|
8
|
+
import { readFile } from "node:fs/promises";
|
|
9
|
+
import { validateFinding } from "./ci-findings.js";
|
|
10
|
+
/** Resolve the finding payload from --file or --finding. Throws on missing/invalid input. */
|
|
11
|
+
export async function resolveEscalationInput(o) {
|
|
12
|
+
let text;
|
|
13
|
+
if (o.finding !== undefined)
|
|
14
|
+
text = o.finding;
|
|
15
|
+
else if (o.file !== undefined)
|
|
16
|
+
text = await readFile(o.file, "utf8");
|
|
17
|
+
else
|
|
18
|
+
throw new Error("ci-steer-escalate requires --file <path> or --finding <json>");
|
|
19
|
+
let parsed;
|
|
20
|
+
try {
|
|
21
|
+
parsed = JSON.parse(text);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw new Error("escalation input must be valid JSON");
|
|
25
|
+
}
|
|
26
|
+
const finding = (typeof parsed === "object" && parsed !== null && "finding" in parsed
|
|
27
|
+
? parsed.finding
|
|
28
|
+
: parsed);
|
|
29
|
+
const errors = validateFinding(finding);
|
|
30
|
+
if (errors.length > 0)
|
|
31
|
+
throw new Error(`invalid finding: ${errors.join("; ")}`);
|
|
32
|
+
return finding;
|
|
33
|
+
}
|
|
34
|
+
/** Build the escalation record (pure; testable without I/O). */
|
|
35
|
+
export function buildEscalation(finding, owner, reason) {
|
|
36
|
+
return {
|
|
37
|
+
escalated: true,
|
|
38
|
+
check: finding.check,
|
|
39
|
+
kind: finding.kind,
|
|
40
|
+
location: finding.location,
|
|
41
|
+
next_action: "escalate",
|
|
42
|
+
owner,
|
|
43
|
+
reason: reason ?? `escalated from ${finding.check} (${finding.next_action})`,
|
|
44
|
+
at: new Date().toISOString(),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** CLI entry point: `codebus ci-steer-escalate --file <path> [--owner o] [--reason r] [--json]`. */
|
|
48
|
+
export async function ciSteerEscalateCmd(o) {
|
|
49
|
+
let finding;
|
|
50
|
+
try {
|
|
51
|
+
finding = await resolveEscalationInput(o);
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
55
|
+
process.exitCode = 1;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const record = buildEscalation(finding, o.owner ?? "ci-owner", o.reason);
|
|
59
|
+
if (o.json) {
|
|
60
|
+
console.log(JSON.stringify(record, null, 2));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
console.log(`Escalated [${record.kind}] ${record.check} (${record.location}) to ${record.owner}: ${record.reason}`);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=ci-steer-escalate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci-steer-escalate.js","sourceRoot":"","sources":["../../src/commands/ci-steer-escalate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAa,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAqB9D,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,CAAyB;IACpE,IAAI,IAAwB,CAAC;IAC7B,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS;QAAE,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC;SACzC,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;QAAE,IAAI,GAAG,MAAM,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;;QAChE,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;IACrF,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,SAAS,IAAK,MAAkC;QAChH,CAAC,CAAE,MAAiC,CAAC,OAAO;QAC5C,CAAC,CAAC,MAAM,CAAc,CAAC;IACzB,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,eAAe,CAAC,OAAkB,EAAE,KAAa,EAAE,MAAe;IAChF,OAAO;QACL,SAAS,EAAE,IAAI;QACf,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,WAAW,EAAE,UAAU;QACvB,KAAK;QACL,MAAM,EAAE,MAAM,IAAI,kBAAkB,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,WAAW,GAAG;QAC5E,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KAC7B,CAAC;AACJ,CAAC;AAED,oGAAoG;AACpG,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,CAAyB;IAChE,IAAI,OAAkB,CAAC;IACvB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACzE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,QAAQ,QAAQ,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AACtH,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command: `codebus correlation` — query and display the T-01 correlation chain.
|
|
3
|
+
*
|
|
4
|
+
* Shared command core for MCP parity: calls correlationQueryCore which is
|
|
5
|
+
* also used by the MCP tool in mcp-registry.ts.
|
|
6
|
+
*
|
|
7
|
+
* ADR 0007 (owner ruling): tests verify transport parity but cannot implement
|
|
8
|
+
* the feature — the feature lives here, tests assert.
|
|
9
|
+
*/
|
|
10
|
+
import { makeCtx } from "../client.js";
|
|
11
|
+
import { resolveConfig } from "../config.js";
|
|
12
|
+
import { CodebusError } from "../errors.js";
|
|
13
|
+
import { correlationCmd } from "./correlation.js";
|
|
14
|
+
import { withCorrelation, resolveCorrelation, validateBinding, } from "../mcp-correlation.js";
|
|
15
|
+
/**
|
|
16
|
+
* Shared command core: query correlation chain.
|
|
17
|
+
* Exported for use in MCP tool (mcp-registry.ts) and CLI command wrapper below.
|
|
18
|
+
*
|
|
19
|
+
* Input: partial correlation data (binding_id or run_id)
|
|
20
|
+
* Output: full T-01 correlation chain (or error if not found/not authorized)
|
|
21
|
+
*/
|
|
22
|
+
export async function correlationQueryCore(ctx, opts) {
|
|
23
|
+
// Validate input
|
|
24
|
+
if (!opts.bindingId && !opts.runId) {
|
|
25
|
+
throw new CodebusError("correlation query requires either binding_id or run_id", {
|
|
26
|
+
code: "INVALID_REQUEST",
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
// Query the correlation chain — resolveCorrelation handles both
|
|
30
|
+
// binding_id-only and run_id-only (via external_run_id) lookups.
|
|
31
|
+
// NOTE: requireBinding must NOT fail early on a run_id-only query: the run
|
|
32
|
+
// may well resolve to a real binding via execution_bindings.external_run_id.
|
|
33
|
+
// T-02 is enforced on the RESOLVED chain below, so a fabricated/unfetchable
|
|
34
|
+
// binding_id (stripped by resolveCorrelation) and a genuinely unbound run
|
|
35
|
+
// both fail — while a run_id that resolves to a real binding passes.
|
|
36
|
+
const chain = await resolveCorrelation(ctx, {
|
|
37
|
+
binding_id: opts.bindingId,
|
|
38
|
+
run_id: opts.runId,
|
|
39
|
+
});
|
|
40
|
+
// Validate results if requested
|
|
41
|
+
if (opts.requireBinding && !chain.binding_id) {
|
|
42
|
+
const validation = validateBinding(chain, opts.requireFull);
|
|
43
|
+
throw new CodebusError(validation.reason, { code: "BINDING_REQUIRED" });
|
|
44
|
+
}
|
|
45
|
+
if (opts.requireFull) {
|
|
46
|
+
const validation = validateBinding(chain, true);
|
|
47
|
+
if (!validation.valid) {
|
|
48
|
+
throw new CodebusError(validation.reason, { code: "CORRELATION_INCOMPLETE" });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return chain;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* CLI wrapper: `codebus correlation [--binding-id <id>] [--run-id <id>]`
|
|
55
|
+
*
|
|
56
|
+
* Calls correlationQueryCore with parity envelope wrapping (for --json output).
|
|
57
|
+
*/
|
|
58
|
+
async function correlationCommand(opts, overrides) {
|
|
59
|
+
const ctx = await makeCtx(resolveConfig(overrides));
|
|
60
|
+
// For --json output, use the parity envelope (CLI transport)
|
|
61
|
+
if (opts.json) {
|
|
62
|
+
const envelope = await withCorrelation((c, args) => correlationQueryCore(c, {
|
|
63
|
+
bindingId: args.bindingId,
|
|
64
|
+
runId: args.runId,
|
|
65
|
+
requireBinding: args.requireBinding,
|
|
66
|
+
requireFull: args.requireFull,
|
|
67
|
+
}), ctx, { bindingId: opts.bindingId, runId: opts.runId, requireBinding: opts.requireBinding, requireFull: opts.requireFull }, { transport: "cli", correlationPartial: { binding_id: opts.bindingId, run_id: opts.runId } });
|
|
68
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// Human output: just the chain
|
|
72
|
+
const chain = await correlationQueryCore(ctx, {
|
|
73
|
+
bindingId: opts.bindingId,
|
|
74
|
+
runId: opts.runId,
|
|
75
|
+
requireBinding: opts.requireBinding,
|
|
76
|
+
requireFull: opts.requireFull,
|
|
77
|
+
});
|
|
78
|
+
const lines = [
|
|
79
|
+
`Jira key: ${chain.jira_key || "(none)"}`,
|
|
80
|
+
`Plan: ${chain.plan_id || "(none)"}`,
|
|
81
|
+
`Stage: ${chain.stage_id || "(none)"}`,
|
|
82
|
+
`Child: ${chain.child_id || "(none)"}`,
|
|
83
|
+
`Binding: ${chain.binding_id || "(none)"}`,
|
|
84
|
+
`Run: ${chain.run_id || "(none)"}`,
|
|
85
|
+
`PR: ${chain.pr || "(none)"}`,
|
|
86
|
+
`Receipt: ${chain.receipt_id || "(none)"}`,
|
|
87
|
+
`Actor: ${chain.actor || "(none)"}`,
|
|
88
|
+
`Environment: ${chain.environment || "(none)"}`,
|
|
89
|
+
];
|
|
90
|
+
console.log(lines.join("\n"));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Register the CLI command with commander.
|
|
94
|
+
* Called by index.ts to attach to the main CLI via the g wrapper (adds
|
|
95
|
+
* --url/--token/--agent/--workspace/--json standard options).
|
|
96
|
+
*
|
|
97
|
+
* If a `correlation` command already exists on the program (main's T-01
|
|
98
|
+
* chain BUILDER, commands/correlation.ts), this EXTENDS it with the
|
|
99
|
+
* lookup flags and routes in the action handler: lookup flags present →
|
|
100
|
+
* database-resolved query core (this file); otherwise → the existing
|
|
101
|
+
* builder. Registering a second `correlation` command would make
|
|
102
|
+
* commander throw ("cannot add command 'correlation' as already have
|
|
103
|
+
* command 'correlation'") and crash the whole CLI at import time.
|
|
104
|
+
*/
|
|
105
|
+
export function registerCorrelationCommand(program, g) {
|
|
106
|
+
const existing = program.commands.find((c) => c.name() === "correlation");
|
|
107
|
+
const cmd = existing ?? g(program.command("correlation"))
|
|
108
|
+
.description("Query the T-01 correlation chain (Jira → Plan → Stage → Child → Binding → Run → PR → Receipt)");
|
|
109
|
+
cmd
|
|
110
|
+
.option("--binding-id <id>", "Lookup by binding UUID")
|
|
111
|
+
.option("--run-id <id>", "Lookup by run ID (resolves bindings via external_run_id)")
|
|
112
|
+
.option("--require-binding", "Fail if no binding exists (T-02)")
|
|
113
|
+
.option("--require-full", "Fail if any chain field is null")
|
|
114
|
+
// commander calls action(options, command); the parsed options ARE the
|
|
115
|
+
// Overrides (url/token/agent/workspace) — passing `command` here would
|
|
116
|
+
// silently drop every connection flag (resolveConfig would see env only).
|
|
117
|
+
// commander keeps ONE action handler (last .action() wins), so when
|
|
118
|
+
// extending main's builder command this router REPLACES its handler and
|
|
119
|
+
// delegates back to correlationCmd for the build path.
|
|
120
|
+
.action((opts) => {
|
|
121
|
+
const lookupMode = opts.bindingId !== undefined ||
|
|
122
|
+
opts.runId !== undefined ||
|
|
123
|
+
opts.requireBinding !== undefined ||
|
|
124
|
+
opts.requireFull !== undefined;
|
|
125
|
+
if (lookupMode || !existing) {
|
|
126
|
+
return correlationCommand(opts, opts);
|
|
127
|
+
}
|
|
128
|
+
return correlationCmd(opts);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=cli-mcp-correlation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-mcp-correlation.js","sourceRoot":"","sources":["../../src/commands/cli-mcp-correlation.ts"],"names":[],"mappings":"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"}
|