ccgx-workflow 1.0.1 → 1.0.2

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.Bq9vAaEw.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.Bq9vAaEw.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.Bq9vAaEw.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';
@@ -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.2";
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.2",
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
  }