@imdeadpool/guardex 7.0.23 → 7.0.25

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.
Files changed (26) hide show
  1. package/README.md +30 -3
  2. package/package.json +1 -1
  3. package/src/cli/args.js +9 -0
  4. package/src/cli/main.js +7 -2
  5. package/src/context.js +22 -0
  6. package/src/doctor/index.js +158 -5
  7. package/src/finish/index.js +1 -0
  8. package/src/report/session-severity.js +77 -8
  9. package/templates/AGENTS.multiagent-safety.md +3 -0
  10. package/templates/codex/skills/guardex-merge-skills-to-dev/SKILL.md +3 -2
  11. package/templates/scripts/agent-branch-finish.sh +155 -5
  12. package/templates/scripts/agent-branch-start.sh +35 -0
  13. package/templates/scripts/agent-worktree-prune.sh +22 -1
  14. package/templates/vscode/guardex-active-agents/README.md +6 -3
  15. package/templates/vscode/guardex-active-agents/extension.js +1706 -247
  16. package/templates/vscode/guardex-active-agents/fileicons/gitguardex-fileicons.json +54 -0
  17. package/templates/vscode/guardex-active-agents/fileicons/icons/agent.svg +4 -0
  18. package/templates/vscode/guardex-active-agents/fileicons/icons/branch.svg +4 -0
  19. package/templates/vscode/guardex-active-agents/fileicons/icons/config.svg +4 -0
  20. package/templates/vscode/guardex-active-agents/fileicons/icons/hook.svg +3 -0
  21. package/templates/vscode/guardex-active-agents/fileicons/icons/openspec.svg +5 -0
  22. package/templates/vscode/guardex-active-agents/fileicons/icons/plan.svg +4 -0
  23. package/templates/vscode/guardex-active-agents/fileicons/icons/spec.svg +4 -0
  24. package/templates/vscode/guardex-active-agents/media/active-agents-hivemind.svg +14 -0
  25. package/templates/vscode/guardex-active-agents/package.json +39 -11
  26. package/templates/vscode/guardex-active-agents/session-schema.js +226 -8
package/README.md CHANGED
@@ -140,7 +140,7 @@ That's it. Install and update via `@imdeadpool/guardex`. Setup installs the mini
140
140
  </div>
141
141
 
142
142
  > [!NOTE]
143
- > In this repo, `CLAUDE.md` is a symlink to `AGENTS.md`, so Claude reads the same contract. Optional Codex/Claude companion files are installed at the user level with `gx install-agent-skills`, not copied into each repo.
143
+ > In this repo, `CLAUDE.md` is a symlink to `AGENTS.md`, so Claude reads the same contract. Optional Codex/Claude companion files still install at the user level with `gx install-agent-skills`, while the generic repo skill catalog is available through `npx skills add recodeee/` or directly via `npx skills add recodeee/gitguardex`.
144
144
 
145
145
  ### Decision flow
146
146
 
@@ -266,7 +266,7 @@ To install the real companion into local VS Code from a GitGuardex-wired repo:
266
266
  node scripts/install-vscode-active-agents-extension.js
