great-cto 3.72.0 → 3.74.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/board/.claude-plugin/plugin.json +1 -1
- package/board/agents/accounting-reviewer.md +2 -2
- package/board/agents/adtech-privacy-reviewer.md +3 -3
- package/board/agents/ai-eval-engineer.md +3 -3
- package/board/agents/ai-prompt-architect.md +3 -3
- package/board/agents/ai-security-reviewer.md +2 -2
- package/board/agents/api-platform-reviewer.md +2 -2
- package/board/agents/app-scaffolder.md +3 -3
- package/board/agents/architect.md +8 -8
- package/board/agents/auth-engineer.md +4 -4
- package/board/agents/ci-resolver.md +5 -5
- package/board/agents/cli-reviewer.md +2 -2
- package/board/agents/cmmc-reviewer.md +2 -2
- package/board/agents/cms-reviewer.md +2 -2
- package/board/agents/code-reviewer.md +4 -4
- package/board/agents/connector-builder.md +5 -5
- package/board/agents/continuous-learner.md +3 -3
- package/board/agents/coordinator.md +4 -4
- package/board/agents/data-platform-reviewer.md +2 -2
- package/board/agents/db-migration-reviewer.md +2 -2
- package/board/agents/decision-scorer.md +3 -3
- package/board/agents/design-advisor.md +3 -3
- package/board/agents/devops.md +12 -12
- package/board/agents/devtools-reviewer.md +2 -2
- package/board/agents/dpdpa-reviewer.md +2 -2
- package/board/agents/e2e-test-engineer.md +1 -1
- package/board/agents/edtech-reviewer.md +3 -3
- package/board/agents/enterprise-saas-reviewer.md +2 -2
- package/board/agents/firmware-reviewer.md +2 -2
- package/board/agents/game-reviewer.md +2 -2
- package/board/agents/gdpr-reviewer.md +3 -3
- package/board/agents/geo-routing-engineer.md +5 -5
- package/board/agents/gov-reviewer.md +2 -2
- package/board/agents/growth-engineer.md +3 -3
- package/board/agents/healthcare-reviewer.md +3 -3
- package/board/agents/hr-ai-reviewer.md +3 -3
- package/board/agents/infra-provisioner.md +3 -3
- package/board/agents/infra-reviewer.md +2 -2
- package/board/agents/insurance-reviewer.md +2 -2
- package/board/agents/integrations-engineer.md +5 -5
- package/board/agents/knowledge-extractor.md +2 -2
- package/board/agents/l3-support.md +8 -8
- package/board/agents/legal-reviewer.md +3 -3
- package/board/agents/library-reviewer.md +2 -2
- package/board/agents/marketplace-reviewer.md +2 -2
- package/board/agents/mcp-server-reviewer.md +2 -2
- package/board/agents/media-pipeline-engineer.md +5 -5
- package/board/agents/migration-import-engineer.md +5 -5
- package/board/agents/mlops-reviewer.md +2 -2
- package/board/agents/mobile-app-builder.md +6 -6
- package/board/agents/mobile-store-reviewer.md +2 -2
- package/board/agents/msp-reviewer.md +2 -2
- package/board/agents/oracle-reviewer.md +2 -2
- package/board/agents/pci-reviewer.md +2 -2
- package/board/agents/performance-engineer.md +3 -3
- package/board/agents/pm.md +6 -6
- package/board/agents/procurement-reviewer.md +2 -2
- package/board/agents/product-owner.md +5 -5
- package/board/agents/project-auditor.md +6 -6
- package/board/agents/qa-engineer.md +11 -11
- package/board/agents/quant-researcher.md +2 -2
- package/board/agents/rcm-reviewer.md +3 -3
- package/board/agents/regulated-reviewer.md +2 -2
- package/board/agents/security-officer.md +8 -8
- package/board/agents/senior-dev.md +7 -7
- package/board/agents/smart-contract-auditor.md +4 -4
- package/board/agents/streaming-reviewer.md +2 -2
- package/board/agents/subscription-billing-engineer.md +5 -5
- package/board/agents/tax-reviewer.md +3 -3
- package/board/agents/us-ai-reviewer.md +2 -2
- package/board/agents/us-privacy-reviewer.md +3 -3
- package/board/agents/voice-ai-reviewer.md +3 -3
- package/board/agents/web-store-reviewer.md +2 -2
- package/board/scripts/codex-pipeline.mjs +42 -7
- package/board/scripts/lib/agent-events.mjs +5 -1
- package/board/scripts/lib/cost-meter.mjs +34 -2
- package/board/scripts/lib/cross-model-review.mjs +107 -9
- package/board/scripts/lib/gate-tier.mjs +1 -1
- package/board/scripts/lib/host-graph-bindings.mjs +15 -3
- package/board/scripts/lib/host-graph-events.mjs +23 -4
- package/board/scripts/lib/host-graph-runtime.mjs +10 -3
- package/board/scripts/lib/kimi-review-profile.mjs +551 -0
- package/board/scripts/lib/kimi-review-store.mjs +469 -0
- package/board/scripts/lib/system-map.mjs +4 -2
- package/board/scripts/lib/work-publication.mjs +10 -9
- package/board/scripts/skill-lint.mjs +3 -3
- package/dist/main.js +82 -16
- package/dist/release-activation.mjs +3 -1
- package/dist/telemetry.js +2 -2
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -66,6 +66,8 @@ function parseArgs(argv) {
|
|
|
66
66
|
version: null,
|
|
67
67
|
useLlm: false,
|
|
68
68
|
noLlm: false,
|
|
69
|
+
noTelemetry: false,
|
|
70
|
+
rootArgv: argv,
|
|
69
71
|
host: null,
|
|
70
72
|
upgradeSelf: false,
|
|
71
73
|
purgeData: false,
|
|
@@ -73,8 +75,18 @@ function parseArgs(argv) {
|
|
|
73
75
|
positional: [],
|
|
74
76
|
};
|
|
75
77
|
const rest = [];
|
|
78
|
+
const telemetryFlagIndices = new Set();
|
|
79
|
+
const webhookValueOptions = new Set(["--secret", "--url", "--format", "--triggers", "--events", "--routing-key"]);
|
|
76
80
|
for (let i = 0; i < argv.length; i++) {
|
|
77
81
|
const a = argv[i];
|
|
82
|
+
// Webhook values may themselves look like options. Consume each owned
|
|
83
|
+
// value once so it cannot claim a later standalone root refusal as data.
|
|
84
|
+
if (args.command === "webhook" && webhookValueOptions.has(a)) {
|
|
85
|
+
rest.push(a);
|
|
86
|
+
if (i + 1 < argv.length)
|
|
87
|
+
rest.push(argv[++i]);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
78
90
|
if (a === "-h" || a === "--help")
|
|
79
91
|
args.command = "help";
|
|
80
92
|
else if (a === "-v" || a === "--version")
|
|
@@ -99,6 +111,10 @@ function parseArgs(argv) {
|
|
|
99
111
|
args.useLlm = true;
|
|
100
112
|
else if (a === "--no-llm")
|
|
101
113
|
args.noLlm = true;
|
|
114
|
+
else if (a === "--no-telemetry") {
|
|
115
|
+
args.noTelemetry = true;
|
|
116
|
+
telemetryFlagIndices.add(i);
|
|
117
|
+
}
|
|
102
118
|
else if (a === "--host") {
|
|
103
119
|
const v = argv[++i] ?? "";
|
|
104
120
|
args.hostInput = v;
|
|
@@ -121,8 +137,6 @@ function parseArgs(argv) {
|
|
|
121
137
|
args.command = "console";
|
|
122
138
|
else if (a === "telemetry")
|
|
123
139
|
args.command = "telemetry";
|
|
124
|
-
else if (a === "--no-telemetry")
|
|
125
|
-
continue;
|
|
126
140
|
else if (a === "distribution") {
|
|
127
141
|
args.command = "distribution";
|
|
128
142
|
args.taskArgs = argv.slice(i + 1);
|
|
@@ -200,7 +214,7 @@ function parseArgs(argv) {
|
|
|
200
214
|
args._fromInstall = true;
|
|
201
215
|
}
|
|
202
216
|
}
|
|
203
|
-
else if (!a.startsWith("-") && args.command === "init" && i === 0) {
|
|
217
|
+
else if (!a.startsWith("-") && args.command === "init" && i - telemetryFlagIndices.size === 0) {
|
|
204
218
|
// First positional that isn't a recognised subcommand → unknown
|
|
205
219
|
args.command = "unknown";
|
|
206
220
|
args.unknownToken = a;
|
|
@@ -215,6 +229,9 @@ function parseArgs(argv) {
|
|
|
215
229
|
}
|
|
216
230
|
args.dir = resolve(args.dir);
|
|
217
231
|
args.positional = rest;
|
|
232
|
+
// A consumed option value or an early-break tail belongs to its original
|
|
233
|
+
// parser. Filtering by value would erase literal data in either case.
|
|
234
|
+
args.rootArgv = argv.filter((_, i) => !telemetryFlagIndices.has(i));
|
|
218
235
|
return args;
|
|
219
236
|
}
|
|
220
237
|
async function runRegister(args) {
|
|
@@ -870,6 +887,9 @@ ${bold("Options:")}
|
|
|
870
887
|
even when heuristic confidence is high
|
|
871
888
|
--no-llm Skip LLM suggestion (run heuristic only)
|
|
872
889
|
Or set ${cyan("GREATCTO_NO_LLM=1")}
|
|
890
|
+
--no-telemetry Disable telemetry for this invocation, even if opted in
|
|
891
|
+
Put before task/worker/codex-host/run/status/resume/statusline
|
|
892
|
+
Does not disable update checks or command network access
|
|
873
893
|
-h, --help Show this help
|
|
874
894
|
-v, --version Show great-cto CLI version
|
|
875
895
|
|
|
@@ -1249,10 +1269,12 @@ async function runInit(args) {
|
|
|
1249
1269
|
// ── 6. install pre-push git hook ─────────────────────────
|
|
1250
1270
|
installPrePushHook(args.dir);
|
|
1251
1271
|
// ── 7. opt-IN telemetry prompt (default OFF) ─────────────
|
|
1252
|
-
|
|
1272
|
+
if (!args.noTelemetry) {
|
|
1273
|
+
await promoteTelemetryOptIn({ archetype: String(archetype), cliVersion: getCliVersion(), yes: args.yes });
|
|
1274
|
+
}
|
|
1253
1275
|
// If already enabled (prior opt-in or env var), count this (re)install toward MAU.
|
|
1254
|
-
if (isTelemetryEnabled()) {
|
|
1255
|
-
await sendInstallPing({ cliVersion: getCliVersion(), archetype: String(archetype), consent: true })
|
|
1276
|
+
if (isTelemetryEnabled(args.noTelemetry)) {
|
|
1277
|
+
await sendInstallPing({ cliVersion: getCliVersion(), archetype: String(archetype), consent: true, noTelemetry: args.noTelemetry })
|
|
1256
1278
|
.catch(() => { });
|
|
1257
1279
|
}
|
|
1258
1280
|
// ── done ─────────────────────────────────────────────────
|
|
@@ -1445,9 +1467,49 @@ async function reportCodexUpgrade() {
|
|
|
1445
1467
|
}
|
|
1446
1468
|
return 0;
|
|
1447
1469
|
}
|
|
1470
|
+
// A successful write() may still have queued pipe bytes. Complete an ordered
|
|
1471
|
+
// empty write before forced exit, without keeping a broken consumer alive.
|
|
1472
|
+
function drainOutput(stream) {
|
|
1473
|
+
if (stream.destroyed || stream.closed || stream.writableFinished)
|
|
1474
|
+
return Promise.resolve(true);
|
|
1475
|
+
return new Promise((resolve) => {
|
|
1476
|
+
let settled = false;
|
|
1477
|
+
const finish = (complete) => {
|
|
1478
|
+
if (settled)
|
|
1479
|
+
return;
|
|
1480
|
+
settled = true;
|
|
1481
|
+
clearTimeout(timer);
|
|
1482
|
+
stream.off("error", completed);
|
|
1483
|
+
stream.off("close", completed);
|
|
1484
|
+
stream.off("finish", completed);
|
|
1485
|
+
resolve(complete);
|
|
1486
|
+
};
|
|
1487
|
+
const completed = () => finish(true);
|
|
1488
|
+
const timer = setTimeout(() => finish(false), 1000);
|
|
1489
|
+
timer.unref();
|
|
1490
|
+
stream.once("error", completed);
|
|
1491
|
+
stream.once("close", completed);
|
|
1492
|
+
stream.once("finish", completed);
|
|
1493
|
+
if (!stream.writableEnded) {
|
|
1494
|
+
try {
|
|
1495
|
+
stream.write("", (error) => {
|
|
1496
|
+
// Node emits the write error after its callback; leave the listener
|
|
1497
|
+
// in place for that event before cleaning up a callback-only failure.
|
|
1498
|
+
if (error)
|
|
1499
|
+
queueMicrotask(completed);
|
|
1500
|
+
else
|
|
1501
|
+
completed();
|
|
1502
|
+
});
|
|
1503
|
+
}
|
|
1504
|
+
catch {
|
|
1505
|
+
completed();
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1448
1510
|
async function main() {
|
|
1449
|
-
const
|
|
1450
|
-
const
|
|
1511
|
+
const args = parseArgs(process.argv.slice(2));
|
|
1512
|
+
const rawArgv = args.rootArgv;
|
|
1451
1513
|
// Anonymous, opt-IN usage telemetry (default OFF — see docs/PRIVACY.md). `finish`
|
|
1452
1514
|
// is the single exit funnel: it fires one fire-and-forget event (command + node + os
|
|
1453
1515
|
// + exit_code + duration, no PII) only when the user has opted in, then exits.
|
|
@@ -1458,13 +1520,13 @@ async function main() {
|
|
|
1458
1520
|
// widen types at every call site.
|
|
1459
1521
|
const finish = async (code) => {
|
|
1460
1522
|
try {
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1523
|
+
await sendUsagePing({
|
|
1524
|
+
cliVersion: getCliVersion(),
|
|
1525
|
+
subcommand: args.command,
|
|
1526
|
+
exitCode: code,
|
|
1527
|
+
durationMs: Date.now() - __tStart,
|
|
1528
|
+
noTelemetry: args.noTelemetry,
|
|
1529
|
+
});
|
|
1468
1530
|
}
|
|
1469
1531
|
catch { /* telemetry never affects the exit */ }
|
|
1470
1532
|
// Update hint / prompt — printed after the command's own output, never
|
|
@@ -1479,7 +1541,11 @@ async function main() {
|
|
|
1479
1541
|
await checkForUpdate({ currentVersion: getCliVersion(), command: args.command });
|
|
1480
1542
|
}
|
|
1481
1543
|
catch { /* update hint never affects the exit */ }
|
|
1482
|
-
|
|
1544
|
+
// An unref deadline cannot keep an otherwise empty event loop alive.
|
|
1545
|
+
// Until completion is proven, even that early exit must fail closed.
|
|
1546
|
+
process.exitCode = code || 1;
|
|
1547
|
+
const completed = await Promise.all([drainOutput(process.stdout), drainOutput(process.stderr)]);
|
|
1548
|
+
process.exit(completed.every(Boolean) ? code : code || 1);
|
|
1483
1549
|
};
|
|
1484
1550
|
// `great-cto telemetry <on|off|status|whoami>` — inspect / toggle, never sends.
|
|
1485
1551
|
if (args.command === "distribution") {
|
|
@@ -183,8 +183,10 @@ function safeEnvironment(tx, npmPath) {
|
|
|
183
183
|
fs.mkdirSync(temp, { mode: 0o700 });
|
|
184
184
|
const config = path.join(tx, 'empty.npmrc');
|
|
185
185
|
fs.writeFileSync(config, '', { flag: 'wx', mode: 0o600 });
|
|
186
|
+
const globalConfig = path.join(tx, 'empty-global.npmrc');
|
|
187
|
+
fs.writeFileSync(globalConfig, '', { flag: 'wx', mode: 0o600 });
|
|
186
188
|
return { PATH: [path.dirname(process.execPath), path.dirname(npmPath), '/usr/bin', '/bin', '/usr/sbin', '/sbin'].join(path.delimiter),
|
|
187
|
-
HOME: home, USERPROFILE: home, TMPDIR: temp, NPM_CONFIG_USERCONFIG: config, NPM_CONFIG_GLOBALCONFIG:
|
|
189
|
+
HOME: home, USERPROFILE: home, TMPDIR: temp, NPM_CONFIG_USERCONFIG: config, NPM_CONFIG_GLOBALCONFIG: globalConfig,
|
|
188
190
|
NPM_CONFIG_CACHE: path.join(tx, 'npm-cache'), NPM_CONFIG_IGNORE_SCRIPTS: 'true', NPM_CONFIG_OFFLINE: 'true',
|
|
189
191
|
NPM_CONFIG_AUDIT: 'false', NPM_CONFIG_FUND: 'false', NPM_CONFIG_PACKAGE_LOCK: 'false',
|
|
190
192
|
DO_NOT_TRACK: '1', GREAT_CTO_TELEMETRY: 'off', GREAT_CTO_NO_BOARD: '1', GREAT_CTO_NO_UPDATE_CHECK: '1', CI: '1' };
|
package/dist/telemetry.js
CHANGED
|
@@ -150,7 +150,7 @@ async function send(evt) {
|
|
|
150
150
|
export async function sendInstallPing(opts) {
|
|
151
151
|
if (!opts.consent)
|
|
152
152
|
return;
|
|
153
|
-
if (!isTelemetryEnabled())
|
|
153
|
+
if (!isTelemetryEnabled(opts.noTelemetry))
|
|
154
154
|
return;
|
|
155
155
|
const evt = sanitize({ cliVersion: opts.cliVersion, command: "install", archetype: opts.archetype });
|
|
156
156
|
if (!evt)
|
|
@@ -159,7 +159,7 @@ export async function sendInstallPing(opts) {
|
|
|
159
159
|
}
|
|
160
160
|
/** Per-command usage ping. Sent only when enabled. Fire-and-forget. */
|
|
161
161
|
export async function sendUsagePing(opts) {
|
|
162
|
-
if (!isTelemetryEnabled())
|
|
162
|
+
if (!isTelemetryEnabled(opts.noTelemetry))
|
|
163
163
|
return;
|
|
164
164
|
const evt = sanitize({
|
|
165
165
|
cliVersion: opts.cliVersion,
|
package/package.json
CHANGED