getadvantage 0.1.0 → 0.3.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.
package/checks-runner.mjs CHANGED
@@ -1,136 +1,136 @@
1
- // Ship-Safe — runs the full check suite and renders the per-check + overall
2
- // verdict. Shared by both `ship-safe check` and `ship-safe deploy` so the gate
3
- // is identical in both paths.
4
-
5
- import { c, GLYPH, printResult, section } from "./util.mjs";
6
- import {
7
- checkDirtyTree,
8
- checkSecrets,
9
- checkTypecheck,
10
- checkBuild,
11
- checkSchemaBump,
12
- } from "./checks.mjs";
13
- import {
14
- overviewApiSurface,
15
- overviewIntegrations,
16
- overviewSchedules,
17
- } from "./overviews.mjs";
18
- import { briefStaleness } from "./brief.mjs";
19
-
20
- /**
21
- * Run every check and print a clean summary.
22
- * @param {object} o
23
- * @param {string} o.cwd repo root
24
- * @param {boolean} o.runBuild also run a full `npm run build` (slower)
25
- * @param {string} [o.baseRef] merge-base ref for the schema diff (default main)
26
- * @param {boolean} [o.overview] run the v1.1 read-only overview scanners
27
- * (API surface · integrations · schedules).
28
- * Defaults to ON — they're fast, read-only maps.
29
- * @param {boolean} [o.briefCheck] emit a NON-BLOCKING staleness warning if the
30
- * PROJECT BRAIN (PROJECT-BRIEF.md) is missing or
31
- * out of date. Defaults to ON. Never a fail.
32
- * @returns {Promise<{ exitCode: number, results: any[] }>} exitCode 0=GO, 1=NO-GO
33
- */
34
- export async function runChecks(o) {
35
- const cwd = o.cwd;
36
- const results = [];
37
-
38
- section("Checks");
39
-
40
- // a. Dirty-tree guard
41
- results.push(safe(() => checkDirtyTree(cwd), "Dirty-tree guard"));
42
- printResult(results[results.length - 1]);
43
-
44
- // b. Secret scan
45
- results.push(safe(() => checkSecrets(cwd), "Secret scan"));
46
- printResult(results[results.length - 1]);
47
-
48
- // c. Typecheck (always) + optional full build
49
- results.push(safe(() => checkTypecheck(cwd), "Typecheck (tsc --noEmit)"));
50
- printResult(results[results.length - 1]);
51
- if (o.runBuild) {
52
- results.push(safe(() => checkBuild(cwd), "Production build (npm run build)"));
53
- printResult(results[results.length - 1]);
54
- }
55
-
56
- // d. Schema-bump check
57
- results.push(safe(() => checkSchemaBump(cwd, o.baseRef || "main"), "Schema-bump check"));
58
- printResult(results[results.length - 1]);
59
-
60
- // ---- v1.1 OVERVIEW SCANNERS (read-only maps) ----------------------------
61
- // Default-on: three fast, read-only repo scans that give the builder a map of
62
- // what their app actually has. They emit pass/warn only (never a blocking
63
- // fail) — a surprising map is informational, the v1 safety checks own NO-GO.
64
- // Disable with `--no-overview`.
65
- const runOverview = o.overview !== false;
66
- if (runOverview) {
67
- section("Overview — what your app has (read-only)");
68
-
69
- results.push(safe(() => overviewApiSurface(cwd), "API surface map"));
70
- printResult(results[results.length - 1]);
71
-
72
- results.push(safe(() => overviewIntegrations(cwd), "Agents & integrations map"));
73
- printResult(results[results.length - 1]);
74
-
75
- results.push(safe(() => overviewSchedules(cwd), "Schedules & jobs map"));
76
- printResult(results[results.length - 1]);
77
- }
78
-
79
- // ---- PROJECT BRAIN staleness (non-blocking) -----------------------------
80
- // Warn (never fail) if the repo-resident project brief is missing or stale,
81
- // so the portable context any model/tool reads on start doesn't silently rot.
82
- if (o.briefCheck !== false) {
83
- results.push(
84
- safe(() => {
85
- const s = briefStaleness(cwd);
86
- if (s.status === "ok") {
87
- return { status: "pass", label: "Project brief", detail: s.reason, extra: [] };
88
- }
89
- return {
90
- status: "warn",
91
- label: "Project brief",
92
- detail: s.reason,
93
- extra: ["project brief is stale, run `ship-safe brief` to refresh."],
94
- };
95
- }, "Project brief"),
96
- );
97
- printResult(results[results.length - 1]);
98
- }
99
-
100
- // ---- Overall verdict ----------------------------------------------------
101
- const fails = results.filter((r) => r.status === "fail").length;
102
- const warns = results.filter((r) => r.status === "warn").length;
103
- const passes = results.filter((r) => r.status === "pass").length;
104
-
105
- section("Verdict");
106
- console.log(` ${GLYPH.pass} ${passes} ${GLYPH.warn} ${warns} ${GLYPH.fail} ${fails}`);
107
-
108
- if (fails > 0) {
109
- console.log(
110
- "\n" + c.red(c.bold(" NO-GO")) + c.red(` — ${fails} blocking issue(s). Do not ship until these are clear.`),
111
- );
112
- return { exitCode: 1, results };
113
- }
114
- if (warns > 0) {
115
- console.log(
116
- "\n" + c.green(c.bold(" GO")) + c.yellow(` — with ${warns} warning(s) to eyeball first.`),
117
- );
118
- return { exitCode: 0, results };
119
- }
120
- console.log("\n" + c.green(c.bold(" GO")) + c.green(" — all checks clear. Safe to ship."));
121
- return { exitCode: 0, results };
122
- }
123
-
124
- /** Never let one check throwing crash the whole gate — surface it as a fail. */
125
- function safe(fn, label) {
126
- try {
127
- return fn();
128
- } catch (e) {
129
- return {
130
- status: "fail",
131
- label,
132
- detail: `Check errored: ${e.message || e}`,
133
- extra: [],
134
- };
135
- }
136
- }
1
+ // Ship-Safe — runs the full check suite and renders the per-check + overall
2
+ // verdict. Shared by both `ship-safe check` and `ship-safe deploy` so the gate
3
+ // is identical in both paths.
4
+
5
+ import { c, GLYPH, printResult, section } from "./util.mjs";
6
+ import {
7
+ checkDirtyTree,
8
+ checkSecrets,
9
+ checkTypecheck,
10
+ checkBuild,
11
+ checkSchemaBump,
12
+ } from "./checks.mjs";
13
+ import {
14
+ overviewApiSurface,
15
+ overviewIntegrations,
16
+ overviewSchedules,
17
+ } from "./overviews.mjs";
18
+ import { briefStaleness } from "./brief.mjs";
19
+
20
+ /**
21
+ * Run every check and print a clean summary.
22
+ * @param {object} o
23
+ * @param {string} o.cwd repo root
24
+ * @param {boolean} o.runBuild also run a full `npm run build` (slower)
25
+ * @param {string} [o.baseRef] merge-base ref for the schema diff (default main)
26
+ * @param {boolean} [o.overview] run the v1.1 read-only overview scanners
27
+ * (API surface · integrations · schedules).
28
+ * Defaults to ON — they're fast, read-only maps.
29
+ * @param {boolean} [o.briefCheck] emit a NON-BLOCKING staleness warning if the
30
+ * PROJECT BRAIN (PROJECT-BRIEF.md) is missing or
31
+ * out of date. Defaults to ON. Never a fail.
32
+ * @returns {Promise<{ exitCode: number, results: any[] }>} exitCode 0=GO, 1=NO-GO
33
+ */
34
+ export async function runChecks(o) {
35
+ const cwd = o.cwd;
36
+ const results = [];
37
+
38
+ section("Checks");
39
+
40
+ // a. Dirty-tree guard
41
+ results.push(safe(() => checkDirtyTree(cwd), "Dirty-tree guard"));
42
+ printResult(results[results.length - 1]);
43
+
44
+ // b. Secret scan
45
+ results.push(safe(() => checkSecrets(cwd), "Secret scan"));
46
+ printResult(results[results.length - 1]);
47
+
48
+ // c. Typecheck (always) + optional full build
49
+ results.push(safe(() => checkTypecheck(cwd), "Typecheck (tsc --noEmit)"));
50
+ printResult(results[results.length - 1]);
51
+ if (o.runBuild) {
52
+ results.push(safe(() => checkBuild(cwd), "Production build (npm run build)"));
53
+ printResult(results[results.length - 1]);
54
+ }
55
+
56
+ // d. Schema-bump check
57
+ results.push(safe(() => checkSchemaBump(cwd, o.baseRef || "main"), "Schema-bump check"));
58
+ printResult(results[results.length - 1]);
59
+
60
+ // ---- v1.1 OVERVIEW SCANNERS (read-only maps) ----------------------------
61
+ // Default-on: three fast, read-only repo scans that give the builder a map of
62
+ // what their app actually has. They emit pass/warn only (never a blocking
63
+ // fail) — a surprising map is informational, the v1 safety checks own NO-GO.
64
+ // Disable with `--no-overview`.
65
+ const runOverview = o.overview !== false;
66
+ if (runOverview) {
67
+ section("Overview — what your app has (read-only)");
68
+
69
+ results.push(safe(() => overviewApiSurface(cwd), "API surface map"));
70
+ printResult(results[results.length - 1]);
71
+
72
+ results.push(safe(() => overviewIntegrations(cwd), "Agents & integrations map"));
73
+ printResult(results[results.length - 1]);
74
+
75
+ results.push(safe(() => overviewSchedules(cwd), "Schedules & jobs map"));
76
+ printResult(results[results.length - 1]);
77
+ }
78
+
79
+ // ---- PROJECT BRAIN staleness (non-blocking) -----------------------------
80
+ // Warn (never fail) if the repo-resident project brief is missing or stale,
81
+ // so the portable context any model/tool reads on start doesn't silently rot.
82
+ if (o.briefCheck !== false) {
83
+ results.push(
84
+ safe(() => {
85
+ const s = briefStaleness(cwd);
86
+ if (s.status === "ok") {
87
+ return { status: "pass", label: "Project brief", detail: s.reason, extra: [] };
88
+ }
89
+ return {
90
+ status: "warn",
91
+ label: "Project brief",
92
+ detail: s.reason,
93
+ extra: ["project brief is stale, run `ship-safe brief` to refresh."],
94
+ };
95
+ }, "Project brief"),
96
+ );
97
+ printResult(results[results.length - 1]);
98
+ }
99
+
100
+ // ---- Overall verdict ----------------------------------------------------
101
+ const fails = results.filter((r) => r.status === "fail").length;
102
+ const warns = results.filter((r) => r.status === "warn").length;
103
+ const passes = results.filter((r) => r.status === "pass").length;
104
+
105
+ section("Verdict");
106
+ console.log(` ${GLYPH.pass} ${passes} ${GLYPH.warn} ${warns} ${GLYPH.fail} ${fails}`);
107
+
108
+ if (fails > 0) {
109
+ console.log(
110
+ "\n" + c.red(c.bold(" NO-GO")) + c.red(` — ${fails} blocking issue(s). Do not ship until these are clear.`),
111
+ );
112
+ return { exitCode: 1, results };
113
+ }
114
+ if (warns > 0) {
115
+ console.log(
116
+ "\n" + c.green(c.bold(" GO")) + c.yellow(` — with ${warns} warning(s) to eyeball first.`),
117
+ );
118
+ return { exitCode: 0, results };
119
+ }
120
+ console.log("\n" + c.green(c.bold(" GO")) + c.green(" — all checks clear. Safe to ship."));
121
+ return { exitCode: 0, results };
122
+ }
123
+
124
+ /** Never let one check throwing crash the whole gate — surface it as a fail. */
125
+ function safe(fn, label) {
126
+ try {
127
+ return fn();
128
+ } catch (e) {
129
+ return {
130
+ status: "fail",
131
+ label,
132
+ detail: `Check errored: ${e.message || e}`,
133
+ extra: [],
134
+ };
135
+ }
136
+ }