great-cto 2.5.5 → 2.5.6
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/dist/archetypes.js +23 -2
- package/dist/ci.js +5 -1
- package/dist/main.js +61 -4
- package/package.json +1 -1
package/dist/archetypes.js
CHANGED
|
@@ -156,9 +156,30 @@ const RULES = [
|
|
|
156
156
|
s += 6; // explicit agent framework
|
|
157
157
|
if ((hasLlm || hasLlmFw) && hasAgentFw)
|
|
158
158
|
s += 2; // bonus
|
|
159
|
-
//
|
|
160
|
-
|
|
159
|
+
// Project-shape signals (agent-runtime archetypes that don't depend
|
|
160
|
+
// on a specific framework — e.g. a deterministic local agent runtime
|
|
161
|
+
// built from scratch). Each signal is weak; multiple together strong.
|
|
162
|
+
const kws = d.readmeKeywords.map((k) => k.toLowerCase());
|
|
163
|
+
const agentRuntimeKws = [
|
|
164
|
+
"agent", "agent-runtime", "agent_runtime", "agentic",
|
|
165
|
+
"tool-calling", "tool-use", "tool_use", "tool-registry",
|
|
166
|
+
"planner", "agent-loop", "agent-runtime", "deterministic-agent",
|
|
167
|
+
"plan-step", "planstep", "tool-allowlist", "agent-budget",
|
|
168
|
+
"mcp-server", "mcp-client", "mcp",
|
|
169
|
+
];
|
|
170
|
+
const matchedAgentKws = agentRuntimeKws.filter((k) => kws.includes(k));
|
|
171
|
+
if (matchedAgentKws.length >= 3)
|
|
172
|
+
s += 5; // strong shape signal
|
|
173
|
+
else if (matchedAgentKws.length === 2)
|
|
174
|
+
s += 3;
|
|
175
|
+
else if (matchedAgentKws.length === 1)
|
|
161
176
|
s += 1;
|
|
177
|
+
// Stack-name patterns: agent-runtime / agent-product (the user
|
|
178
|
+
// explicitly named their library/package after agent or runtime).
|
|
179
|
+
// Detected via signals — d.stack includes the package name as a token.
|
|
180
|
+
const stackJoined = d.stack.join(" ").toLowerCase();
|
|
181
|
+
if (/(?:^| )agent[-_](?:runtime|product|loop|kit|sdk)/.test(stackJoined))
|
|
182
|
+
s += 2;
|
|
162
183
|
return s;
|
|
163
184
|
},
|
|
164
185
|
reason: (d) => {
|
package/dist/ci.js
CHANGED
|
@@ -114,7 +114,11 @@ async function archetypeCheck(cwd, quiet) {
|
|
|
114
114
|
if (result.primary !== declared) {
|
|
115
115
|
return {
|
|
116
116
|
ok: false,
|
|
117
|
-
msg: `archetype drift: declared=${declared}, detected=${result.primary} (${result.confidence})
|
|
117
|
+
msg: `archetype drift: declared=${declared}, detected=${result.primary} (${result.confidence}). ` +
|
|
118
|
+
`Either:\n` +
|
|
119
|
+
` • run 'npx great-cto adapt --platform <yours>' to refresh configs after intentional change, or\n` +
|
|
120
|
+
` • run 'npx great-cto init --force --archetype ${result.primary}' to align PROJECT.md with the codebase, or\n` +
|
|
121
|
+
` • pass '--no-archetype' to ci to skip this check (e.g. during transitional refactors)`,
|
|
118
122
|
};
|
|
119
123
|
}
|
|
120
124
|
return { ok: true, msg: `archetype confirmed: ${declared}` };
|
package/dist/main.js
CHANGED
|
@@ -95,6 +95,18 @@ function parseArgs(argv) {
|
|
|
95
95
|
args.command = "webhook";
|
|
96
96
|
else if (a === "report")
|
|
97
97
|
args.command = "report";
|
|
98
|
+
// Slash-commands surfaced as CLI subcommands so users get a clear hint
|
|
99
|
+
// instead of a confusing usage error. These work only in the chat plugin.
|
|
100
|
+
else if (a === "start" || a === "audit" || a === "inbox" || a === "digest" ||
|
|
101
|
+
a === "review" || a === "doctor" || a === "burn" || a === "save" ||
|
|
102
|
+
a === "resume" || a === "learn" || a === "agent-review" || a === "agent-retire" ||
|
|
103
|
+
a === "rfc" || a === "release" || a === "ownership" || a === "oncall" ||
|
|
104
|
+
a === "sec" || a === "poc" || a === "promote" || a === "crystallize" ||
|
|
105
|
+
a === "migrate") {
|
|
106
|
+
args.command = "chat-only-hint";
|
|
107
|
+
// Stash which command they tried so we can quote it back
|
|
108
|
+
args._slashTried = a;
|
|
109
|
+
}
|
|
98
110
|
else if (a.startsWith("--dir="))
|
|
99
111
|
args.dir = a.slice("--dir=".length);
|
|
100
112
|
else if (a === "--dir")
|
|
@@ -417,16 +429,45 @@ ${bold("Links:")}
|
|
|
417
429
|
async function runInit(args) {
|
|
418
430
|
banner();
|
|
419
431
|
// ── 1. detect ────────────────────────────────────────────
|
|
432
|
+
// Guard: refuse to init in $HOME or other "obviously not a project" locations.
|
|
433
|
+
// Most projects have at least one of: package.json / pyproject.toml /
|
|
434
|
+
// Cargo.toml / go.mod / .git / src/. Without any signal we'd default to
|
|
435
|
+
// greenfield with low confidence, which leaves users confused.
|
|
436
|
+
const HOME = process.env.HOME || process.env.USERPROFILE || "";
|
|
437
|
+
if (args.dir === HOME) {
|
|
438
|
+
error(`refusing to initialize great_cto in $HOME (${HOME}).`);
|
|
439
|
+
log("");
|
|
440
|
+
log(`great_cto is meant to run inside a project repository, not your home directory.`);
|
|
441
|
+
log(`If you're testing the install, ${cyan("cd")} into a real repo first:`);
|
|
442
|
+
log("");
|
|
443
|
+
log(` ${cyan("cd /path/to/your/project")}`);
|
|
444
|
+
log(` ${cyan("npx great-cto init")}`);
|
|
445
|
+
log("");
|
|
446
|
+
log(`Or create an empty test project:`);
|
|
447
|
+
log("");
|
|
448
|
+
log(` ${cyan("mkdir /tmp/test-greatcto && cd /tmp/test-greatcto && git init")}`);
|
|
449
|
+
log(` ${cyan("npx great-cto init")}`);
|
|
450
|
+
return 2;
|
|
451
|
+
}
|
|
420
452
|
step(1, 5, `scanning ${args.dir}`);
|
|
421
453
|
const detection = detect(args.dir);
|
|
422
454
|
if (detection.hasExistingGreatCto) {
|
|
423
455
|
warn(".great_cto/ already exists in this directory.");
|
|
424
|
-
|
|
456
|
+
log("");
|
|
457
|
+
log(`To preserve existing config: nothing to do, you're already initialized.`);
|
|
458
|
+
log(`To start fresh: back up ${cyan(".great_cto/")} first, then re-run with ${cyan("--force")}:`);
|
|
459
|
+
log("");
|
|
460
|
+
log(` ${cyan("npx great-cto init --force")}`);
|
|
461
|
+
log("");
|
|
462
|
+
log(`To override the detected archetype without re-init:`);
|
|
463
|
+
log("");
|
|
464
|
+
log(` ${cyan("npx great-cto init --force --archetype agent-product")}`);
|
|
465
|
+
log("");
|
|
425
466
|
if (!args.yes && !args.force) {
|
|
426
|
-
const ok = await confirm("Continue anyway?", false);
|
|
467
|
+
const ok = await confirm("Continue anyway? (existing PROJECT.md will be kept as-is)", false);
|
|
427
468
|
if (!ok) {
|
|
428
|
-
log("Aborted.");
|
|
429
|
-
return
|
|
469
|
+
log(yellow("Aborted. (Not an error — your existing config is intact.)"));
|
|
470
|
+
return 0; // exit 0 — user-initiated abort is not a failure
|
|
430
471
|
}
|
|
431
472
|
}
|
|
432
473
|
}
|
|
@@ -865,6 +906,22 @@ async function main() {
|
|
|
865
906
|
process.exit(2);
|
|
866
907
|
}
|
|
867
908
|
}
|
|
909
|
+
if (args.command === "chat-only-hint") {
|
|
910
|
+
const tried = args._slashTried || "<command>";
|
|
911
|
+
error(`'${tried}' is a chat slash command, not a CLI subcommand.`);
|
|
912
|
+
log("");
|
|
913
|
+
log(`To run it, open Claude Code, Cursor, or any AI assistant that has`);
|
|
914
|
+
log(`great_cto installed and type:`);
|
|
915
|
+
log("");
|
|
916
|
+
log(` ${cyan("/" + tried)} ${dim("[args]")}`);
|
|
917
|
+
log("");
|
|
918
|
+
log(`The CLI surface (this command) only exposes:`);
|
|
919
|
+
log(` ${cyan("init")} · ${cyan("scan")} · ${cyan("list-rules")} · ${cyan("ci")} · ${cyan("mcp")} ·`);
|
|
920
|
+
log(` ${cyan("adapt")} · ${cyan("serve")} · ${cyan("webhook")} · ${cyan("report")} · ${cyan("board")} · ${cyan("register")}`);
|
|
921
|
+
log("");
|
|
922
|
+
log(`Run ${cyan("npx great-cto --help")} for the full CLI reference.`);
|
|
923
|
+
process.exit(2);
|
|
924
|
+
}
|
|
868
925
|
if (args.command === "report") {
|
|
869
926
|
try {
|
|
870
927
|
const { runReport, parseReportArgs } = await import("./report.js");
|
package/package.json
CHANGED