@maind-dev/cli 0.6.0 → 0.7.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 @@
1
+ {"inputs":{"src/auth.ts":{"bytes":3441,"imports":[{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true}],"format":"esm"},"src/mcp-client.ts":{"bytes":8724,"imports":[],"format":"esm"},"src/render.ts":{"bytes":4525,"imports":[],"format":"esm"},"src/context.ts":{"bytes":6805,"imports":[{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"src/auth.ts","kind":"import-statement","original":"./auth.js"},{"path":"src/mcp-client.ts","kind":"import-statement","original":"./mcp-client.js"},{"path":"src/render.ts","kind":"import-statement","original":"./render.js"}],"format":"esm"},"../../packages/project-key/build/index.js":{"bytes":3446,"imports":[{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:crypto","kind":"import-statement","external":true}],"format":"esm"},"src/git.ts":{"bytes":5748,"imports":[{"path":"node:child_process","kind":"import-statement","external":true},{"path":"../../packages/project-key/build/index.js","kind":"import-statement","original":"@maind/project-key"},{"path":"../../packages/project-key/build/index.js","kind":"import-statement","original":"@maind/project-key"}],"format":"esm"},"src/ci-report.ts":{"bytes":6631,"imports":[{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"src/auth.ts","kind":"import-statement","original":"./auth.js"},{"path":"src/git.ts","kind":"import-statement","original":"./git.js"}],"format":"esm"},"src/ci-result.ts":{"bytes":5483,"imports":[{"path":"node:fs","kind":"import-statement","external":true},{"path":"src/auth.ts","kind":"import-statement","original":"./auth.js"}],"format":"esm"},"src/git-context.ts":{"bytes":9481,"imports":[{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"src/auth.ts","kind":"import-statement","original":"./auth.js"},{"path":"src/mcp-client.ts","kind":"import-statement","original":"./mcp-client.js"},{"path":"src/git.ts","kind":"import-statement","original":"./git.js"}],"format":"esm"},"../../packages/code-index/build/parse/keys.js":{"bytes":448,"imports":[],"format":"esm"},"../../packages/code-index/build/parse/types.js":{"bytes":768,"imports":[],"format":"esm"},"../../packages/code-index/build/parse/lang/shared.js":{"bytes":2278,"imports":[],"format":"esm"},"../../packages/code-index/build/parse/lang/python.js":{"bytes":4535,"imports":[{"path":"../../packages/code-index/build/parse/keys.js","kind":"import-statement","original":"../keys.js"},{"path":"../../packages/code-index/build/parse/lang/shared.js","kind":"import-statement","original":"./shared.js"}],"format":"esm"},"../../packages/code-index/build/parse/lang/typescript.js":{"bytes":5949,"imports":[{"path":"../../packages/code-index/build/parse/keys.js","kind":"import-statement","original":"../keys.js"},{"path":"../../packages/code-index/build/parse/lang/shared.js","kind":"import-statement","original":"./shared.js"}],"format":"esm"},"../../packages/code-index/build/parse/tree-sitter/grammars.js":{"bytes":1941,"imports":[{"path":"node:module","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true}],"format":"esm"},"../../packages/code-index/build/parse/tree-sitter/parser.js":{"bytes":3231,"imports":[{"path":"node:path","kind":"import-statement","external":true},{"path":"web-tree-sitter","kind":"import-statement","external":true},{"path":"../../packages/code-index/build/parse/keys.js","kind":"import-statement","original":"../keys.js"},{"path":"../../packages/code-index/build/parse/types.js","kind":"import-statement","original":"../types.js"},{"path":"../../packages/code-index/build/parse/lang/python.js","kind":"import-statement","original":"../lang/python.js"},{"path":"../../packages/code-index/build/parse/lang/typescript.js","kind":"import-statement","original":"../lang/typescript.js"},{"path":"../../packages/code-index/build/parse/lang/shared.js","kind":"import-statement","original":"../lang/shared.js"},{"path":"../../packages/code-index/build/parse/tree-sitter/grammars.js","kind":"import-statement","original":"./grammars.js"}],"format":"esm"},"../../packages/code-index/build/embed/recipe.js":{"bytes":594,"imports":[],"format":"esm"},"../../packages/code-index/build/embed/types.js":{"bytes":505,"imports":[],"format":"esm"},"../../packages/code-index/build/util/vector.js":{"bytes":707,"imports":[],"format":"esm"},"../../packages/code-index/build/graph/resolve.js":{"bytes":3928,"imports":[{"path":"node:path","kind":"import-statement","external":true},{"path":"../../packages/code-index/build/parse/keys.js","kind":"import-statement","original":"../parse/keys.js"}],"format":"esm"},"../../packages/code-index/build/incremental/discover.js":{"bytes":8578,"imports":[{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"../../packages/code-index/build/parse/types.js","kind":"import-statement","original":"../parse/types.js"}],"format":"esm"},"../../packages/code-index/build/incremental/hunks.js":{"bytes":6171,"imports":[{"path":"../../packages/code-index/build/incremental/discover.js","kind":"import-statement","original":"./discover.js"}],"format":"esm"},"../../packages/code-index/build/review/risk-rules.js":{"bytes":1958,"imports":[],"format":"esm"},"../../packages/code-index/build/review/risk-scan.js":{"bytes":1451,"imports":[{"path":"../../packages/code-index/build/review/risk-rules.js","kind":"import-statement","original":"./risk-rules.js"}],"format":"esm"},"../../packages/code-index/build/store/schema.js":{"bytes":3047,"imports":[],"format":"esm"},"../../packages/code-index/build/util/identifiers.js":{"bytes":2180,"imports":[],"format":"esm"},"../../packages/code-index/build/query/engine.js":{"bytes":18965,"imports":[{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"../../packages/code-index/build/embed/recipe.js","kind":"import-statement","original":"../embed/recipe.js"},{"path":"../../packages/code-index/build/embed/types.js","kind":"import-statement","original":"../embed/types.js"},{"path":"../../packages/code-index/build/util/vector.js","kind":"import-statement","original":"../util/vector.js"},{"path":"../../packages/code-index/build/graph/resolve.js","kind":"import-statement","original":"../graph/resolve.js"},{"path":"../../packages/code-index/build/incremental/discover.js","kind":"import-statement","original":"../incremental/discover.js"},{"path":"../../packages/code-index/build/incremental/hunks.js","kind":"import-statement","original":"../incremental/hunks.js"},{"path":"../../packages/code-index/build/review/risk-scan.js","kind":"import-statement","original":"../review/risk-scan.js"},{"path":"../../packages/code-index/build/store/schema.js","kind":"import-statement","original":"../store/schema.js"},{"path":"../../packages/code-index/build/util/identifiers.js","kind":"import-statement","original":"../util/identifiers.js"}],"format":"esm"},"../../packages/code-index/build/store/node-sqlite.js":{"bytes":11850,"imports":[{"path":"better-sqlite3","kind":"import-statement","external":true},{"path":"../../packages/code-index/build/store/schema.js","kind":"import-statement","original":"./schema.js"},{"path":"../../packages/code-index/build/util/identifiers.js","kind":"import-statement","original":"../util/identifiers.js"}],"format":"esm"},"../../packages/code-index/build/sync/types.js":{"bytes":1779,"imports":[{"path":"node:crypto","kind":"import-statement","external":true}],"format":"esm"},"../../packages/code-index/build/sync/client.js":{"bytes":10021,"imports":[{"path":"../../packages/code-index/build/store/schema.js","kind":"import-statement","original":"../store/schema.js"},{"path":"../../packages/code-index/build/sync/types.js","kind":"import-statement","original":"./types.js"}],"format":"esm"},"../../packages/code-index/build/node.js":{"bytes":2578,"imports":[{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"../../packages/project-key/build/index.js","kind":"import-statement","original":"@maind/project-key"},{"path":"../../packages/code-index/build/parse/tree-sitter/parser.js","kind":"import-statement","original":"./parse/tree-sitter/parser.js"},{"path":"../../packages/code-index/build/query/engine.js","kind":"import-statement","original":"./query/engine.js"},{"path":"../../packages/code-index/build/store/node-sqlite.js","kind":"import-statement","original":"./store/node-sqlite.js"},{"path":"../../packages/code-index/build/sync/client.js","kind":"import-statement","original":"./sync/client.js"},{"path":"../../packages/code-index/build/sync/client.js","kind":"import-statement","original":"./sync/client.js"}],"format":"esm"},"../../packages/embedding/build/index.js":{"bytes":6053,"imports":[{"path":"@huggingface/transformers","kind":"dynamic-import","external":true}],"format":"esm"},"../../packages/code-index/build/embed/node.js":{"bytes":661,"imports":[{"path":"../../packages/embedding/build/index.js","kind":"import-statement","original":"@maind/embedding"},{"path":"../../packages/code-index/build/embed/recipe.js","kind":"import-statement","original":"./recipe.js"}],"format":"esm"},"../../packages/code-index/build/node-embed.js":{"bytes":660,"imports":[{"path":"../../packages/code-index/build/embed/node.js","kind":"import-statement","original":"./embed/node.js"}],"format":"esm"},"src/index-cmd.ts":{"bytes":9353,"imports":[{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:url","kind":"import-statement","external":true},{"path":"../../packages/code-index/build/node.js","kind":"import-statement","original":"@maind/code-index/node"},{"path":"../../packages/code-index/build/node-embed.js","kind":"import-statement","original":"@maind/code-index/node-embed"}],"format":"esm"},"../../packages/code-index/build/model/types.js":{"bytes":471,"imports":[],"format":"esm"},"../../packages/code-index/build/index.js":{"bytes":1204,"imports":[{"path":"../../packages/code-index/build/model/types.js","kind":"import-statement","original":"./model/types.js"},{"path":"../../packages/code-index/build/query/engine.js","kind":"import-statement","original":"./query/engine.js"},{"path":"../../packages/code-index/build/review/risk-rules.js","kind":"import-statement","original":"./review/risk-rules.js"},{"path":"../../packages/code-index/build/parse/types.js","kind":"import-statement","original":"./parse/types.js"},{"path":"../../packages/code-index/build/embed/types.js","kind":"import-statement","original":"./embed/types.js"},{"path":"../../packages/code-index/build/store/schema.js","kind":"import-statement","original":"./store/schema.js"}],"format":"esm"},"src/review-render.ts":{"bytes":14139,"imports":[],"format":"esm"},"src/review.ts":{"bytes":16004,"imports":[{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"../../packages/code-index/build/node.js","kind":"import-statement","original":"@maind/code-index/node"},{"path":"../../packages/code-index/build/index.js","kind":"import-statement","original":"@maind/code-index"},{"path":"src/auth.ts","kind":"import-statement","original":"./auth.js"},{"path":"src/git.ts","kind":"import-statement","original":"./git.js"},{"path":"src/mcp-client.ts","kind":"import-statement","original":"./mcp-client.js"},{"path":"src/review-render.ts","kind":"import-statement","original":"./review-render.js"}],"format":"esm"},"src/sync-cmd.ts":{"bytes":5243,"imports":[{"path":"node:child_process","kind":"import-statement","external":true},{"path":"../../packages/code-index/build/node.js","kind":"import-statement","original":"@maind/code-index/node"},{"path":"src/auth.ts","kind":"import-statement","original":"./auth.js"}],"format":"esm"},"src/index.ts":{"bytes":9745,"imports":[{"path":"src/context.ts","kind":"import-statement","original":"./context.js"},{"path":"src/ci-report.ts","kind":"import-statement","original":"./ci-report.js"},{"path":"src/ci-result.ts","kind":"import-statement","original":"./ci-result.js"},{"path":"src/git-context.ts","kind":"import-statement","original":"./git-context.js"},{"path":"src/git.ts","kind":"import-statement","original":"./git.js"},{"path":"src/index-cmd.ts","kind":"import-statement","original":"./index-cmd.js"},{"path":"src/review.ts","kind":"import-statement","original":"./review.js"},{"path":"src/sync-cmd.ts","kind":"import-statement","original":"./sync-cmd.js"}],"format":"esm"}},"outputs":{"build/index.js":{"imports":[{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:url","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"web-tree-sitter","kind":"import-statement","external":true},{"path":"node:module","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"better-sqlite3","kind":"import-statement","external":true},{"path":"node:crypto","kind":"import-statement","external":true},{"path":"@huggingface/transformers","kind":"dynamic-import","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:fs","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true}],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/context.ts":{"bytesInOutput":4644},"src/auth.ts":{"bytesInOutput":1609},"src/mcp-client.ts":{"bytesInOutput":5955},"src/render.ts":{"bytesInOutput":2406},"src/ci-report.ts":{"bytesInOutput":4467},"src/git.ts":{"bytesInOutput":3325},"../../packages/project-key/build/index.js":{"bytesInOutput":1449},"src/ci-result.ts":{"bytesInOutput":3848},"src/git-context.ts":{"bytesInOutput":6854},"src/index-cmd.ts":{"bytesInOutput":6717},"../../packages/code-index/build/node.js":{"bytesInOutput":1159},"../../packages/code-index/build/parse/tree-sitter/parser.js":{"bytesInOutput":2043},"../../packages/code-index/build/parse/keys.js":{"bytesInOutput":169},"../../packages/code-index/build/parse/types.js":{"bytesInOutput":546},"../../packages/code-index/build/parse/lang/shared.js":{"bytesInOutput":1131},"../../packages/code-index/build/parse/lang/python.js":{"bytesInOutput":3747},"../../packages/code-index/build/parse/lang/typescript.js":{"bytesInOutput":4721},"../../packages/code-index/build/parse/tree-sitter/grammars.js":{"bytesInOutput":523},"../../packages/code-index/build/query/engine.js":{"bytesInOutput":13877},"../../packages/code-index/build/embed/recipe.js":{"bytesInOutput":229},"../../packages/code-index/build/embed/types.js":{"bytesInOutput":105},"../../packages/code-index/build/util/vector.js":{"bytesInOutput":339},"../../packages/code-index/build/graph/resolve.js":{"bytesInOutput":2486},"../../packages/code-index/build/incremental/discover.js":{"bytesInOutput":4855},"../../packages/code-index/build/incremental/hunks.js":{"bytesInOutput":3951},"../../packages/code-index/build/review/risk-rules.js":{"bytesInOutput":876},"../../packages/code-index/build/review/risk-scan.js":{"bytesInOutput":798},"../../packages/code-index/build/store/schema.js":{"bytesInOutput":2266},"../../packages/code-index/build/util/identifiers.js":{"bytesInOutput":1094},"../../packages/code-index/build/store/node-sqlite.js":{"bytesInOutput":9751},"../../packages/code-index/build/sync/types.js":{"bytesInOutput":875},"../../packages/code-index/build/sync/client.js":{"bytesInOutput":7568},"../../packages/embedding/build/index.js":{"bytesInOutput":1293},"../../packages/code-index/build/embed/node.js":{"bytesInOutput":288},"../../packages/code-index/build/node-embed.js":{"bytesInOutput":63},"src/review.ts":{"bytesInOutput":10816},"../../packages/code-index/build/index.js":{"bytesInOutput":34},"src/review-render.ts":{"bytesInOutput":7809},"src/sync-cmd.ts":{"bytesInOutput":3860},"src/index.ts":{"bytesInOutput":7760}},"bytes":138276}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maind-dev/cli",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
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",
@@ -12,14 +12,19 @@
12
12
  "README.md"
13
13
  ],
14
14
  "dependencies": {
15
- "@maind/code-index": "0.0.0",
16
- "@maind/project-key": "0.0.0",
17
- "@maind/embedding": "0.0.0"
15
+ "@huggingface/transformers": "^3.0.0",
16
+ "better-sqlite3": "^12.11.1",
17
+ "tree-sitter-wasms": "^0.1.13",
18
+ "web-tree-sitter": "0.24.7"
18
19
  },
19
20
  "devDependencies": {
20
21
  "@types/node": "^20.11.0",
22
+ "esbuild": "^0.24.0",
21
23
  "tsx": "^4.7.0",
22
- "typescript": "^5.4.0"
24
+ "typescript": "^5.4.0",
25
+ "@maind/code-index": "0.0.0",
26
+ "@maind/embedding": "0.0.0",
27
+ "@maind/project-key": "0.0.0"
23
28
  },
24
29
  "engines": {
25
30
  "node": ">=20.0.0"
@@ -36,7 +41,7 @@
36
41
  "access": "public"
37
42
  },
38
43
  "scripts": {
39
- "build": "tsc && chmod +x build/index.js",
44
+ "build": "node scripts/bundle.mjs",
40
45
  "start": "node build/index.js",
41
46
  "dev": "node --import tsx src/index.ts",
42
47
  "test": "node --import tsx --test test/**/*.test.ts",
package/build/auth.js DELETED
@@ -1,76 +0,0 @@
1
- // API-key + device-id resolution for the headless CLI.
2
- //
3
- // CI-first: the key comes from the MAIND_API_KEY environment variable. For local
4
- // dev convenience we also fall back to the same on-disk key the mcp-bridge
5
- // persists (~/Library/Application Support/maind/api-key etc.), so a developer who
6
- // already paired the bridge can run `maind context` without re-exporting anything.
7
- //
8
- // We deliberately do NOT run a device-authorization flow here. A CI runner has no
9
- // browser and no stable device, so an interactive flow would just hang. The
10
- // intended key for CI is a device-unbound "ci"-kind key minted in the dashboard
11
- // (read-scoped). Until that key class ships, a free-tier / pre-cutoff key works
12
- // because those are not device-bound either.
13
- //
14
- // The device-id is sent ONLY when an existing device-id file is found on disk
15
- // (i.e. this machine already paired the bridge). In CI no such file exists, so the
16
- // header is omitted and the server treats the request as device-less.
17
- import { existsSync, readFileSync } from "node:fs";
18
- import { homedir, platform } from "node:os";
19
- import { join } from "node:path";
20
- /** XDG-style config directory for maind — must match apps/mcp-bridge/src/device-id.ts. */
21
- function configDir() {
22
- const home = homedir();
23
- const env = process.env;
24
- if (platform() === "darwin") {
25
- return join(home, "Library", "Application Support", "maind");
26
- }
27
- if (platform() === "win32") {
28
- const appdata = env.APPDATA && env.APPDATA.length > 0 ? env.APPDATA : join(home, "AppData", "Roaming");
29
- return join(appdata, "maind");
30
- }
31
- const xdg = env.XDG_CONFIG_HOME && env.XDG_CONFIG_HOME.length > 0
32
- ? env.XDG_CONFIG_HOME
33
- : join(home, ".config");
34
- return join(xdg, "maind");
35
- }
36
- function readFileTrimmed(path) {
37
- if (!existsSync(path))
38
- return null;
39
- try {
40
- const raw = readFileSync(path, "utf8").trim();
41
- return raw.length > 0 ? raw : null;
42
- }
43
- catch {
44
- return null;
45
- }
46
- }
47
- export class MissingApiKeyError extends Error {
48
- constructor() {
49
- super("No API key found. Set MAIND_API_KEY (a read-scoped CI key from https://maind.dev/keys) " +
50
- "or pair the maind bridge on this machine first.");
51
- this.name = "MissingApiKeyError";
52
- }
53
- }
54
- /**
55
- * Resolves the API key (env-first, then the bridge's on-disk key) and an optional
56
- * device-id. Throws MissingApiKeyError when neither source yields a key.
57
- */
58
- export function resolveAuth() {
59
- const fromEnv = process.env.MAIND_API_KEY?.trim();
60
- const apiKey = fromEnv && fromEnv.length > 0 ? fromEnv : readFileTrimmed(join(configDir(), "api-key"));
61
- if (!apiKey)
62
- throw new MissingApiKeyError();
63
- const deviceId = readFileTrimmed(join(configDir(), "device-id"));
64
- return { apiKey, deviceId, keyPrefix: keyPrefixOf(apiKey) };
65
- }
66
- /**
67
- * Extracts the non-secret identifying prefix from a maind key (`mnd_<8hex>_<secret>`).
68
- * Returns the `mnd_<8hex>` portion, or a coarse first-12-chars fallback for other shapes.
69
- */
70
- export function keyPrefixOf(apiKey) {
71
- const m = /^(mnd_[0-9a-f]{8})_/i.exec(apiKey);
72
- if (m)
73
- return m[1];
74
- return apiKey.slice(0, 12);
75
- }
76
- //# sourceMappingURL=auth.js.map
package/build/auth.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -1,162 +0,0 @@
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
- import { gatherGitState } from "./git.js";
14
- const DEFAULT_REPORT_URL = "https://app.maind.dev/api/ci/report";
15
- const PROJECT_KEY_RE = /^[a-f0-9]{64}$/;
16
- export function parseCiReportArgs(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
- lessonPath: get("--lesson") ?? null,
25
- rationale: get("--rationale") ?? null,
26
- failureType: get("--failure-type") ?? null,
27
- signature: get("--signature") ?? null,
28
- summary: get("--summary") ?? null,
29
- provider: get("--provider") ?? "github-actions",
30
- logsPath: get("--logs") ?? null,
31
- remediation: get("--remediation") ?? null,
32
- reportUrl: get("--report-url") ?? process.env.MAIND_REPORT_URL ?? DEFAULT_REPORT_URL,
33
- projectKey: get("--project-key") ?? null,
34
- };
35
- }
36
- /** Collects CI run metadata from the runner environment (GitHub Actions today). */
37
- function ciEnv() {
38
- const env = process.env;
39
- const runId = env.GITHUB_RUN_ID;
40
- const repo = env.GITHUB_REPOSITORY;
41
- const server = env.GITHUB_SERVER_URL ?? "https://github.com";
42
- return {
43
- workflow_name: env.GITHUB_WORKFLOW || undefined,
44
- run_id: runId || undefined,
45
- run_url: runId && repo ? `${server}/${repo}/actions/runs/${runId}` : undefined,
46
- };
47
- }
48
- function sha256(s) {
49
- return createHash("sha256").update(s, "utf8").digest("hex");
50
- }
51
- /** Runs the report. Always returns 0 (fail-open). */
52
- export async function runCiReport(opts) {
53
- try {
54
- if (!opts.lessonPath) {
55
- warn("missing --lesson <path-to-authored-lesson.md>; nothing to report.");
56
- return 0;
57
- }
58
- if (!opts.rationale) {
59
- warn("missing --rationale; the agent should explain why this is a lesson.");
60
- return 0;
61
- }
62
- if (!opts.failureType) {
63
- warn("missing --failure-type (e.g. tsc-error, test-failure).");
64
- return 0;
65
- }
66
- const lesson = readFileSync(opts.lessonPath, "utf8");
67
- if (lesson.trim().length < 50) {
68
- warn("authored lesson is too short — skipping report.");
69
- return 0;
70
- }
71
- const env = ciEnv();
72
- const runId = env.run_id ?? "local";
73
- // Stable signature: explicit flag wins; else derive from failure-type + a
74
- // hash of the lesson so the same recurring failure dedups server-side.
75
- const signature = opts.signature ?? `${opts.failureType}:${sha256(opts.failureType + lesson).slice(0, 16)}`;
76
- const provenance = {
77
- ci_provider: opts.provider,
78
- run_id: runId,
79
- failure_type: opts.failureType,
80
- failure_signature: signature,
81
- draft_rationale: opts.rationale,
82
- };
83
- if (env.workflow_name)
84
- provenance.workflow_name = env.workflow_name;
85
- if (env.run_url)
86
- provenance.run_url = env.run_url;
87
- if (opts.summary)
88
- provenance.failure_summary = opts.summary;
89
- if (opts.remediation)
90
- provenance.remediation_hint = opts.remediation;
91
- if (opts.logsPath) {
92
- try {
93
- provenance.failure_logs = readFileSync(opts.logsPath, "utf8").slice(0, 8000);
94
- }
95
- catch {
96
- // logs are best-effort
97
- }
98
- }
99
- // Repo scope (ADR-212 B4): explicit --project-key wins (validated 64-hex),
100
- // else auto-detect from the repo's git remote. Fail-soft: null → the server
101
- // routes the draft public (fallback), exactly as before B4.
102
- const overrideKey = opts.projectKey?.trim().toLowerCase();
103
- const projectKey = overrideKey && PROJECT_KEY_RE.test(overrideKey)
104
- ? overrideKey
105
- : gatherGitState().projectKey;
106
- const auth = resolveAuth();
107
- const body = JSON.stringify({
108
- lesson,
109
- content_hash: sha256(lesson),
110
- ci_provenance: provenance,
111
- ...(projectKey ? { project_key: projectKey } : {}),
112
- });
113
- let res;
114
- try {
115
- res = await fetch(opts.reportUrl, {
116
- method: "POST",
117
- headers: {
118
- "content-type": "application/json",
119
- authorization: `Bearer ${auth.apiKey}`,
120
- },
121
- body,
122
- });
123
- }
124
- catch (err) {
125
- warn(`network error posting to ${opts.reportUrl}: ${msg(err)}`);
126
- return 0;
127
- }
128
- const text = await res.text().catch(() => "");
129
- if (!res.ok) {
130
- warn(`ingest rejected (HTTP ${res.status}): ${text.slice(0, 300)}`);
131
- return 0;
132
- }
133
- let parsed = {};
134
- try {
135
- parsed = JSON.parse(text);
136
- }
137
- catch {
138
- // non-JSON 200 — treat as success but unparseable
139
- }
140
- const scope = parsed.routing_decision === "org_private"
141
- ? parsed.repo_scoped
142
- ? " [org-private, repo-scoped]"
143
- : " [org-private]"
144
- : "";
145
- process.stderr.write(`maind ci-report: ${parsed.deduplicated ? "deduplicated" : "filed"} draft ${parsed.draft_id ?? "?"}${scope}` +
146
- (parsed.review_url ? ` → ${parsed.review_url}` : "") +
147
- "\n");
148
- return 0;
149
- }
150
- catch (err) {
151
- const reason = err instanceof MissingApiKeyError ? err.message : msg(err);
152
- warn(`report failed, continuing: ${reason}`);
153
- return 0;
154
- }
155
- }
156
- function msg(err) {
157
- return err instanceof Error ? err.message : String(err);
158
- }
159
- function warn(line) {
160
- process.stderr.write(`maind ci-report: ${line}\n`);
161
- }
162
- //# sourceMappingURL=ci-report.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ci-report.js","sourceRoot":"","sources":["../src/ci-report.ts"],"names":[],"mappings":"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"}
@@ -1,145 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"ci-result.js","sourceRoot":"","sources":["../src/ci-result.ts"],"names":[],"mappings":"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"}