267
267
  ```
268
268
 
269
- It adds an `Active Agents` view to the Source Control container, groups each live repo into `ACTIVE AGENTS` and `CHANGES` sections, splits `ACTIVE AGENTS` into `BLOCKED`, `WORKING NOW`, `IDLE`, `STALLED`, and `DEAD` when those states are present, mirrors the selected session or active-agent count in the VS Code status bar, reads `.omx/state/active-sessions/*.json`, derives session state from git conflict markers, dirty worktree status, PID liveness, and recent file mtimes, and surfaces working/dead counts in the repo/header affordances. Reload the VS Code window after install.
269
+ It adds a dedicated `Active Agents` Activity Bar container with a hive icon, shows the live active-agent count as a badge on that icon, groups each live repo into `ACTIVE AGENTS` and `CHANGES` sections, splits `ACTIVE AGENTS` into `BLOCKED`, `WORKING NOW`, `IDLE`, `STALLED`, and `DEAD` when those states are present, mirrors the selected session or active-agent count in the VS Code status bar, reads `.omx/state/active-sessions/*.json`, derives session state from git conflict markers, dirty worktree status, PID liveness, and recent file mtimes, and surfaces working/dead counts in the repo/header affordances. Reload the VS Code window after install.
270
270
 
271
271
  ---
272
272
 
@@ -459,6 +459,23 @@ npm i -g oh-my-claude-sisyphus@latest
459
459
  Repo: <https://github.com/Yeachan-Heo/oh-my-claudecode>
460
460
  [![GitHub stars](https://img.shields.io/github/stars/Yeachan-Heo/oh-my-claudecode?style=social)](https://github.com/Yeachan-Heo/oh-my-claudecode)
461
461
 
462
+ ### GitGuardex skills - install the repo skill catalog through `npx skills`
463
+
464
+ For agents that already support the generic `skills` installer flow, GitGuardex now exposes its repo skill catalog directly. You can start from the broader `recodeee` source or jump straight into this repo's catalog.
465
+
466
+ ```sh
467
+ npx skills add recodeee/
468
+ ```
469
+
470
+ ```sh
471
+ npx skills add recodeee/gitguardex
472
+ ```
473
+
474
+ This repo currently exposes `gitguardex` and `guardex-merge-skills-to-dev` through that flow. If the picker does not show a separate `guardex` skill, that is expected: `guardex` remains the legacy CLI alias, while the repo skill itself is named `gitguardex`. Use `gx install-agent-skills` when you want the Codex/Claude user-home startup files instead of the generic `skills` catalog.
475
+
476
+ Repo: <https://github.com/recodeee/gitguardex>
477
+ [![GitHub stars](https://img.shields.io/github/stars/recodeee/gitguardex?style=social)](https://github.com/recodeee/gitguardex)
478
+
462
479
  ### Caveman — output compression for long agent runs
463
480
 
464
481
  Ultra-compressed response mode for Claude/Codex-style agents. Useful when you want less output-token churn during long reviews, debug loops, or multi-agent sessions.
@@ -609,7 +626,7 @@ vscode/guardex-active-agents/README.md
609
626
 
610
627
  Legacy compatibility note: older repos may still contain repo-local workflow scripts under `scripts/`. Direct `gx branch ...`, `gx locks ...`, `gx finish`, `gx cleanup`, `gx merge`, and `gx migrate` do not require them. `gx migrate` removes those leftover workflow shims by default. The CLI still honors repo-local `scripts/review-bot-watch.sh` and `scripts/codex-agent.sh` when they are already present so older repos can keep working during migration.
611
628
 
612
- Optional Codex/Claude user-level companions still install with `gx install-agent-skills`; they are not copied into each repo.
629
+ Optional Codex/Claude user-level companions still install with `gx install-agent-skills`; the generic repo skill catalog is available with `npx skills add recodeee/` or directly via `npx skills add recodeee/gitguardex`. Neither path copies those user-home files into each repo.
613
630
 
614
631
  ---
615
632
 
@@ -672,6 +689,16 @@ npm pack --dry-run
672
689
  <details>
673
690
  <summary><strong>v7.x</strong></summary>
674
691
 
692
+ ### v7.0.25
693
+ - Bumped `@imdeadpool/guardex` from `7.0.24` to `7.0.25` so npm and GitHub Releases can ship the current `main` payload.
694
+ - The bundled `GitGuardex Active Agents` VS Code companion now self-heals stale repo-scan ignore settings in older repos, keeps plain managed sandboxes visible in Source Control, and preserves cleanup truth so the tree matches actual sandbox state.
695
+ - Bumped the shipped Active Agents companion manifests from `0.0.8` to `0.0.9` so local VS Code installs can pick up the newer workspace build and show the refreshed extension version from this release.
696
+
697
+ ### v7.0.24
698
+ - Bumped `@imdeadpool/guardex` from `7.0.23` to `7.0.24` so GitHub Releases and the npm publish retry can advance together after `v7.0.23` landed on GitHub but not on npm.
699
+ - Release verification no longer loses its base ref on tag-triggered runs, so the publish workflow keeps the history it needs before packing and publish checks.
700
+ - Keep the release scoped to version and release automation metadata only; the packaged Guardex CLI payload stays aligned with the already-verified `main` branch contents.
701
+
675
702
  ### v7.0.23
676
703
  - Bumped `@imdeadpool/guardex` from `7.0.22` to `7.0.23` so GitHub release and npm can advance together after `7.0.22` reached npm without a matching published GitHub release.
677
704
  - Active Agents stays easier to scan and more truthful: the package repo remains the canonical source, inspect/install paths stay loadable across VS Code churn, and session rows group under worktrees with clearer merged-cleanup truth.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imdeadpool/guardex",
3
- "version": "7.0.23",
3
+ "version": "7.0.25",
4
4
  "description": "Guardian T-Rex for your multi-agent repo. Isolated worktrees, file locks, and PR-only merges stop parallel Codex & Claude agents from overwriting each other's work. Auto-wires Oh My Codex, Oh My Claude, OpenSpec, and Caveman.",
5
5
  "license": "MIT",
6
6
  "preferGlobal": true,
package/src/cli/args.js CHANGED
@@ -770,6 +770,7 @@ function parseFinishArgs(rawArgs, defaults = {}) {
770
770
  cleanup: defaults.cleanup ?? true,
771
771
  keepRemote: false,
772
772
  noAutoCommit: false,
773
+ parentGitlinkCommit: defaults.parentGitlinkCommit ?? true,
773
774
  failFast: false,
774
775
  commitMessage: '',
775
776
  mergeMode: defaults.mergeMode || 'pr',
@@ -865,6 +866,14 @@ function parseFinishArgs(rawArgs, defaults = {}) {
865
866
  options.noAutoCommit = true;
866
867
  continue;
867
868
  }
869
+ if (arg === '--parent-gitlink-commit') {
870
+ options.parentGitlinkCommit = true;
871
+ continue;
872
+ }
873
+ if (arg === '--no-parent-gitlink-commit') {
874
+ options.parentGitlinkCommit = false;
875
+ continue;
876
+ }
868
877
  if (arg === '--fail-fast') {
869
878
  options.failFast = true;
870
879
  continue;
package/src/cli/main.js CHANGED
@@ -2431,15 +2431,20 @@ function report(rawArgs) {
2431
2431
  const options = parseReportArgs(rawArgs);
2432
2432
  const subcommand = options.subcommand || 'help';
2433
2433
  if (subcommand === 'help' || subcommand === '--help' || subcommand === '-h') {
2434
+ const sessionSeverityHelpDetails = sessionSeverityReport.renderSessionSeverityHelpDetails()
2435
+ .split('\n')
2436
+ .map((line) => ` ${line}`)
2437
+ .join('\n');
2434
2438
  console.log(
2435
2439
  `${TOOL_NAME} report commands:\n` +
2436
2440
  ` ${TOOL_NAME} report scorecard [--target <path>] [--repo github.com/<owner>/<repo>] [--scorecard-json <file>] [--output-dir <path>] [--date YYYY-MM-DD] [--dry-run] [--json]\n` +
2437
- ` ${TOOL_NAME} report session-severity --task-size <narrow-patch|medium-change|large-change> --tokens <count> --exec-count <count> --write-stdin-count <count> --completion-before-tail <yes|no> [--expected-bound <count>] [--fragmentation <preset|0-25>] [--finish-path <preset|0-15>] [--post-proof <preset|0-15>] [--json]\n` +
2441
+ ` ${sessionSeverityReport.renderSessionSeverityCommand(TOOL_NAME)}\n` +
2442
+ `${sessionSeverityHelpDetails}\n` +
2438
2443
  `\n` +
2439
2444
  `Examples:\n` +
2440
2445
  ` ${TOOL_NAME} report scorecard --repo github.com/recodeecom/multiagent-safety\n` +
2441
2446
  ` ${TOOL_NAME} report scorecard --scorecard-json ./scorecard.json --date 2026-04-10\n` +
2442
- ` ${TOOL_NAME} report session-severity --task-size narrow-patch --tokens 3850000 --exec-count 18 --write-stdin-count 6 --completion-before-tail yes --fragmentation 14 --finish-path 6 --post-proof 4`,
2447
+ ` ${sessionSeverityReport.renderSessionSeverityExample(TOOL_NAME)}`,
2443
2448
  );
2444
2449
  process.exitCode = 0;
2445
2450
  return;
package/src/context.js CHANGED
@@ -129,6 +129,14 @@ const TEMPLATE_FILES = [
129
129
  'vscode/guardex-active-agents/session-schema.js',
130
130
  'vscode/guardex-active-agents/README.md',
131
131
  'vscode/guardex-active-agents/icon.png',
132
+ 'vscode/guardex-active-agents/fileicons/gitguardex-fileicons.json',
133
+ 'vscode/guardex-active-agents/fileicons/icons/agent.svg',
134
+ 'vscode/guardex-active-agents/fileicons/icons/branch.svg',
135
+ 'vscode/guardex-active-agents/fileicons/icons/config.svg',
136
+ 'vscode/guardex-active-agents/fileicons/icons/hook.svg',
137
+ 'vscode/guardex-active-agents/fileicons/icons/openspec.svg',
138
+ 'vscode/guardex-active-agents/fileicons/icons/plan.svg',
139
+ 'vscode/guardex-active-agents/fileicons/icons/spec.svg',
132
140
  ];
133
141
 
134
142
  const PACKAGE_ROOT_SOURCE_OVERRIDES = new Set([
@@ -139,6 +147,14 @@ const PACKAGE_ROOT_SOURCE_OVERRIDES = new Set([
139
147
  'vscode/guardex-active-agents/session-schema.js',
140
148
  'vscode/guardex-active-agents/README.md',
141
149
  'vscode/guardex-active-agents/icon.png',
150
+ 'vscode/guardex-active-agents/fileicons/gitguardex-fileicons.json',
151
+ 'vscode/guardex-active-agents/fileicons/icons/agent.svg',
152
+ 'vscode/guardex-active-agents/fileicons/icons/branch.svg',
153
+ 'vscode/guardex-active-agents/fileicons/icons/config.svg',
154
+ 'vscode/guardex-active-agents/fileicons/icons/hook.svg',
155
+ 'vscode/guardex-active-agents/fileicons/icons/openspec.svg',
156
+ 'vscode/guardex-active-agents/fileicons/icons/plan.svg',
157
+ 'vscode/guardex-active-agents/fileicons/icons/spec.svg',
142
158
  ]);
143
159
 
144
160
  const LEGACY_WORKFLOW_SHIM_SPECS = [
@@ -263,8 +279,12 @@ const AGENT_WORKTREE_RELATIVE_DIRS = [
263
279
  const MANAGED_REPO_SCAN_IGNORED_FOLDERS = [
264
280
  '.omx/agent-worktrees',
265
281
  '**/.omx/agent-worktrees',
