ccgx-workflow 1.0.1 → 1.0.3

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/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import cac from 'cac';
3
3
  import ansis from 'ansis';
4
- import { d as diagnoseMcpConfig, i as isWindows, r as readClaudeCodeConfig, f as fixWindowsMcpConfig, w as writeClaudeCodeConfig, a as readCcgConfig, b as initI18n, c as i18n, s as showMainMenu, e as init, g as configMcp, v as version } from './shared/ccgx-workflow.SJPbUy5_.mjs';
4
+ import { d as diagnoseMcpConfig, i as isWindows, r as readClaudeCodeConfig, f as fixWindowsMcpConfig, w as writeClaudeCodeConfig, a as readCcgConfig, b as initI18n, c as i18n, s as showMainMenu, e as init, g as configMcp, v as version } from './shared/ccgx-workflow.BnfaZnVu.mjs';
5
5
  import 'inquirer';
6
6
  import 'ora';
7
7
  import 'node:child_process';
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { h as collectSkills } from './shared/ccgx-workflow.SJPbUy5_.mjs';
2
- export { j as changeLanguage, F as checkForUpdates, H as collectInvocableSkills, G as compareVersions, l as createDefaultConfig, m as createDefaultRouting, I as generateCommandContent, n as getCcgDir, o as getConfigPath, D as getCurrentVersion, E as getLatestVersion, q as getWorkflowById, p as getWorkflowConfigs, c as i18n, e as init, b as initI18n, x as installAceTool, y as installAceToolRs, J as installSkillCommands, t as installWorkflows, B as migrateToV1_4_0, C as needsMigration, K as parseFrontmatter, a as readCcgConfig, s as showMainMenu, A as uninstallAceTool, z as uninstallWorkflows, u as update, k as writeCcgConfig } from './shared/ccgx-workflow.SJPbUy5_.mjs';
1
+ import { h as collectSkills } from './shared/ccgx-workflow.BnfaZnVu.mjs';
2
+ export { j as changeLanguage, F as checkForUpdates, H as collectInvocableSkills, G as compareVersions, l as createDefaultConfig, m as createDefaultRouting, I as generateCommandContent, n as getCcgDir, o as getConfigPath, D as getCurrentVersion, E as getLatestVersion, q as getWorkflowById, p as getWorkflowConfigs, c as i18n, e as init, b as initI18n, x as installAceTool, y as installAceToolRs, J as installSkillCommands, t as installWorkflows, B as migrateToV1_4_0, C as needsMigration, K as parseFrontmatter, a as readCcgConfig, s as showMainMenu, A as uninstallAceTool, z as uninstallWorkflows, u as update, k as writeCcgConfig } from './shared/ccgx-workflow.BnfaZnVu.mjs';
3
3
  import { existsSync, readFileSync, mkdirSync, writeFileSync, statSync, readdirSync } from 'node:fs';
4
4
  import { join, dirname } from 'node:path';
5
5
  import { homedir } from 'node:os';
@@ -986,9 +986,9 @@ function resolveQualityTier(input) {
986
986
  return { tier: "triple", source: "default" };
987
987
  }
988
988
  const PHASE_RUNNER_BUDGET_USD = {
989
- fast: 1,
990
- triple: 2,
991
- debate: 5
989
+ fast: 50,
990
+ triple: 100,
991
+ debate: 250
992
992
  };
