@opvs-ai/cli 0.13.3 โ†’ 0.15.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,54 @@
1
+ /**
2
+ * Terminal rendering for the board / project health reports (ASP-15 / ASP-16).
3
+ *
4
+ * ๐Ÿ”ด The one rule: NOT_CHECKED must never read as PASS.
5
+ *
6
+ * The server's report has a three-value verdict (`healthy | incomplete |
7
+ * not_healthy`) and a per-check level where `not_checked` is distinct from
8
+ * `PASS` โ€” a check whose threshold the caller did not supply made no finding
9
+ * either way. A terminal that coloured both green, or printed a tick for both,
10
+ * would tell an operator a board had been audited against limits nobody set.
11
+ * So every line carries its level as a WORD, padded to one width, and colour is
12
+ * never the only signal (it is not used at all โ€” pipes, CI logs and screen
13
+ * readers see the same text a TTY does).
14
+ *
15
+ * The parameter a `not_checked` names is translated to the CLI FLAG that would
16
+ * enable it, because "stale_days" is the API's name and the reader is at a
17
+ * shell prompt.
18
+ */
19
+ export interface HealthCheck {
20
+ check: string;
21
+ level: string;
22
+ category?: string;
23
+ detail?: string;
24
+ parameter?: string;
25
+ items?: string[];
26
+ }
27
+ export interface HealthReport {
28
+ verdict?: string;
29
+ profile?: string | null;
30
+ board_name?: string;
31
+ board_ref?: string | null;
32
+ board_type?: string;
33
+ project_name?: string;
34
+ parameters_not_supplied?: string[];
35
+ counts?: Record<string, number>;
36
+ checks?: HealthCheck[];
37
+ }
38
+ /** API query parameter โ†’ the flag `opvs boards|projects health` spells it as. */
39
+ export declare const HEALTH_PARAM_FLAGS: Record<string, string>;
40
+ export declare function levelWord(level: string): string;
41
+ /** Render a board or project health report as plain text lines. */
42
+ export declare function renderHealthReport(report: HealthReport): string;
43
+ /** The shared threshold flags, as query params. Only flags given become params. */
44
+ export declare function healthParams(opts: Record<string, string | undefined>): Record<string, string>;
45
+ /**
46
+ * Attach the threshold flags to a `health` command.
47
+ *
48
+ * No flag has a default, on purpose: the server refuses to invent a threshold,
49
+ * and a CLI default would invent one on its behalf โ€” the same opinion arriving
50
+ * through a different door (AgentCLI LEARNINGS #31).
51
+ */
52
+ export declare function withHealthOptions<T extends {
53
+ option: (flags: string, desc: string) => T;
54
+ }>(cmd: T): T;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Terminal rendering for the board / project health reports (ASP-15 / ASP-16).
3
+ *
4
+ * ๐Ÿ”ด The one rule: NOT_CHECKED must never read as PASS.
5
+ *
6
+ * The server's report has a three-value verdict (`healthy | incomplete |
7
+ * not_healthy`) and a per-check level where `not_checked` is distinct from
8
+ * `PASS` โ€” a check whose threshold the caller did not supply made no finding
9
+ * either way. A terminal that coloured both green, or printed a tick for both,
10
+ * would tell an operator a board had been audited against limits nobody set.
11
+ * So every line carries its level as a WORD, padded to one width, and colour is
12
+ * never the only signal (it is not used at all โ€” pipes, CI logs and screen
13
+ * readers see the same text a TTY does).
14
+ *
15
+ * The parameter a `not_checked` names is translated to the CLI FLAG that would
16
+ * enable it, because "stale_days" is the API's name and the reader is at a
17
+ * shell prompt.
18
+ */
19
+ /** API query parameter โ†’ the flag `opvs boards|projects health` spells it as. */
20
+ export const HEALTH_PARAM_FLAGS = {
21
+ profile: "--profile",
22
+ preset: "--preset",
23
+ required_column_fields: "--required-column-fields",
24
+ required_task_fields: "--required-task-fields",
25
+ stale_days: "--stale-days",
26
+ column_age_days: "--column-age-days",
27
+ star_fanout: "--star-fanout",
28
+ };
29
+ /** Level โ†’ the word printed. `not_checked` is lower-case on the wire; shout it. */
30
+ const LEVEL_WORD = {
31
+ PASS: "PASS",
32
+ FAIL: "FAIL",
33
+ WARN: "WARN",
34
+ INFO: "INFO",
35
+ not_checked: "NOT CHECKED",
36
+ };
37
+ const VERDICT_LINE = {
38
+ healthy: "HEALTHY โ€” every check ran and none failed",
39
+ incomplete: "INCOMPLETE โ€” not every check ran, so this is NOT a pass",
40
+ not_healthy: "NOT HEALTHY โ€” at least one check failed",
41
+ };
42
+ const WIDTH = Math.max(...Object.values(LEVEL_WORD).map((w) => w.length));
43
+ export function levelWord(level) {
44
+ return LEVEL_WORD[level] ?? level.toUpperCase();
45
+ }
46
+ function flagsFor(parameter) {
47
+ return parameter
48
+ .split(",")
49
+ .map((p) => p.trim())
50
+ .filter(Boolean)
51
+ .map((p) => HEALTH_PARAM_FLAGS[p] ?? p)
52
+ .join(", ");
53
+ }
54
+ /** Render a board or project health report as plain text lines. */
55
+ export function renderHealthReport(report) {
56
+ const lines = [];
57
+ const subject = report.project_name
58
+ ? `Project health โ€” ${report.project_name}`
59
+ : `Board health โ€” ${report.board_name ?? "(unnamed)"}${report.board_ref ? ` (${report.board_ref})` : ""}`;
60
+ lines.push(subject);
61
+ const verdict = report.verdict ?? "unknown";
62
+ lines.push(`Verdict: ${VERDICT_LINE[verdict] ?? verdict.toUpperCase()}`);
63
+ if (report.profile)
64
+ lines.push(`Profile: ${report.profile}`);
65
+ const c = report.counts ?? {};
66
+ lines.push(`Counts: ${c.pass ?? 0} PASS ยท ${c.fail ?? 0} FAIL ยท ${c.warn ?? 0} WARN ยท ${c.info ?? 0} INFO ยท ` +
67
+ `${c.not_checked ?? 0} NOT CHECKED`);
68
+ const missing = report.parameters_not_supplied ?? [];
69
+ if (missing.length) {
70
+ lines.push(`Not supplied (so their checks made no finding): ${flagsFor(missing.join(","))}`);
71
+ }
72
+ lines.push("");
73
+ for (const chk of report.checks ?? []) {
74
+ const word = levelWord(chk.level).padEnd(WIDTH);
75
+ lines.push(` ${word} ${chk.check}${chk.detail ? ` โ€” ${chk.detail}` : ""}`);
76
+ if (chk.level === "not_checked") {
77
+ // A not_checked with no parameter is a DATA gap (e.g. unstamped cards),
78
+ // and no flag fixes it โ€” say so rather than leave an empty hint.
79
+ lines.push(chk.parameter
80
+ ? ` ${"".padEnd(WIDTH)} โ†ณ enable with ${flagsFor(chk.parameter)}`
81
+ : ` ${"".padEnd(WIDTH)} โ†ณ no flag enables this โ€” the data it audits is missing`);
82
+ }
83
+ for (const item of chk.items ?? []) {
84
+ lines.push(` ${"".padEnd(WIDTH)} ยท ${item}`);
85
+ }
86
+ }
87
+ return lines.join("\n");
88
+ }
89
+ /** The shared threshold flags, as query params. Only flags given become params. */
90
+ export function healthParams(opts) {
91
+ const params = {};
92
+ const map = [
93
+ ["profile", "profile"],
94
+ ["preset", "preset"],
95
+ ["requiredColumnFields", "required_column_fields"],
96
+ ["requiredTaskFields", "required_task_fields"],
97
+ ["staleDays", "stale_days"],
98
+ ["columnAgeDays", "column_age_days"],
99
+ ["starFanout", "star_fanout"],
100
+ ];
101
+ for (const [opt, param] of map) {
102
+ const v = opts[opt];
103
+ if (v !== undefined && v !== "")
104
+ params[param] = v;
105
+ }
106
+ return params;
107
+ }
108
+ /**
109
+ * Attach the threshold flags to a `health` command.
110
+ *
111
+ * No flag has a default, on purpose: the server refuses to invent a threshold,
112
+ * and a CLI default would invent one on its behalf โ€” the same opinion arriving
113
+ * through a different door (AgentCLI LEARNINGS #31).
114
+ */
115
+ export function withHealthOptions(cmd) {
116
+ return cmd
117
+ .option("--profile <name>", "Named contract supplying thresholds + field lists: planner-orchestration | factory | crm. Any flag below overrides one value.")
118
+ .option("--preset <preset>", "Column preset the board(s) should match, e.g. factory-full.")
119
+ .option("--required-column-fields <fields>", "Comma-separated column fields that must be non-empty, e.g. description,managed_by_type.")
120
+ .option("--required-task-fields <fields>", "Comma-separated card fields every open card must fill, e.g. description,agent_instructions.")
121
+ .option("--stale-days <n>", "Warn on an open card not updated in N days.")
122
+ .option("--column-age-days <n>", "Warn on an open card in the same column for N days.")
123
+ .option("--star-fanout <n>", "Warn on a prerequisite whose top-layer fan-out exceeds N.")
124
+ .option("--json", "Print the raw JSON report instead of the text rendering.");
125
+ }
126
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/lib/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `set-routing` for boards and projects (ASP-25, plan ยงC / migration 062).
3
+ *
4
+ * The routing chain, highest wins:
5
+ *
6
+ * card pin > board default > project default > box default
7
+ *
8
+ * A board default is consulted only when the card is silent on that axis; a
9
+ * project default only when the card AND the board are silent, and only for a
10
+ * board claimed by exactly ONE active project โ€” a board in two projects
11
+ * resolves no project default at all (`ClaimService`, and the `ambiguous`
12
+ * resolution `opvs boards projects` reports).
13
+ *
14
+ * One helper for both, because the two PATCH bodies are the same four keys and
15
+ * a copy is where the fourth one gets forgotten (the server says the same about
16
+ * its own validator).
17
+ */
18
+ export interface RoutingOpts {
19
+ model?: string;
20
+ provider?: string;
21
+ harness?: string;
22
+ claimableBy?: string;
23
+ }
24
+ /**
25
+ * Build the PATCH body. Only flags given become keys โ€” both routes are
26
+ * `exclude_unset`, so an omitted flag leaves that default alone, and `none`
27
+ * sends `""`, which `_blank_routing_default_clears` normalises to NULL.
28
+ */
29
+ export declare function buildRoutingBody(opts: RoutingOpts): Record<string, string>;
30
+ /**
31
+ * Attach the four routing flags. `scope` is "board" or "project", and the help
32
+ * says which rung of the chain the value lands on.
33
+ *
34
+ * Values are server-side enums (`BuildProvider` / `BuildHarness` /
35
+ * `TaskActorClass`) and are quoted here as examples, not re-validated โ€” a
36
+ * second copy of an enum is a second thing to drift, and a bad value is a 422
37
+ * that names the accepted set.
38
+ */
39
+ export declare function withRoutingOptions<T extends {
40
+ option: (flags: string, desc: string) => T;
41
+ }>(cmd: T, scope: "board" | "project"): T;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * `set-routing` for boards and projects (ASP-25, plan ยงC / migration 062).
3
+ *
4
+ * The routing chain, highest wins:
5
+ *
6
+ * card pin > board default > project default > box default
7
+ *
8
+ * A board default is consulted only when the card is silent on that axis; a
9
+ * project default only when the card AND the board are silent, and only for a
10
+ * board claimed by exactly ONE active project โ€” a board in two projects
11
+ * resolves no project default at all (`ClaimService`, and the `ambiguous`
12
+ * resolution `opvs boards projects` reports).
13
+ *
14
+ * One helper for both, because the two PATCH bodies are the same four keys and
15
+ * a copy is where the fourth one gets forgotten (the server says the same about
16
+ * its own validator).
17
+ */
18
+ /** The CLEAR verb. The server reads a blank string as "no opinion" (062). */
19
+ const CLEAR = "none";
20
+ /**
21
+ * Build the PATCH body. Only flags given become keys โ€” both routes are
22
+ * `exclude_unset`, so an omitted flag leaves that default alone, and `none`
23
+ * sends `""`, which `_blank_routing_default_clears` normalises to NULL.
24
+ */
25
+ export function buildRoutingBody(opts) {
26
+ const body = {};
27
+ const put = (key, raw) => {
28
+ if (raw === undefined)
29
+ return;
30
+ body[key] = raw === CLEAR ? "" : raw;
31
+ };
32
+ put("default_model", opts.model);
33
+ put("default_provider", opts.provider);
34
+ put("default_harness", opts.harness);
35
+ put("default_claimable_by", opts.claimableBy);
36
+ return body;
37
+ }
38
+ /**
39
+ * Attach the four routing flags. `scope` is "board" or "project", and the help
40
+ * says which rung of the chain the value lands on.
41
+ *
42
+ * Values are server-side enums (`BuildProvider` / `BuildHarness` /
43
+ * `TaskActorClass`) and are quoted here as examples, not re-validated โ€” a
44
+ * second copy of an enum is a second thing to drift, and a bad value is a 422
45
+ * that names the accepted set.
46
+ */
47
+ export function withRoutingOptions(cmd, scope) {
48
+ const where = scope === "board"
49
+ ? "for every card on this board that names none itself (card pin > BOARD > project > box)"
50
+ : "for every card on this project's boards when neither the card nor its board names one " +
51
+ "(card pin > board > PROJECT > box) โ€” and to no board claimed by two active projects";
52
+ return cmd
53
+ .option("--model <model>", `Default model, e.g. claude-opus-5. Applies ${where}. Pass 'none' to clear.`)
54
+ .option("--provider <lane>", "Default credential LANE: anthropic-claude-code | openai-codex | gemini-cli (hyphens) โ€” NOT the model vendor. " +
55
+ `Applies ${where}. Pass 'none' to clear.`)
56
+ .option("--harness <executor>", `Default executor: claude_code | openhands | codex (underscores). Applies ${where}. Pass 'none' to clear.`)
57
+ .option("--claimable-by <class>", `Default actor gate: worker | agent | human. Applies ${where}. GATES: cards become invisible to callers of any ` +
58
+ "other class โ€” a claim returns task_id null exactly as an empty board does; only its actor_gated count tells " +
59
+ "them apart. Pass 'none' to clear.");
60
+ }
61
+ //# sourceMappingURL=routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.js","sourceRoot":"","sources":["../../src/lib/routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,6EAA6E;AAC7E,MAAM,KAAK,GAAG,MAAM,CAAC;AASrB;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAiB;IAChD,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,GAAuB,EAAE,EAAE;QACnD,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO;QAC9B,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IACvC,CAAC,CAAC;IACF,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,GAAG,CAAC,sBAAsB,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAM,EACN,KAA0B;IAE1B,MAAM,KAAK,GACT,KAAK,KAAK,OAAO;QACf,CAAC,CAAC,wFAAwF;QAC1F,CAAC,CAAC,wFAAwF;YACxF,qFAAqF,CAAC;IAC5F,OAAO,GAAG;SACP,MAAM,CACL,iBAAiB,EACjB,8CAA8C,KAAK,yBAAyB,CAC7E;SACA,MAAM,CACL,mBAAmB,EACnB,+GAA+G;QAC7G,WAAW,KAAK,yBAAyB,CAC5C;SACA,MAAM,CACL,sBAAsB,EACtB,4EAA4E,KAAK,yBAAyB,CAC3G;SACA,MAAM,CACL,wBAAwB,EACxB,uDAAuD,KAAK,oDAAoD;QAC9G,8GAA8G;QAC9G,mCAAmC,CACtC,CAAC;AACN,CAAC"}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@opvs-ai/cli",
3
- "version": "0.13.3",
3
+ "version": "0.15.0",
4
4
  "description": "OPVS CLI \u2014 Terminal access to AgentBoard + AgentDocs for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "opvs": "dist/index.js"
8
8
  },
9
9
  "scripts": {
10
- "build": "tsc",
10
+ "build": "tsc && node ../../scripts/dist-stale.mjs stamp",
11
11
  "dev": "tsx src/index.ts",
12
12
  "start": "node dist/index.js",
13
13
  "test": "vitest run",