@maind-dev/cli 0.1.0 → 0.4.0

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.
@@ -0,0 +1,146 @@
1
+ // `maind ci-report` — report a CI failure as a draft-lesson candidate (ADR-207
2
+ // Phase 2, INGESTION). An agent running in the CI runner authors a lesson
3
+ // candidate (frontmatter + body) capturing the gotcha + fix; this command reads
4
+ // that file, attaches CI provenance from the runner env, and POSTs it to the
5
+ // maind ingest endpoint with the CI key. maind files it in the maintainer review
6
+ // inbox — never auto-published.
7
+ //
8
+ // Fail-open by contract: a failing report must never further break the build.
9
+ // Any error → stderr warning, exit 0. (This already runs in an on-failure step.)
10
+ import { createHash } from "node:crypto";
11
+ import { readFileSync } from "node:fs";
12
+ import { MissingApiKeyError, resolveAuth } from "./auth.js";
13
+ const DEFAULT_REPORT_URL = "https://app.maind.dev/api/ci/report";
14
+ export function parseCiReportArgs(argv) {
15
+ const get = (name) => {
16
+ const i = argv.indexOf(name);
17
+ if (i === -1 || i + 1 >= argv.length)
18
+ return undefined;
19
+ return argv[i + 1];
20
+ };
21
+ return {
22
+ lessonPath: get("--lesson") ?? null,
23
+ rationale: get("--rationale") ?? null,
24
+ failureType: get("--failure-type") ?? null,
25
+ signature: get("--signature") ?? null,
26
+ summary: get("--summary") ?? null,
27
+ provider: get("--provider") ?? "github-actions",
28
+ logsPath: get("--logs") ?? null,
29
+ remediation: get("--remediation") ?? null,
30
+ reportUrl: get("--report-url") ?? process.env.MAIND_REPORT_URL ?? DEFAULT_REPORT_URL,
31
+ };
32
+ }
33
+ /** Collects CI run metadata from the runner environment (GitHub Actions today). */
34
+ function ciEnv() {
35
+ const env = process.env;
36
+ const runId = env.GITHUB_RUN_ID;
37
+ const repo = env.GITHUB_REPOSITORY;
38
+ const server = env.GITHUB_SERVER_URL ?? "https://github.com";
39
+ return {
40
+ workflow_name: env.GITHUB_WORKFLOW || undefined,
41
+ run_id: runId || undefined,
42
+ run_url: runId && repo ? `${server}/${repo}/actions/runs/${runId}` : undefined,
43
+ };
44
+ }
45
+ function sha256(s) {
46
+ return createHash("sha256").update(s, "utf8").digest("hex");
47
+ }
48
+ /** Runs the report. Always returns 0 (fail-open). */
49
+ export async function runCiReport(opts) {
50
+ try {
51
+ if (!opts.lessonPath) {
52
+ warn("missing --lesson <path-to-authored-lesson.md>; nothing to report.");
53
+ return 0;
54
+ }
55
+ if (!opts.rationale) {
56
+ warn("missing --rationale; the agent should explain why this is a lesson.");
57
+ return 0;
58
+ }
59
+ if (!opts.failureType) {
60
+ warn("missing --failure-type (e.g. tsc-error, test-failure).");
61
+ return 0;
62
+ }
63
+ const lesson = readFileSync(opts.lessonPath, "utf8");
64
+ if (lesson.trim().length < 50) {
65
+ warn("authored lesson is too short — skipping report.");
66
+ return 0;
67
+ }
68
+ const env = ciEnv();
69
+ const runId = env.run_id ?? "local";
70
+ // Stable signature: explicit flag wins; else derive from failure-type + a
71
+ // hash of the lesson so the same recurring failure dedups server-side.
72
+ const signature = opts.signature ?? `${opts.failureType}:${sha256(opts.failureType + lesson).slice(0, 16)}`;
73
+ const provenance = {
74
+ ci_provider: opts.provider,
75
+ run_id: runId,
76
+ failure_type: opts.failureType,
77
+ failure_signature: signature,
78
+ draft_rationale: opts.rationale,
79
+ };
80
+ if (env.workflow_name)
81
+ provenance.workflow_name = env.workflow_name;
82
+ if (env.run_url)
83
+ provenance.run_url = env.run_url;
84
+ if (opts.summary)
85
+ provenance.failure_summary = opts.summary;
86
+ if (opts.remediation)
87
+ provenance.remediation_hint = opts.remediation;
88
+ if (opts.logsPath) {
89
+ try {
90
+ provenance.failure_logs = readFileSync(opts.logsPath, "utf8").slice(0, 8000);
91
+ }
92
+ catch {
93
+ // logs are best-effort
94
+ }
95
+ }
96
+ const auth = resolveAuth();
97
+ const body = JSON.stringify({
98
+ lesson,
99
+ content_hash: sha256(lesson),
100
+ ci_provenance: provenance,
101
+ });
102
+ let res;
103
+ try {
104
+ res = await fetch(opts.reportUrl, {
105
+ method: "POST",
106
+ headers: {
107
+ "content-type": "application/json",
108
+ authorization: `Bearer ${auth.apiKey}`,
109
+ },
110
+ body,
111
+ });
112
+ }
113
+ catch (err) {
114
+ warn(`network error posting to ${opts.reportUrl}: ${msg(err)}`);
115
+ return 0;
116
+ }
117
+ const text = await res.text().catch(() => "");
118
+ if (!res.ok) {
119
+ warn(`ingest rejected (HTTP ${res.status}): ${text.slice(0, 300)}`);
120
+ return 0;
121
+ }
122
+ let parsed = {};
123
+ try {
124
+ parsed = JSON.parse(text);
125
+ }
126
+ catch {
127
+ // non-JSON 200 — treat as success but unparseable
128
+ }
129
+ process.stderr.write(`maind ci-report: ${parsed.deduplicated ? "deduplicated" : "filed"} draft ${parsed.draft_id ?? "?"}` +
130
+ (parsed.review_url ? ` → ${parsed.review_url}` : "") +
131
+ "\n");
132
+ return 0;
133
+ }
134
+ catch (err) {
135
+ const reason = err instanceof MissingApiKeyError ? err.message : msg(err);
136
+ warn(`report failed, continuing: ${reason}`);
137
+ return 0;
138
+ }
139
+ }
140
+ function msg(err) {
141
+ return err instanceof Error ? err.message : String(err);
142
+ }
143
+ function warn(line) {
144
+ process.stderr.write(`maind ci-report: ${line}\n`);
145
+ }
146
+ //# sourceMappingURL=ci-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-report.js","sourceRoot":"","sources":["../src/ci-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,145 @@
1
+ // `maind ci-result` — report a CI build outcome (success|failure) together with
2
+ // the served-lesson manifest (ADR-207 Phase 3, FEEDBACK). For every lesson that
3
+ // was in the agent's context for this run (from `maind context`'s manifest.json),
4
+ // maind records a per-run CI signal. The aggregate "CI-confirmed N×" is shown to
5
+ // maintainers as a human-gated signal — it never changes a lesson's trust
6
+ // automatically. The signal means "this lesson was in context for N green runs"
7
+ // (correlation, not causation).
8
+ //
9
+ // Fail-open by contract: a failing report must never break the build. Any error
10
+ // → stderr warning, exit 0. Runs at the end of a job (success OR failure).
11
+ import { readFileSync } from "node:fs";
12
+ import { MissingApiKeyError, resolveAuth } from "./auth.js";
13
+ const DEFAULT_RESULT_URL = "https://app.maind.dev/api/ci/result";
14
+ export function parseCiResultArgs(argv) {
15
+ const get = (name) => {
16
+ const i = argv.indexOf(name);
17
+ if (i === -1 || i + 1 >= argv.length)
18
+ return undefined;
19
+ return argv[i + 1];
20
+ };
21
+ return {
22
+ outcome: get("--outcome") ?? null,
23
+ manifestPath: get("--manifest") ?? ".maind/manifest.json",
24
+ runRef: get("--run-ref") ?? null,
25
+ runUrl: get("--run-url") ?? null,
26
+ resultUrl: get("--result-url") ?? process.env.MAIND_RESULT_URL ?? DEFAULT_RESULT_URL,
27
+ };
28
+ }
29
+ /**
30
+ * Normalizes common CI outcome spellings (incl. GitHub Actions `${{ job.status }}`
31
+ * → success|failure|cancelled) to the two states the server records.
32
+ */
33
+ function normalizeOutcome(raw) {
34
+ const s = raw.trim().toLowerCase();
35
+ if (["success", "passed", "pass", "passing", "ok", "green", "0"].includes(s))
36
+ return "success";
37
+ if (["failure", "failed", "fail", "failing", "error", "red", "cancelled", "canceled"].includes(s)) {
38
+ return "failure";
39
+ }
40
+ return null;
41
+ }
42
+ /** Collects CI run metadata from the runner environment (GitHub Actions today). */
43
+ function ciEnv() {
44
+ const env = process.env;
45
+ const runId = env.GITHUB_RUN_ID;
46
+ const repo = env.GITHUB_REPOSITORY;
47
+ const server = env.GITHUB_SERVER_URL ?? "https://github.com";
48
+ return {
49
+ run_id: runId || undefined,
50
+ run_url: runId && repo ? `${server}/${repo}/actions/runs/${runId}` : undefined,
51
+ };
52
+ }
53
+ /** Runs the result report. Always returns 0 (fail-open). */
54
+ export async function runCiResult(opts) {
55
+ try {
56
+ if (!opts.outcome) {
57
+ warn("missing --outcome <success|failure> (e.g. --outcome ${{ job.status }}).");
58
+ return 0;
59
+ }
60
+ const outcome = normalizeOutcome(opts.outcome);
61
+ if (!outcome) {
62
+ warn(`unrecognized --outcome '${opts.outcome}'; expected success|failure.`);
63
+ return 0;
64
+ }
65
+ let manifestRaw;
66
+ try {
67
+ manifestRaw = readFileSync(opts.manifestPath, "utf8");
68
+ }
69
+ catch {
70
+ warn(`no manifest at ${opts.manifestPath} (did 'maind context' run first?); nothing to attribute.`);
71
+ return 0;
72
+ }
73
+ let manifest;
74
+ try {
75
+ manifest = JSON.parse(manifestRaw);
76
+ }
77
+ catch {
78
+ warn(`manifest at ${opts.manifestPath} is not valid JSON; skipping.`);
79
+ return 0;
80
+ }
81
+ const lessonIds = Array.isArray(manifest.served)
82
+ ? manifest.served.map((s) => s.id).filter((id) => typeof id === "string" && id.length > 0)
83
+ : [];
84
+ if (lessonIds.length === 0) {
85
+ warn("manifest lists no served lessons; nothing to report.");
86
+ return 0;
87
+ }
88
+ const env = ciEnv();
89
+ const runRef = opts.runRef ?? manifest.run_ref ?? env.run_id ?? null;
90
+ if (!runRef) {
91
+ warn("no run ref (--run-ref / manifest.run_ref / $GITHUB_RUN_ID); cannot attribute an outcome.");
92
+ return 0;
93
+ }
94
+ const runUrl = opts.runUrl ?? env.run_url ?? null;
95
+ const auth = resolveAuth();
96
+ const body = JSON.stringify({
97
+ outcome,
98
+ run_ref: runRef,
99
+ run_url: runUrl,
100
+ lesson_ids: lessonIds,
101
+ });
102
+ let res;
103
+ try {
104
+ res = await fetch(opts.resultUrl, {
105
+ method: "POST",
106
+ headers: {
107
+ "content-type": "application/json",
108
+ authorization: `Bearer ${auth.apiKey}`,
109
+ },
110
+ body,
111
+ });
112
+ }
113
+ catch (err) {
114
+ warn(`network error posting to ${opts.resultUrl}: ${msg(err)}`);
115
+ return 0;
116
+ }
117
+ const text = await res.text().catch(() => "");
118
+ if (!res.ok) {
119
+ warn(`ingest rejected (HTTP ${res.status}): ${text.slice(0, 300)}`);
120
+ return 0;
121
+ }
122
+ let parsed = {};
123
+ try {
124
+ parsed = JSON.parse(text);
125
+ }
126
+ catch {
127
+ // non-JSON 200 — treat as success but unparseable
128
+ }
129
+ process.stderr.write(`maind ci-result: ${outcome} · recorded ${parsed.recorded ?? "?"} · skipped ${parsed.skipped ?? 0}` +
130
+ ` (run ${runRef})\n`);
131
+ return 0;
132
+ }
133
+ catch (err) {
134
+ const reason = err instanceof MissingApiKeyError ? err.message : msg(err);
135
+ warn(`result failed, continuing: ${reason}`);
136
+ return 0;
137
+ }
138
+ }
139
+ function msg(err) {
140
+ return err instanceof Error ? err.message : String(err);
141
+ }
142
+ function warn(line) {
143
+ process.stderr.write(`maind ci-result: ${line}\n`);
144
+ }
145
+ //# sourceMappingURL=ci-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-result.js","sourceRoot":"","sources":["../src/ci-result.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,212 @@
1
+ // `maind git-context` — a session-start briefing of the LOCAL git state, enriched
2
+ // with maind's parallel-session coordination (ADR-188) and state-relevant git
3
+ // lessons (ADR-212 v2 / B1). Run it before an agent starts work so it begins
4
+ // informed ("you're on feat/x, 3 ahead, CI red, a peer is editing src/auth.ts")
5
+ // instead of blind.
6
+ //
7
+ // Fail-open + fail-soft: local git state always renders; the MCP enrichment
8
+ // (peer conflicts, lessons) is best-effort and each piece degrades independently.
9
+ // No git remote, no API key, no network, no `gh` → you still get what's available.
10
+ // The remote URL never leaves the machine — only the project_key (sha256) does.
11
+ import { mkdirSync, writeFileSync } from "node:fs";
12
+ import { dirname } from "node:path";
13
+ import { resolveAuth } from "./auth.js";
14
+ import { McpClient } from "./mcp-client.js";
15
+ import { gatherGitState, gatherOpenPrs } from "./git.js";
16
+ export function parseGitContextArgs(argv) {
17
+ const get = (name) => {
18
+ const i = argv.indexOf(name);
19
+ if (i === -1 || i + 1 >= argv.length)
20
+ return undefined;
21
+ return argv[i + 1];
22
+ };
23
+ return {
24
+ out: get("--out") ?? ".maind/git-context.md",
25
+ manifest: get("--manifest") ?? null,
26
+ mcpUrl: get("--mcp-url") ?? null,
27
+ noMcp: argv.includes("--no-mcp"),
28
+ clientVersion: "0.4.0",
29
+ };
30
+ }
31
+ function nowIso() {
32
+ return new Date().toISOString();
33
+ }
34
+ function writeArtifact(path, content) {
35
+ const dir = dirname(path);
36
+ if (dir && dir !== ".")
37
+ mkdirSync(dir, { recursive: true });
38
+ writeFileSync(path, content, "utf8");
39
+ }
40
+ /** A state-aware query so the pulled lessons match the current situation. */
41
+ function stateQuery(git, prs) {
42
+ if (prs.some((p) => p.isCurrentBranch && p.ci === "failure"))
43
+ return "ci failure red build fix";
44
+ if ((git.behind ?? 0) > 0 && (git.ahead ?? 0) > 0)
45
+ return "rebase merge integration diverged branch";
46
+ if ((git.behind ?? 0) > 0)
47
+ return "branch behind main pull rebase update";
48
+ if (prs.some((p) => p.isCurrentBranch))
49
+ return "pull request review merge workflow";
50
+ if ((git.ahead ?? 0) > 0)
51
+ return "open pull request commit message branch";
52
+ return "git branch commit pull request workflow";
53
+ }
54
+ export async function runGitContext(opts) {
55
+ const git = gatherGitState();
56
+ // gh is optional; only probe when we're in a repo.
57
+ const prResult = git.isRepo ? gatherOpenPrs(git.branch) : { available: false, prs: [] };
58
+ let peer = null;
59
+ let lessons = [];
60
+ let lessonsAvailable = false;
61
+ if (!opts.noMcp && git.isRepo) {
62
+ try {
63
+ const auth = resolveAuth();
64
+ const client = new McpClient({
65
+ apiKey: auth.apiKey,
66
+ deviceId: auth.deviceId,
67
+ clientVersion: opts.clientVersion,
68
+ mcpUrl: opts.mcpUrl ?? undefined,
69
+ });
70
+ // Peer/conflict check — READ-ONLY (no announce → no phantom session).
71
+ if (git.projectKey && git.workingPaths.length > 0) {
72
+ try {
73
+ const c = await client.callTool("check_path_conflicts", {
74
+ project_key: git.projectKey,
75
+ paths: git.workingPaths,
76
+ });
77
+ peer = {
78
+ peersActive: c.peers_active ?? 0,
79
+ conflicts: (c.conflicts ?? [])
80
+ .filter((x) => x.path)
81
+ .map((x) => ({ path: x.path, focus: x.focus })),
82
+ recommendation: c.recommendation ?? null,
83
+ checked: true,
84
+ };
85
+ }
86
+ catch (err) {
87
+ warn(`peer check unavailable: ${msg(err)}`);
88
+ }
89
+ }
90
+ // State-relevant git lessons.
91
+ try {
92
+ const res = await client.callTool("search_lessons", {
93
+ query: stateQuery(git, prResult.prs),
94
+ platforms: ["git", "github"],
95
+ limit: 3,
96
+ });
97
+ lessons = Array.isArray(res.lessons) ? res.lessons : [];
98
+ lessonsAvailable = true;
99
+ }
100
+ catch (err) {
101
+ warn(`git lessons unavailable: ${msg(err)}`);
102
+ }
103
+ }
104
+ catch (err) {
105
+ // No API key / auth failure → local-only briefing, still useful.
106
+ warn(`maind enrichment skipped (${msg(err)}); rendering local git state only.`);
107
+ }
108
+ }
109
+ writeArtifact(opts.out, renderMarkdown(git, prResult, peer, lessons, lessonsAvailable));
110
+ if (opts.manifest) {
111
+ writeArtifact(opts.manifest, JSON.stringify(buildManifest(git, prResult.prs, peer), null, 2) + "\n");
112
+ }
113
+ process.stderr.write(`maind git-context: ${git.isRepo ? `${git.branch ?? "?"} (+${git.ahead ?? "?"}/-${git.behind ?? "?"})` : "not a git repo"}` +
114
+ (peer?.conflicts.length ? `, ${peer.conflicts.length} peer conflict(s)` : "") +
115
+ ` → ${opts.out}\n`);
116
+ return 0;
117
+ }
118
+ function ciIcon(ci) {
119
+ return ci === "success" ? "🟢" : ci === "failure" ? "🔴" : ci === "pending" ? "🟡" : "⚪";
120
+ }
121
+ function renderMarkdown(git, prResult, peer, lessons, lessonsAvailable) {
122
+ const L = [];
123
+ L.push("<!-- Generated by `maind git-context` — local git state for the agent. -->");
124
+ L.push(`<!-- generated_at: ${nowIso()} -->`);
125
+ L.push("");
126
+ L.push("# maind git-context");
127
+ L.push("");
128
+ if (!git.isRepo) {
129
+ L.push("_Not inside a git work tree — no git context to report._");
130
+ L.push("");
131
+ return L.join("\n");
132
+ }
133
+ const aheadBehind = git.defaultBranch != null
134
+ ? `${git.ahead ?? "?"} ahead, ${git.behind ?? "?"} behind \`${git.defaultBranch}\``
135
+ : "no upstream default branch resolved";
136
+ L.push(`**Branch:** \`${git.branch ?? "?"}\` — ${aheadBehind}`);
137
+ L.push(`**Working tree:** ${git.uncommitted} uncommitted change${git.uncommitted === 1 ? "" : "s"}`);
138
+ if (git.projectKey)
139
+ L.push(`**Project:** \`${git.projectKey.slice(0, 12)}…\` (sha256 of remote — URL never sent)`);
140
+ L.push("");
141
+ // Open PRs
142
+ if (prResult.available) {
143
+ if (prResult.prs.length === 0) {
144
+ L.push("**Open PRs:** none");
145
+ }
146
+ else {
147
+ L.push("**Open PRs:**");
148
+ for (const p of prResult.prs) {
149
+ const tag = p.isCurrentBranch ? ` ${ciIcon(p.ci)} CI:${p.ci} · this branch` : "";
150
+ L.push(`- #${p.number} ${p.title}${tag}`);
151
+ }
152
+ }
153
+ }
154
+ else {
155
+ L.push("**Open PRs:** _unavailable (`gh` not installed / not authenticated)_");
156
+ }
157
+ L.push("");
158
+ // Peers (ADR-188 coordination)
159
+ if (peer?.checked) {
160
+ if (peer.conflicts.length > 0) {
161
+ L.push(`**⚠ Parallel sessions on this repo:** ${peer.peersActive} active — path conflicts:`);
162
+ for (const c of peer.conflicts) {
163
+ L.push(`- \`${c.path}\`${c.focus ? ` — peer focus: ${c.focus}` : ""}`);
164
+ }
165
+ if (peer.recommendation)
166
+ L.push(`- _${peer.recommendation}_`);
167
+ }
168
+ else if (peer.peersActive > 0) {
169
+ L.push(`**Parallel sessions on this repo:** ${peer.peersActive} active — no conflict on your changed paths.`);
170
+ }
171
+ else {
172
+ L.push("**Parallel sessions on this repo:** none.");
173
+ }
174
+ }
175
+ else {
176
+ L.push("**Parallel sessions:** _not checked (no key / no changed paths / offline)._");
177
+ }
178
+ L.push("");
179
+ // Lessons
180
+ if (lessonsAvailable && lessons.length > 0) {
181
+ L.push("## Relevant git lessons (maind)");
182
+ for (const l of lessons) {
183
+ L.push(`- **${l.title ?? l.id}**${l.id ? ` \`${l.id}\`` : ""}`);
184
+ }
185
+ L.push("");
186
+ }
187
+ L.push("_Full PR workflow: `activate_skill({id:\"skill_pr_lifecycle\"})`._");
188
+ L.push("");
189
+ return L.join("\n");
190
+ }
191
+ function buildManifest(git, prs, peer) {
192
+ return {
193
+ schema: "maind.git-context/v1",
194
+ generated_at: nowIso(),
195
+ project_key: git.projectKey,
196
+ branch: git.branch,
197
+ default_branch: git.defaultBranch,
198
+ ahead: git.ahead,
199
+ behind: git.behind,
200
+ uncommitted: git.uncommitted,
201
+ open_prs: prs.map((p) => ({ number: p.number, ci: p.ci, current_branch: p.isCurrentBranch })),
202
+ peers_active: peer?.checked ? peer.peersActive : null,
203
+ path_conflicts: peer?.conflicts.map((c) => c.path) ?? [],
204
+ };
205
+ }
206
+ function msg(err) {
207
+ return err instanceof Error ? err.message : String(err);
208
+ }
209
+ function warn(line) {
210
+ process.stderr.write(`maind git-context: ${line}\n`);
211
+ }
212
+ //# sourceMappingURL=git-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-context.js","sourceRoot":"","sources":["../src/git-context.ts"],"names":[],"mappings":"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"}
package/build/git.js ADDED
@@ -0,0 +1,162 @@
1
+ // Local git/gh state gathering for `maind git-context` (ADR-212 v2 / B1).
2
+ //
3
+ // All gathering is CLIENT-SIDE — the maind server is repo-blind by design
4
+ // (ADR-188 privacy): only the project_key (sha256 of the normalized remote) and
5
+ // repo-relative paths ever leave this machine; the remote URL never does.
6
+ //
7
+ // Every probe is fail-soft: a missing git, no remote, or absent `gh` degrades to
8
+ // null/empty, never throws. The command around this is fail-open.
9
+ import { execFileSync } from "node:child_process";
10
+ import { createHash } from "node:crypto";
11
+ function run(bin, args) {
12
+ try {
13
+ return execFileSync(bin, args, {
14
+ encoding: "utf8",
15
+ stdio: ["ignore", "pipe", "ignore"],
16
+ timeout: 5000,
17
+ }).trim();
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ }
23
+ const git = (args) => run("git", args);
24
+ const gh = (args) => run("gh", args);
25
+ // ── project_key contract (replicated from apps/vscode-extension/src/harness/
26
+ // projectKey.ts — ADR-188). MUST normalize identically or sessions won't match
27
+ // across clients. Keep in sync; extract to a shared package when a third client
28
+ // needs it. ────────────────────────────────────────────────────────────────────
29
+ export function sha256Hex(input) {
30
+ return createHash("sha256").update(input).digest("hex");
31
+ }
32
+ export function normalizeRemoteUrl(raw) {
33
+ let s = raw.trim();
34
+ if (!s)
35
+ return null;
36
+ const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(s);
37
+ if (scheme) {
38
+ s = s.slice(scheme[0].length);
39
+ s = s.replace(/^[^@/]+@/, "");
40
+ s = s.replace(/^([^/:]+):\d+(?=\/)/, "$1");
41
+ }
42
+ else {
43
+ s = s.replace(/^[^@/]+@/, "");
44
+ const i = s.indexOf(":");
45
+ if (i >= 0)
46
+ s = `${s.slice(0, i)}/${s.slice(i + 1)}`;
47
+ }
48
+ s = s
49
+ .replace(/\.git$/i, "")
50
+ .replace(/\/+$/, "")
51
+ .toLowerCase();
52
+ return s.length > 0 ? s : null;
53
+ }
54
+ export function projectKeyFromRemote(raw) {
55
+ const norm = normalizeRemoteUrl(raw);
56
+ return norm ? sha256Hex(norm) : null;
57
+ }
58
+ function resolveDefaultBranch() {
59
+ // origin/HEAD → refs/remotes/origin/main (when set), else probe common names.
60
+ const sym = git(["symbolic-ref", "--quiet", "refs/remotes/origin/HEAD"]);
61
+ if (sym) {
62
+ const m = /refs\/remotes\/origin\/(.+)$/.exec(sym);
63
+ if (m)
64
+ return m[1];
65
+ }
66
+ for (const cand of ["main", "master"]) {
67
+ if (git(["rev-parse", "--verify", "--quiet", `origin/${cand}`]) !== null)
68
+ return cand;
69
+ }
70
+ return null;
71
+ }
72
+ export function gatherGitState() {
73
+ const inside = git(["rev-parse", "--is-inside-work-tree"]);
74
+ if (inside !== "true") {
75
+ return {
76
+ isRepo: false,
77
+ projectKey: null,
78
+ branch: null,
79
+ defaultBranch: null,
80
+ ahead: null,
81
+ behind: null,
82
+ uncommitted: 0,
83
+ workingPaths: [],
84
+ };
85
+ }
86
+ const remote = git(["config", "--get", "remote.origin.url"]);
87
+ const projectKey = remote ? projectKeyFromRemote(remote) : null;
88
+ const branch = git(["rev-parse", "--abbrev-ref", "HEAD"]);
89
+ const defaultBranch = resolveDefaultBranch();
90
+ let ahead = null;
91
+ let behind = null;
92
+ if (defaultBranch) {
93
+ // `--left-right --count A...B` → "<left> <right>": left = in A not B (behind),
94
+ // right = in B not A (ahead). Here A=origin/default, B=HEAD.
95
+ const counts = git(["rev-list", "--left-right", "--count", `origin/${defaultBranch}...HEAD`]);
96
+ if (counts) {
97
+ const [b, a] = counts.split(/\s+/).map((n) => Number.parseInt(n, 10));
98
+ if (Number.isFinite(b))
99
+ behind = b;
100
+ if (Number.isFinite(a))
101
+ ahead = a;
102
+ }
103
+ }
104
+ const porcelain = git(["status", "--porcelain"]) ?? "";
105
+ const changedLines = porcelain.split("\n").filter((l) => l.trim().length > 0);
106
+ const workingPaths = changedLines
107
+ .map((l) => l.slice(3).split(" -> ").pop().trim().replace(/^"|"$/g, ""))
108
+ .filter((p) => p.length > 0)
109
+ .slice(0, 32);
110
+ return {
111
+ isRepo: true,
112
+ projectKey,
113
+ branch,
114
+ defaultBranch,
115
+ ahead,
116
+ behind,
117
+ uncommitted: changedLines.length,
118
+ workingPaths,
119
+ };
120
+ }
121
+ function ciFromChecks(prNumber) {
122
+ const out = gh(["pr", "checks", String(prNumber), "--json", "bucket"]);
123
+ if (!out)
124
+ return "unknown";
125
+ try {
126
+ const rows = JSON.parse(out);
127
+ if (rows.length === 0)
128
+ return "unknown";
129
+ if (rows.some((r) => r.bucket === "fail"))
130
+ return "failure";
131
+ if (rows.some((r) => r.bucket === "pending"))
132
+ return "pending";
133
+ if (rows.every((r) => r.bucket === "pass" || r.bucket === "skipping"))
134
+ return "success";
135
+ return "unknown";
136
+ }
137
+ catch {
138
+ return "unknown";
139
+ }
140
+ }
141
+ export function gatherOpenPrs(currentBranch, max = 5) {
142
+ const out = gh(["pr", "list", "--state", "open", "--limit", String(max), "--json", "number,title,headRefName"]);
143
+ if (out === null)
144
+ return { available: false, prs: [] };
145
+ try {
146
+ const rows = JSON.parse(out);
147
+ const prs = rows.map((r) => ({
148
+ number: r.number,
149
+ title: r.title,
150
+ isCurrentBranch: currentBranch != null && r.headRefName === currentBranch,
151
+ // Only resolve CI for the current branch's PR (cheap) — others stay unknown to avoid N gh calls.
152
+ ci: currentBranch != null && r.headRefName === currentBranch
153
+ ? ciFromChecks(r.number)
154
+ : "unknown",
155
+ }));
156
+ return { available: true, prs };
157
+ }
158
+ catch {
159
+ return { available: false, prs: [] };
160
+ }
161
+ }
162
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
package/build/index.js CHANGED
@@ -10,14 +10,44 @@
10
10
  // STDOUT is reserved for command results that are meant to be piped; all
11
11
  // diagnostics go to STDERR. Today only the `context` command exists.
12
12
  import { parseContextArgs, runContext } from "./context.js";
13
- const VERSION = "0.1.0";
14
- const HELP = `maind ${VERSION} headless maind CLI for CI
13
+ import { parseCiReportArgs, runCiReport } from "./ci-report.js";
14
+ import { parseCiResultArgs, runCiResult } from "./ci-result.js";
15
+ import { parseGitContextArgs, runGitContext } from "./git-context.js";
16
+ const VERSION = "0.4.0";
17
+ const HELP = `maind ${VERSION} — headless maind CLI for CI + git context
15
18
 
16
19
  Usage:
17
20
  maind context [options] Pull stack-relevant lessons + conventions into the runner
21
+ maind git-context [options] Briefing of local git state + peers + relevant lessons (session-start)
22
+ maind ci-report [options] Report a CI failure as a draft-lesson candidate (on failure)
23
+ maind ci-result [options] Report a build outcome + served manifest (end of job)
18
24
  maind --help Show this help
19
25
  maind --version Print version
20
26
 
27
+ git-context options (run at session-start; reads local git + gh, all fail-open):
28
+ --out <path> Briefing markdown output (default .maind/git-context.md)
29
+ --manifest <path> Optional structured JSON output (git_context manifest)
30
+ --no-mcp Local git state only — skip peer-conflict + lesson enrichment
31
+ --mcp-url <url> Override MCP endpoint (default \$MAIND_MCP_URL or production)
32
+
33
+ ci-report options (run in an on-failure step; the agent authors the lesson first):
34
+ --lesson <path> Agent-authored lesson markdown (frontmatter + body) — required
35
+ --rationale <text> Why this is a reusable lesson — required
36
+ --failure-type <t> e.g. tsc-error, test-failure, lint-error — required
37
+ --signature <s> Stable dedup key (default: failure-type + lesson hash)
38
+ --summary <text> Short failure description
39
+ --remediation <text> Suggested fix
40
+ --logs <path> Optional failure-log file (truncated to 8k)
41
+ --provider <p> CI provider (default github-actions)
42
+ --report-url <url> Override ingest endpoint (default \$MAIND_REPORT_URL or prod)
43
+
44
+ ci-result options (run at the end of a job, success OR failure):
45
+ --outcome <s> Build outcome, e.g. \${{ job.status }} (success|failure) — required
46
+ --manifest <path> Served-lesson manifest from 'maind context' (default .maind/manifest.json)
47
+ --run-ref <id> Build identifier (default manifest.run_ref or \$GITHUB_RUN_ID)
48
+ --run-url <url> Link to the CI run (default derived from GitHub env)
49
+ --result-url <url> Override ingest endpoint (default \$MAIND_RESULT_URL or prod)
50
+
21
51
  context options:
22
52
  --stack <a,b> Stack hint (seeds the platforms filter), e.g. nextjs,supabase
23
53
  --platforms <a,b> Explicit platforms filter (overrides --stack)
@@ -49,6 +79,15 @@ async function main() {
49
79
  if (cmd === "context") {
50
80
  return runContext(parseContextArgs(argv.slice(1)));
51
81
  }
82
+ if (cmd === "git-context") {
83
+ return runGitContext(parseGitContextArgs(argv.slice(1)));
84
+ }
85
+ if (cmd === "ci-report") {
86
+ return runCiReport(parseCiReportArgs(argv.slice(1)));
87
+ }
88
+ if (cmd === "ci-result") {
89
+ return runCiResult(parseCiResultArgs(argv.slice(1)));
90
+ }
52
91
  process.stderr.write(`maind: unknown command '${cmd}'. Run 'maind --help'.\n`);
53
92
  return 2;
54
93
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,EAAE;AACF,gCAAgC;AAChC,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAC3E,gFAAgF;AAChF,sEAAsE;AACtE,EAAE;AACF,yEAAyE;AACzE,qEAAqE;AAErE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE5D,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,MAAM,IAAI,GAAG,SAAS,OAAO;;;;;;;;;;;;;;;;;;;;;;;CAuB5B,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAEpB,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QAC/D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;QACrC,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,GAAG,0BAA0B,CAAC,CAAC;IAC/E,OAAO,CAAC,CAAC;AACX,CAAC;AAED,IAAI,EAAE;KACH,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;KAClC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACb,+EAA+E;IAC/E,2EAA2E;IAC3E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,EAAE;AACF,gCAAgC;AAChC,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAC3E,gFAAgF;AAChF,sEAAsE;AACtE,EAAE;AACF,yEAAyE;AACzE,qEAAqE;AAErE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtE,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,MAAM,IAAI,GAAG,SAAS,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkD5B,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAEpB,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QAC/D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;QACrC,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,GAAG,KAAK,aAAa,EAAE,CAAC;QAC1B,OAAO,aAAa,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;QACxB,OAAO,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;QACxB,OAAO,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,GAAG,0BAA0B,CAAC,CAAC;IAC/E,OAAO,CAAC,CAAC;AACX,CAAC;AAED,IAAI,EAAE;KACH,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;KAClC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACb,+EAA+E;IAC/E,2EAA2E;IAC3E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maind-dev/cli",
3
- "version": "0.1.0",
4
- "description": "Headless maind CLI — pull stack-relevant lessons into CI runners and emit a context manifest for build-outcome attribution. No device flow; authenticates from MAIND_API_KEY.",
3
+ "version": "0.4.0",
4
+ "description": "Headless maind CLI — pull stack-relevant lessons into CI runners, report CI outcomes, and brief agents on local git state (branch, PRs, peers). No device flow; authenticates from MAIND_API_KEY.",
5
5
  "type": "module",
6
6
  "main": "./build/index.js",
7
7
  "bin": {