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.
@@ -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
- // README mining hint
160
- if (d.readmeKeywords.includes("agent") || d.readmeKeywords.includes("ai"))
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
- warn("If you're re-initializing, back it up first or run with --force.");
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 1;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "great-cto",
3
- "version": "2.5.5",
3
+ "version": "2.5.6",
4
4
  "description": "One command install for the great_cto Claude Code plugin. Auto-detects your stack, picks the right archetype, bootstraps PROJECT.md.",
5
5
  "keywords": [
6
6
  "claude-code",