great-cto 3.59.0 → 3.59.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "great-cto",
|
|
3
3
|
"description": "You already have the agent. This is everything around it. great_cto runs Claude Code as a pipeline of 72 specialist agents \u2014 an independent model checks each stage before the next builds on it, spending caps refuse rather than warn, and three decisions stay yours: what gets built, how, and whether it ships.",
|
|
4
|
-
"version": "3.59.
|
|
4
|
+
"version": "3.59.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Alexander Velikiy",
|
|
7
7
|
"url": "https://hashnode.com/@Greatcto"
|
|
@@ -24,8 +24,9 @@ import { fileURLToPath } from 'node:url';
|
|
|
24
24
|
|
|
25
25
|
import { classify } from './change-tier.mjs';
|
|
26
26
|
import { selectJudgeModel } from './judge-model.mjs';
|
|
27
|
-
//
|
|
28
|
-
|
|
27
|
+
// Generated from the canonical CLI policy, but shipped in Git too: marketplace
|
|
28
|
+
// installs do not contain the gitignored CLI build.
|
|
29
|
+
import { effectiveGates } from './gate-policy.mjs';
|
|
29
30
|
|
|
30
31
|
/** Parse archetype + project_size out of a .great_cto/PROJECT.md body. */
|
|
31
32
|
export function parseProject(text) {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Generated by scripts/build-gate-policy.mjs from packages/cli/src/archetypes.ts.
|
|
2
|
+
// Do not edit; regenerate, then run --check. No CLI build is needed at runtime.
|
|
3
|
+
export const GATES_BY_ARCHETYPE = {
|
|
4
|
+
"web-service": ["plan", "qa", "ship"],
|
|
5
|
+
"mobile-app": ["plan", "qa", "ship"],
|
|
6
|
+
"ai-system": ["plan", "cost", "qa", "security", "ship"],
|
|
7
|
+
"agent-product": ["plan", "cost", "qa", "security", "ship"],
|
|
8
|
+
"mlops": ["plan", "cost", "qa", "security", "ship"],
|
|
9
|
+
"data-platform": ["plan", "qa", "ship"],
|
|
10
|
+
"streaming": ["plan", "qa", "ship"],
|
|
11
|
+
"infra": ["plan", "qa", "ship"],
|
|
12
|
+
"library": ["plan", "qa", "ship"],
|
|
13
|
+
"cli-tool": ["plan", "qa", "ship"],
|
|
14
|
+
"commerce": ["plan", "qa", "security", "ship", "compliance"],
|
|
15
|
+
"marketplace": ["plan", "qa", "security", "ship", "compliance"],
|
|
16
|
+
"fintech": ["plan", "qa", "security", "ship", "compliance"],
|
|
17
|
+
"healthcare": ["plan", "qa", "security", "ship", "compliance"],
|
|
18
|
+
"web3": ["plan", "qa", "oracle-review", "security", "ship"],
|
|
19
|
+
"iot-embedded": ["plan", "qa", "security", "ship"],
|
|
20
|
+
"regulated": ["plan", "qa", "security", "ship", "compliance"],
|
|
21
|
+
"devtools": ["plan", "qa", "ship"],
|
|
22
|
+
"browser-extension": ["plan", "qa", "ship"],
|
|
23
|
+
"game": ["plan", "qa", "ship"],
|
|
24
|
+
"cms": ["plan", "qa", "ship"],
|
|
25
|
+
"enterprise-saas": ["plan", "qa", "security", "ship", "compliance"],
|
|
26
|
+
"edtech": ["plan", "qa", "edtech-review", "security", "ship", "compliance"],
|
|
27
|
+
"gov-public": ["plan", "qa", "gov-review", "security", "ship", "compliance"],
|
|
28
|
+
"insurance": ["plan", "qa", "insurance-review", "security", "ship", "compliance"],
|
|
29
|
+
"legal": ["plan", "qa", "upl-review", "security", "ship", "compliance"],
|
|
30
|
+
"defense-govcon": ["plan", "qa", "cmmc-assessment", "security", "ship", "compliance"],
|
|
31
|
+
// Product Builder archetypes (A1–A6) — non-regulated baseline; the single CTO gate
|
|
32
|
+
// emerges at change_tier T1 (effectiveGates → [plan]).
|
|
33
|
+
"vertical-saas": ["plan", "qa", "ship"],
|
|
34
|
+
"booking": ["plan", "qa", "ship"],
|
|
35
|
+
"crm": ["plan", "qa", "ship"],
|
|
36
|
+
"dashboard": ["plan", "qa", "ship"],
|
|
37
|
+
"content-platform": ["plan", "qa", "ship"],
|
|
38
|
+
"marketplace-lite": ["plan", "qa", "ship"],
|
|
39
|
+
"greenfield": ["plan"],
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Returns the subset of gates the pipeline will actually open for a
|
|
43
|
+
* given archetype + project_size. Used by the orchestrator before
|
|
44
|
+
* opening any gate to skip unnecessary human checkpoints on smaller
|
|
45
|
+
* projects (e.g. nano always skips QA).
|
|
46
|
+
*/
|
|
47
|
+
export function gatesFor(archetype, size) {
|
|
48
|
+
const all = GATES_BY_ARCHETYPE[archetype] ?? [];
|
|
49
|
+
if (size === "nano")
|
|
50
|
+
return all.filter((g) => g === "plan");
|
|
51
|
+
if (size === "small")
|
|
52
|
+
return all.filter((g) => g === "plan" || g === "ship");
|
|
53
|
+
if (size === "medium")
|
|
54
|
+
return all;
|
|
55
|
+
// large + enterprise → ensure compliance is included
|
|
56
|
+
return all.includes("compliance") ? all : [...all, "compliance"];
|
|
57
|
+
}
|
|
58
|
+
/** Gates that form the non-negotiable floor for a *regulated* archetype. */
|
|
59
|
+
const FLOOR_GATES = ["security", "compliance", "ship"];
|
|
60
|
+
/**
|
|
61
|
+
* The human gates the pipeline opens for a change, given its archetype, the
|
|
62
|
+
* project size, AND the per-change risk tier. Composes with `gatesFor()`:
|
|
63
|
+
*
|
|
64
|
+
* - T2 (default): the full size baseline, with `ship` guaranteed even if a
|
|
65
|
+
* small project_size had stripped it. An irreversible change always gets a
|
|
66
|
+
* final go/no-go. Nothing is ever removed → fail-safe for an unknown tier.
|
|
67
|
+
* - T1: only `plan` (you review intent) PLUS the regulated floor. The standalone
|
|
68
|
+
* qa/security-as-ceremony is dropped because CI + tests cover a reversible change.
|
|
69
|
+
* - T0: the regulated floor only — for a plain archetype that is the empty set
|
|
70
|
+
* (CI is the gate); for a regulated one, security+compliance+ship still fire.
|
|
71
|
+
*
|
|
72
|
+
* An archetype is "regulated" iff its baseline contains `security` or `compliance`.
|
|
73
|
+
* That is what keeps the downgrade sound: a fintech repo cannot ship an
|
|
74
|
+
* irreversible change unreviewed even when the change is labelled a fix.
|
|
75
|
+
*
|
|
76
|
+
* NOTE: change-specific T2 triggers (a migration, a new write-connector, a prod
|
|
77
|
+
* deploy) are resolved upstream by the classifier, which escalates such a change
|
|
78
|
+
* to T2 before this function sees it. Here we only map an already-decided tier.
|
|
79
|
+
*/
|
|
80
|
+
export function effectiveGates(archetype, size, tier = "T2") {
|
|
81
|
+
const base = gatesFor(archetype, size);
|
|
82
|
+
// T2 (and any unrecognized tier) → full baseline, never downgraded, ship forced.
|
|
83
|
+
if (tier !== "T0" && tier !== "T1") {
|
|
84
|
+
return base.includes("ship") ? base : [...base, "ship"];
|
|
85
|
+
}
|
|
86
|
+
// Regulated archetypes carry a floor that survives every downgrade.
|
|
87
|
+
const isRegulated = base.includes("security") || base.includes("compliance");
|
|
88
|
+
const floor = isRegulated ? base.filter((g) => FLOOR_GATES.includes(g)) : [];
|
|
89
|
+
if (tier === "T1") {
|
|
90
|
+
const keep = new Set(floor);
|
|
91
|
+
if (base.includes("plan"))
|
|
92
|
+
keep.add("plan");
|
|
93
|
+
return base.filter((g) => keep.has(g)); // preserve base order
|
|
94
|
+
}
|
|
95
|
+
// T0 — maintenance.
|
|
96
|
+
return floor;
|
|
97
|
+
}
|
package/package.json
CHANGED
package/postinstall.mjs
CHANGED
|
@@ -138,32 +138,38 @@ function main() {
|
|
|
138
138
|
* - never block. The board takes the better part of a minute to become
|
|
139
139
|
* responsive; the installer does not wait for it. Detached, unref'd, output
|
|
140
140
|
* discarded.
|
|
141
|
-
* - never in CI, and never when asked not to.
|
|
142
|
-
*
|
|
141
|
+
* - never in CI or a Node test runner, and never when asked not to. A test
|
|
142
|
+
* HOME isolates files, NOT ports: a detached board would still claim the
|
|
143
|
+
* user's :3141 and serve fixture projects after the test exits.
|
|
144
|
+
* `GREAT_CTO_NO_BOARD=1` opts out of this specifically.
|
|
143
145
|
* - never twice. `ensure` probes the port first and adopts a board that is
|
|
144
146
|
* already answering, whoever started it.
|
|
145
147
|
*/
|
|
146
|
-
function ensureBoard(
|
|
147
|
-
|
|
148
|
+
export function ensureBoard({ env = process.env, spawnFn = spawn,
|
|
149
|
+
write = (text) => process.stdout.write(text) } = {}) {
|
|
150
|
+
if (env.CI || env.GREAT_CTO_QUIET_POSTINSTALL || env.GREAT_CTO_NO_BOARD || env.NODE_TEST_CONTEXT) return false;
|
|
148
151
|
try {
|
|
149
152
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
150
153
|
const entry = join(here, 'index.mjs');
|
|
151
|
-
if (!existsSync(entry)) return;
|
|
154
|
+
if (!existsSync(entry)) return false;
|
|
152
155
|
|
|
153
|
-
const child =
|
|
156
|
+
const child = spawnFn(process.execPath, [entry, 'board', 'ensure'], {
|
|
154
157
|
detached: true,
|
|
155
158
|
stdio: 'ignore',
|
|
159
|
+
env,
|
|
156
160
|
});
|
|
157
161
|
child.unref();
|
|
158
|
-
|
|
162
|
+
write(' great-cto: starting the board — http://localhost:3141\n');
|
|
163
|
+
return true;
|
|
159
164
|
} catch (e) {
|
|
160
165
|
// Never fail the install — but never fail SILENTLY either. The first version
|
|
161
166
|
// of this function referenced an import that was not there; the catch ate the
|
|
162
167
|
// ReferenceError and the hook printed nothing, so the board simply did not
|
|
163
168
|
// start and nothing said why. A swallowed error is the defect this project
|
|
164
169
|
// spends most of its checks on.
|
|
165
|
-
|
|
166
|
-
|
|
170
|
+
write(` great-cto: could not start the board — ${e?.message || e}\n`);
|
|
171
|
+
write(' Start it yourself with: great-cto board\n');
|
|
172
|
+
return false;
|
|
167
173
|
}
|
|
168
174
|
}
|
|
169
175
|
|