993
993
  function shellSingleQuote(s) {
994
994
  return `'${s.replace(/'/g, `'\\''`)}'`;
@@ -10,7 +10,7 @@ import fs from 'fs-extra';
10
10
  import { parse, stringify } from 'smol-toml';
11
11
  import i18next from 'i18next';
12
12
 
13
- const version = "1.0.1";
13
+ const version = "1.0.3";
14
14
 
15
15
  function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdOverride) {
16
16
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccgx-workflow",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Multi-model orchestration for Claude Code. Codex + Gemini parallel collaboration with fresh-context subagent protocols, OS-level process isolation, and Plan-Critic-Verify quality tiers. Successor to ccg-workflow.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.17.1",
@@ -188,6 +188,33 @@ function composeMessage(head, active, summary, counts) {
188
188
  return msg
189
189
  }
190
190
 
191
+ // ---------------------------------------------------------------------------
192
+ // v1.0.2 — phase-runner CLI self-reference guard.
193
+ //
194
+ // Why this exists:
195
+ // The launcher (templates/scripts/ccg-phase-runner-launcher.mjs) spawns
196
+ // `claude -p --agent ccg/phase-runner`. That child process is itself a fresh
197
+ // Claude Code session, so SessionStart hooks fire inside it too. Without a
198
+ // guard the hook would:
199
+ // 1. Inject the orchestrator-style "Project memory restored / Active phase
200
+ // / Phases X/Y completed" context into a subagent that already has its
201
+ // own focused phase prompt — confusing the model into orchestrator
202
+ // behaviour (e.g. running `/ccg:status` and waiting on its own job).
203
+ // 2. Run the reconciler over `.context/jobs/*`, see its own state.json
204
+ // with `cli_pid` alive, and (harmlessly) no-op — but the additionalContext
205
+ // injection is the actual self-reference loop trigger.
206
+ //
207
+ // The launcher injects two env vars that uniquely tag a phase-runner CLI
208
+ // subprocess: `CCG_JOB_ID` + `CCG_PHASE_RUNNER_TIER`. Either alone is too
209
+ // weak (CCG_JOB_ID could be set elsewhere); requiring both keeps the
210
+ // detection narrow.
211
+ // ---------------------------------------------------------------------------
212
+
213
+ function isPhaseRunnerSubprocess(env) {
214
+ const e = env || process.env
215
+ return Boolean(e.CCG_JOB_ID) && Boolean(e.CCG_PHASE_RUNNER_TIER)
216
+ }
217
+
191
218
  // ---------------------------------------------------------------------------
192
219
  // v4.5 P1b — startup reconciler (inlined CJS twin of src/utils/process-tree.ts).
193
220
  //
@@ -291,6 +318,21 @@ function reconcileStaleJobs(cwd, options) {
291
318
  continue
292
319
  }
293
320
 
321
+ // v1.0.2 defense-in-depth: if the reconciler is somehow running inside the
322
+ // very phase-runner CLI subprocess that owns this state.json (the main()
323
+ // env-guard should already have short-circuited before reaching here),
324
+ // refuse to act on our own row. Without this, a future code path that
325
+ // tightens "cli_pid alive" handling could mistakenly mark our own job
326
+ // failed/adopted and burn the launcher's atomic state contract.
327
+ if (state.cli_pid === process.pid) {
328
+ report.entries.push({
329
+ jobId: id,
330
+ action: 'no-op',
331
+ reason: 'self-reference: state.cli_pid === process.pid',
332
+ })
333
+ continue
334
+ }
335
+
294
336
  const alive = isAlive(state.cli_pid)
295
337
  let pidProbablyReused = false
296
338
  if (alive && state.started_at) {
@@ -444,6 +486,18 @@ function emit(additionalContext) {
444
486
  }
445
487
 
446
488
  function main() {
489
+ // v1.0.2 — phase-runner CLI self-reference guard. When this hook runs inside
490
+ // a launcher-spawned `claude -p --agent ccg/phase-runner` subprocess, emit
491
+ // an empty hookSpecificOutput and exit before reading roadmap/jobs. The
492
+ // subagent already has its own scoped prompt; injecting the orchestrator's
493
+ // "Project memory / Active phase / All phases completed" context confuses
494
+ // the model into running /ccg:status and waiting on its own running job
495
+ // (cli_pid → it sees itself alive → 2-min idle self-terminate, zero output).
496
+ if (isPhaseRunnerSubprocess(process.env)) {
497
+ process.stdout.write('{}')
498
+ process.exit(0)
499
+ }
500
+
447
501
  let input = ''
448
502
  // Timeout guard mirrors ccg-context-monitor: never hang on a stuck pipe.
449
503
  const timer = setTimeout(() => process.exit(0), 10000)
@@ -507,4 +561,6 @@ module.exports = {
507
561
  atomicWriteFileSync,
508
562
  reconcileStaleJobs,
509
563
  summarizeReconciliation,
564
+ // v1.0.2 additions:
565
+ isPhaseRunnerSubprocess,
510
566
  }
@@ -152,7 +152,7 @@ Required:
152
152
 
153
153
  Optional:
154
154
  --tier <fast|triple|debate> Quality tier; maps to --max-budget-usd
155
- (fast=1, triple=2, debate=5). Default: triple.
155
+ (fast=50, triple=100, debate=250). Default: triple.
156
156
  --max-budget-usd <N> Override per-call budget cap.
157
157
  --grace-ms <N> SIGTERM->SIGKILL grace (default 5000).
158
158
 
@@ -193,7 +193,13 @@ function writeState(workdir, jobId, state) {
193
193
  // production phase-runner spawn).
194
194
  // ---------------------------------------------------------------------------
195
195
 
196
- const TIER_BUDGET = { fast: 1.0, triple: 2.0, debate: 5.0 }
196
+ // v1.0.3: ×50 raise after user feedback. PoC D3 baseline (fast=$1 / triple=$2
197
+ // / debate=$5) was tuned for "p90 + 50% margin" of *single phase* spawns, but
198
+ // real autonomous runs hit the cap on edge cases ($1.034 over $1) — tight
199
+ // enough to surface as failures rather than runaway loops. Raising to 50/100/
200
+ // 250 keeps the runaway-loop guardrail intact (a stuck loop blows >$1000 fast)
201
+ // while removing the false-positive failure mode for legitimately complex phases.
202
+ const TIER_BUDGET = { fast: 50.0, triple: 100.0, debate: 250.0 }
197
203
 
198
204
  function buildClaudeArgs({ promptFile, workdir, tier, maxBudgetUsd }) {
199
205
  const budget = maxBudgetUsd ?? TIER_BUDGET[tier]