282
+ '.omx/.tmp-worktrees',
283
+ '**/.omx/.tmp-worktrees',
266
284
  '.omc/agent-worktrees',
267
285
  '**/.omc/agent-worktrees',
286
+ '.omc/.tmp-worktrees',
287
+ '**/.omc/.tmp-worktrees',
268
288
  ];
269
289
  const MANAGED_GITIGNORE_PATHS = [
270
290
  '.omx/',
@@ -427,6 +447,8 @@ const AI_SETUP_PARTS = [
427
447
  'gx branch start "<task>" "<agent>"',
428
448
  'then gx locks claim --branch "<agent-branch>" <file...> -> inspect once -> patch once -> verify once -> gx branch finish',
429
449
  'batch discovery, git/PR, and CI by phase; avoid repeated peeks or stdin loops',
450
+ 'checkpoint after each milestone: Task -> Done -> Current status -> Next; keep only the latest checkpoint(s) in active context',
451
+ 'summarize tool results, keep stdin/process chatter ephemeral, and keep execution log separate from reasoning context',
430
452
  ],
431
453
  execLines: [
432
454
  'gx branch start "<task>" "<agent>"',
@@ -314,6 +314,118 @@ function doctorFinishFlowIsPending(output) {
314
314
  );
315
315
  }
316
316
 
317
+ function verifyDoctorSandboxCleanup(repoRoot, metadata) {
318
+ const branchExists = Boolean(metadata.branch) && gitRefExists(repoRoot, `refs/heads/${metadata.branch}`);
319
+ const worktreeExists = Boolean(metadata.worktreePath) && fs.existsSync(metadata.worktreePath);
320
+
321
+ if (!branchExists && !worktreeExists) {
322
+ return {
323
+ status: 'verified',
324
+ note: 'doctor sandbox cleanup verified',
325
+ };
326
+ }
327
+
328
+ const cleanup = cleanupProtectedBaseSandbox(repoRoot, metadata);
329
+ const branchStillExists = Boolean(metadata.branch) && gitRefExists(repoRoot, `refs/heads/${metadata.branch}`);
330
+ const worktreeStillExists = Boolean(metadata.worktreePath) && fs.existsSync(metadata.worktreePath);
331
+ if (branchStillExists || worktreeStillExists) {
332
+ return {
333
+ status: 'failed',
334
+ note:
335
+ 'doctor sandbox cleanup incomplete ' +
336
+ `(branch=${branchStillExists ? 'present' : 'missing'}, worktree=${worktreeStillExists ? 'present' : 'missing'})`,
337
+ cleanup,
338
+ };
339
+ }
340
+
341
+ return {
342
+ status: 'verified',
343
+ note: 'doctor sandbox cleanup verified',
344
+ cleanup,
345
+ };
346
+ }
347
+
348
+ function verifyDoctorSandboxRemoteCleanup(repoRoot, metadata) {
349
+ if (!metadata.branch || !hasOriginRemote(repoRoot)) {
350
+ return {
351
+ status: 'skipped',
352
+ note: 'doctor sandbox remote cleanup skipped',
353
+ };
354
+ }
355
+
356
+ const remoteBefore = run(
357
+ 'git',
358
+ ['-C', repoRoot, 'ls-remote', '--heads', 'origin', metadata.branch],
359
+ { timeout: 20_000 },
360
+ );
361
+ if (isSpawnFailure(remoteBefore)) {
362
+ throw remoteBefore.error;
363
+ }
364
+ if (remoteBefore.status !== 0) {
365
+ return {
366
+ status: 'failed',
367
+ note: 'doctor sandbox remote branch inspection failed',
368
+ stdout: remoteBefore.stdout || '',
369
+ stderr: remoteBefore.stderr || '',
370
+ };
371
+ }
372
+ if (!String(remoteBefore.stdout || '').trim()) {
373
+ return {
374
+ status: 'verified',
375
+ note: 'doctor sandbox remote cleanup verified',
376
+ };
377
+ }
378
+
379
+ const deleteResult = run(
380
+ 'git',
381
+ ['-C', repoRoot, 'push', 'origin', '--delete', metadata.branch],
382
+ { timeout: 30_000 },
383
+ );
384
+ if (isSpawnFailure(deleteResult)) {
385
+ throw deleteResult.error;
386
+ }
387
+ if (deleteResult.status !== 0) {
388
+ return {
389
+ status: 'failed',
390
+ note: 'doctor sandbox remote branch cleanup failed',
391
+ stdout: deleteResult.stdout || '',
392
+ stderr: deleteResult.stderr || '',
393
+ };
394
+ }
395
+
396
+ const remoteAfter = run(
397
+ 'git',
398
+ ['-C', repoRoot, 'ls-remote', '--heads', 'origin', metadata.branch],
399
+ { timeout: 20_000 },
400
+ );
401
+ if (isSpawnFailure(remoteAfter)) {
402
+ throw remoteAfter.error;
403
+ }
404
+ if (remoteAfter.status !== 0) {
405
+ return {
406
+ status: 'failed',
407
+ note: 'doctor sandbox remote cleanup recheck failed',
408
+ stdout: remoteAfter.stdout || '',
409
+ stderr: remoteAfter.stderr || '',
410
+ };
411
+ }
412
+ if (String(remoteAfter.stdout || '').trim()) {
413
+ return {
414
+ status: 'failed',
415
+ note: 'doctor sandbox remote branch still present after cleanup',
416
+ stdout: remoteAfter.stdout || '',
417
+ stderr: remoteAfter.stderr || '',
418
+ };
419
+ }
420
+
421
+ return {
422
+ status: 'verified',
423
+ note: 'doctor sandbox remote cleanup verified',
424
+ stdout: deleteResult.stdout || '',
425
+ stderr: deleteResult.stderr || '',
426
+ };
427
+ }
428
+
317
429
  function finishDoctorSandboxBranch(blocked, metadata, options = {}) {
318
430
  if (!hasOriginRemote(blocked.repoRoot)) {
319
431
  return {
@@ -353,8 +465,8 @@ function finishDoctorSandboxBranch(blocked, metadata, options = {}) {
353
465
 
354
466
  const finishResult = runPackageAsset(
355
467
  'branchFinish',
356
- ['--branch', metadata.branch, '--base', blocked.branch, '--via-pr', waitForMergeArg, '--cleanup'],
357
- { cwd: metadata.worktreePath, timeout: finishTimeoutMs },
468
+ ['--branch', metadata.branch, '--base', blocked.branch, '--via-pr', waitForMergeArg, '--no-cleanup'],
469
+ { cwd: blocked.repoRoot, timeout: finishTimeoutMs },
358
470
  );
359
471
  if (isSpawnFailure(finishResult)) {
360
472
  return {
@@ -384,11 +496,52 @@ function finishDoctorSandboxBranch(blocked, metadata, options = {}) {
384
496
  };
385
497
  }
386
498
 
499
+ let cleanupVerification;
500
+ try {
501
+ cleanupVerification = verifyDoctorSandboxCleanup(blocked.repoRoot, metadata);
502
+ } catch (error) {
503
+ return {
504
+ status: 'failed',
505
+ note: `doctor sandbox cleanup verification failed: ${error.message}`,
506
+ stdout: finishResult.stdout || '',
507
+ stderr: finishResult.stderr || '',
508
+ };
509
+ }
510
+ if (cleanupVerification.status === 'failed') {
511
+ return {
512
+ status: 'failed',
513
+ note: cleanupVerification.note,
514
+ stdout: finishResult.stdout || '',
515
+ stderr: finishResult.stderr || '',
516
+ };
517
+ }
518
+
519
+ let remoteCleanupVerification;
520
+ try {
521
+ remoteCleanupVerification = verifyDoctorSandboxRemoteCleanup(blocked.repoRoot, metadata);
522
+ } catch (error) {
523
+ return {
524
+ status: 'failed',
525
+ note: `doctor sandbox remote cleanup verification failed: ${error.message}`,
526
+ stdout: finishResult.stdout || '',
527
+ stderr: finishResult.stderr || '',
528
+ };
529
+ }
530
+ if (remoteCleanupVerification.status === 'failed') {
531
+ return {
532
+ status: 'failed',
533
+ note: remoteCleanupVerification.note,
534
+ stdout: [finishResult.stdout || '', remoteCleanupVerification.stdout || ''].filter(Boolean).join('\n'),
535
+ stderr: [finishResult.stderr || '', remoteCleanupVerification.stderr || ''].filter(Boolean).join('\n'),
536
+ };
537
+ }
538
+
387
539
  return {
388
540
  status: 'completed',
389
- note: 'doctor sandbox finish flow completed',
390
- stdout: finishResult.stdout || '',
391
- stderr: finishResult.stderr || '',
541
+ note: 'doctor sandbox finish flow completed and cleanup verified',
542
+ stdout: [finishResult.stdout || '', remoteCleanupVerification.stdout || ''].filter(Boolean).join('\n'),
543
+ stderr: [finishResult.stderr || '', remoteCleanupVerification.stderr || ''].filter(Boolean).join('\n'),
544
+ cleanup: cleanupVerification.cleanup,
392
545
  };
393
546
  }
394
547
 
@@ -317,6 +317,7 @@ function finish(rawArgs, defaults = {}) {
317
317
  if (options.keepRemote) {
318
318
  finishArgs.push('--keep-remote-branch');
319
319
  }
320
+ finishArgs.push(options.parentGitlinkCommit ? '--parent-gitlink-commit' : '--no-parent-gitlink-commit');
320
321
 
321
322
  if (options.dryRun) {
322
323
  console.log(`[${TOOL_NAME}] [dry-run] Would run: gx branch finish ${finishArgs.join(' ')}`);
@@ -4,7 +4,8 @@ const TASK_SIZE_UPPER_BOUNDS = {
4
4
  'large-change': 8_000_000,
5
5
  };
6
6
 
7
- const TASK_SIZE_VALUES = new Set(Object.keys(TASK_SIZE_UPPER_BOUNDS));
7
+ const TASK_SIZE_VALUES = Object.keys(TASK_SIZE_UPPER_BOUNDS);
8
+ const TASK_SIZE_SET = new Set(TASK_SIZE_VALUES);
8
9
  const FRAGMENTATION_PRESET_SCORES = {
9
10
  clean: 0,
10
11
  'few-extra-checks': 5,
@@ -32,6 +33,50 @@ const DRIVER_LABELS = {
32
33
  finishPath: 'finish-path discipline',
33
34
  postProof: 'post-proof drift',
34
35
  };
36
+ const LABEL_BANDS = [
37
+ { max: 15, label: 'Healthy' },
38
+ { max: 30, label: 'Mildly fragmented' },
39
+ { max: 50, label: 'Inefficient' },
40
+ { max: 75, label: 'Runaway' },
41
+ { max: 100, label: 'Catastrophic' },
42
+ ];
43
+ const SESSION_SEVERITY_SUBCOMMAND = 'session-severity';
44
+ const SESSION_SEVERITY_USAGE_ARGS = [
45
+ `--task-size <${TASK_SIZE_VALUES.join('|')}>`,
46
+ '--tokens <count>',
47
+ '--exec-count <count>',
48
+ '--write-stdin-count <count>',
49
+ '--completion-before-tail <yes|no>',
50
+ '[--expected-bound <count>]',
51
+ `[--fragmentation <${Object.keys(FRAGMENTATION_PRESET_SCORES).join('|')}|0-25>]`,
52
+ `[--finish-path <${Object.keys(FINISH_PATH_PRESET_SCORES).join('|')}|0-15>]`,
53
+ `[--post-proof <${Object.keys(POST_PROOF_PRESET_SCORES).join('|')}|0-15>]`,
54
+ '[--json]',
55
+ ].join(' ');
56
+ const SESSION_SEVERITY_COMMAND_TAIL = `${SESSION_SEVERITY_SUBCOMMAND} ${SESSION_SEVERITY_USAGE_ARGS}`;
57
+ const SESSION_SEVERITY_EXAMPLE_ARGS = [
58
+ '--task-size',
59
+ 'narrow-patch',
60
+ '--tokens',
61
+ '3850000',
62
+ '--exec-count',
63
+ '18',
64
+ '--write-stdin-count',
65
+ '6',
66
+ '--completion-before-tail',
67
+ 'yes',
68
+ '--fragmentation',
69
+ '14',
70
+ '--finish-path',
71
+ '6',
72
+ '--post-proof',
73
+ '4',
74
+ ];
75
+ const SESSION_SEVERITY_EXAMPLE_TAIL = `${SESSION_SEVERITY_SUBCOMMAND} ${SESSION_SEVERITY_EXAMPLE_ARGS.join(' ')}`;
76
+
77
+ function formatInteger(value) {
78
+ return Number(value).toLocaleString('en-US');
79
+ }
35
80
 
36
81
  function parseRequiredPositiveInteger(name, rawValue, { allowZero = true } = {}) {
37
82
  const parsed = Number.parseInt(String(rawValue || ''), 10);
@@ -58,8 +103,8 @@ function clampScore(value, min, max) {
58
103
 
59
104
  function parseTaskSize(rawTaskSize) {
60
105
  const normalized = String(rawTaskSize || '').trim();
61
- if (!TASK_SIZE_VALUES.has(normalized)) {
62
- throw new Error(`--task-size must be one of: ${Array.from(TASK_SIZE_VALUES).join(', ')}`);
106
+ if (!TASK_SIZE_SET.has(normalized)) {
107
+ throw new Error(`--task-size must be one of: ${TASK_SIZE_VALUES.join(', ')}`);
63
108
  }
64
109
  return normalized;
65
110
  }
@@ -123,11 +168,7 @@ function scorePostProof(completionBeforeTail, override) {
123
168
  }
124
169
 
125
170
  function labelForTotal(total) {
126
- if (total <= 15) return 'Healthy';
127
- if (total <= 30) return 'Mildly fragmented';
128
- if (total <= 50) return 'Inefficient';
129
- if (total <= 75) return 'Runaway';
130
- return 'Catastrophic';
171
+ return LABEL_BANDS.find((band) => total <= band.max)?.label || LABEL_BANDS[LABEL_BANDS.length - 1].label;
131
172
  }
132
173
 
133
174
  function buildSessionSeverityReport(options) {
@@ -205,9 +246,37 @@ function renderSessionSeverityReport(report) {
205
246
  ].join('\n');
206
247
  }
207
248
 
249
+ function renderSessionSeverityHelpDetails() {
250
+ const taskSizeDefaults = TASK_SIZE_VALUES
251
+ .map((taskSize) => `${taskSize}=${formatInteger(TASK_SIZE_UPPER_BOUNDS[taskSize])}`)
252
+ .join(', ');
253
+ const labelBands = LABEL_BANDS
254
+ .map((band, index) => {
255
+ const min = index === 0 ? 0 : LABEL_BANDS[index - 1].max + 1;
256
+ return `${band.label}=${min}-${band.max}`;
257
+ })
258
+ .join(', ');
259
+ return [`Task-size defaults: ${taskSizeDefaults}`, `Label bands: ${labelBands}`].join('\n');
260
+ }
261
+
262
+ function renderSessionSeverityCommand(toolName) {
263
+ return `${toolName} report ${SESSION_SEVERITY_COMMAND_TAIL}`;
264
+ }
265
+
266
+ function renderSessionSeverityExample(toolName) {
267
+ return `${toolName} report ${SESSION_SEVERITY_EXAMPLE_TAIL}`;
268
+ }
269
+
208
270
  module.exports = {
271
+ LABEL_BANDS,
272
+ SESSION_SEVERITY_COMMAND_TAIL,
273
+ SESSION_SEVERITY_EXAMPLE_ARGS,
274
+ SESSION_SEVERITY_EXAMPLE_TAIL,
209
275
  TASK_SIZE_UPPER_BOUNDS,
210
276
  buildSessionSeverityReport,
211
277
  renderSessionSeverityReport,
278
+ renderSessionSeverityHelpDetails,
279
+ renderSessionSeverityCommand,
280
+ renderSessionSeverityExample,
212
281
  labelForTotal,
213
282
  };
@@ -21,8 +21,11 @@ Default: less word, same proof.
21
21
  - Front-load scaffold/path discovery into one grouped inspection pass. Avoid serial `ls` / `find` / `rg` / `cat` retries that only rediscover the same path state.
22
22
  - Treat repeated `write_stdin`, repeated `sed` / `cat` peeks, and tiny diagnostic follow-up checks as strong negative signals. If they appear alongside climbing input cost, stop the probe loop and batch the next phase.
23
23
  - Tool / hook summaries stay tiny: command, status, last meaningful lines only. Drop routine hook boilerplate.
24
+ - Keep raw terminal interaction out of long-lived context. For `write_stdin` or interactive babysitting, retain only process, action sent, current result, and next action.
25
+ - Keep execution log separate from reasoning context: full commands/stdout belong in logs, while prompt context keeps only the latest 1-2 checkpoints plus the newest tool-result summary.
24
26
  - Treat local edit/commit, remote publish/PR, CI diagnosis, and cleanup as bounded phases. Do not spend fresh narration or approval turns on obvious safe follow-ons inside an already authorized phase unless the risk changes.
25
27
  - When a session turns fragmented, collapse back to inspect once, patch once, verify once, and summarize once.
28
+ - Use a fixed checkpoint shape when compacting: `Task`, `Done`, `Current status`, and `Next`.
26
29
  - Keep `.omx/notepad.md` lean: live handoffs only. Use exactly `branch`, `task`, `blocker`, `next step`, and `evidence`; move narrative proof into OpenSpec artifacts, PRs, or command output.
27
30
 
28
31
  ## OMX Caveman Style
@@ -9,6 +9,7 @@ Use this skill when you only want to promote Codex skill file updates into the b
9
9
 
10
10
  ## What this merges
11
11
 
12
+ - `skills/**/SKILL.md`
12
13
  - `.codex/skills/**/SKILL.md`
13
14
  - `templates/codex/skills/**/SKILL.md`
14
15
 
@@ -33,7 +34,7 @@ gx branch start "merge-skill-files-to-${BASE_BRANCH}" "skill-merge" "$BASE_BRANC
33
34
 
34
35
  ```sh
35
36
  SOURCE_BRANCH="<agent-branch>"
36
- git checkout "$SOURCE_BRANCH" -- ':(glob).codex/skills/**/SKILL.md' ':(glob)templates/codex/skills/**/SKILL.md'
37
+ git checkout "$SOURCE_BRANCH" -- ':(glob)skills/**/SKILL.md' ':(glob).codex/skills/**/SKILL.md' ':(glob)templates/codex/skills/**/SKILL.md'
37
38
  ```
38
39
 
39
40
  5. Verify scope before commit:
@@ -46,7 +47,7 @@ git diff --name-only
46
47
  6. Commit and merge back to base using guardex finish flow:
47
48
 
48
49
  ```sh
49
- git add .codex/skills templates/codex/skills
50
+ git add skills .codex/skills templates/codex/skills
50
51
  git commit -m "Merge skill file updates into ${BASE_BRANCH}"
51
52
  gx branch finish --branch "$(git rev-parse --abbrev-ref HEAD)" --base "$BASE_BRANCH" --via-pr --wait-for-merge --cleanup
52
53
  ```