aiwcli 0.12.3 → 0.12.7

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 (125) hide show
  1. package/bin/dev.cmd +3 -3
  2. package/bin/dev.js +16 -16
  3. package/bin/run.cmd +3 -3
  4. package/bin/run.js +21 -21
  5. package/dist/commands/branch.js +7 -2
  6. package/dist/lib/bmad-installer.js +37 -37
  7. package/dist/lib/terminal.d.ts +2 -0
  8. package/dist/lib/terminal.js +57 -7
  9. package/dist/templates/CLAUDE.md +205 -205
  10. package/dist/templates/_shared/.claude/commands/handoff-resume.md +12 -64
  11. package/dist/templates/_shared/.claude/commands/handoff.md +12 -198
  12. package/dist/templates/_shared/.claude/settings.json +65 -65
  13. package/dist/templates/_shared/.codex/workflows/handoff.md +226 -226
  14. package/dist/templates/_shared/.windsurf/workflows/handoff.md +226 -226
  15. package/dist/templates/_shared/handoff-system/CLAUDE.md +421 -0
  16. package/dist/templates/_shared/{lib-ts/handoff → handoff-system/lib}/document-generator.ts +215 -216
  17. package/dist/templates/_shared/{lib-ts/handoff → handoff-system/lib}/handoff-reader.ts +157 -158
  18. package/dist/templates/_shared/{scripts → handoff-system/scripts}/resume_handoff.ts +373 -373
  19. package/dist/templates/_shared/{scripts → handoff-system/scripts}/save_handoff.ts +469 -358
  20. package/dist/templates/_shared/handoff-system/workflows/handoff-resume.md +66 -0
  21. package/dist/templates/_shared/{workflows → handoff-system/workflows}/handoff.md +254 -254
  22. package/dist/templates/_shared/hooks-ts/_utils/git-state.ts +2 -2
  23. package/dist/templates/_shared/hooks-ts/archive_plan.ts +159 -159
  24. package/dist/templates/_shared/hooks-ts/context_monitor.ts +147 -147
  25. package/dist/templates/_shared/hooks-ts/file-suggestion.ts +128 -128
  26. package/dist/templates/_shared/hooks-ts/pre_compact.ts +49 -49
  27. package/dist/templates/_shared/hooks-ts/session_end.ts +196 -183
  28. package/dist/templates/_shared/hooks-ts/session_start.ts +163 -151
  29. package/dist/templates/_shared/hooks-ts/task_create_capture.ts +48 -48
  30. package/dist/templates/_shared/hooks-ts/task_update_capture.ts +74 -74
  31. package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +93 -93
  32. package/dist/templates/_shared/lib-ts/CLAUDE.md +367 -367
  33. package/dist/templates/_shared/lib-ts/base/atomic-write.ts +138 -138
  34. package/dist/templates/_shared/lib-ts/base/constants.ts +303 -303
  35. package/dist/templates/_shared/lib-ts/base/git-state.ts +58 -58
  36. package/dist/templates/_shared/lib-ts/base/hook-utils.ts +582 -582
  37. package/dist/templates/_shared/lib-ts/base/inference.ts +301 -301
  38. package/dist/templates/_shared/lib-ts/base/logger.ts +247 -247
  39. package/dist/templates/_shared/lib-ts/base/state-io.ts +202 -130
  40. package/dist/templates/_shared/lib-ts/base/stop-words.ts +184 -184
  41. package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +56 -0
  42. package/dist/templates/_shared/lib-ts/base/utils.ts +184 -184
  43. package/dist/templates/_shared/lib-ts/context/context-formatter.ts +566 -560
  44. package/dist/templates/_shared/lib-ts/context/context-selector.ts +524 -515
  45. package/dist/templates/_shared/lib-ts/context/context-store.ts +712 -668
  46. package/dist/templates/_shared/lib-ts/context/plan-manager.ts +312 -312
  47. package/dist/templates/_shared/lib-ts/context/task-tracker.ts +185 -185
  48. package/dist/templates/_shared/lib-ts/package.json +20 -20
  49. package/dist/templates/_shared/lib-ts/templates/formatters.ts +102 -102
  50. package/dist/templates/_shared/lib-ts/templates/plan-context.ts +58 -58
  51. package/dist/templates/_shared/lib-ts/tsconfig.json +13 -13
  52. package/dist/templates/_shared/lib-ts/types.ts +186 -180
  53. package/dist/templates/_shared/scripts/resolve_context.ts +33 -33
  54. package/dist/templates/_shared/scripts/status_line.ts +690 -690
  55. package/dist/templates/cc-native/.claude/commands/{rlm → cc-native/rlm}/ask.md +136 -136
  56. package/dist/templates/cc-native/.claude/commands/{rlm → cc-native/rlm}/index.md +21 -21
  57. package/dist/templates/cc-native/.claude/commands/{rlm → cc-native/rlm}/overview.md +56 -56
  58. package/dist/templates/cc-native/.claude/commands/cc-native/specdev.md +10 -10
  59. package/dist/templates/cc-native/.windsurf/workflows/cc-native/fix.md +8 -8
  60. package/dist/templates/cc-native/.windsurf/workflows/cc-native/implement.md +8 -8
  61. package/dist/templates/cc-native/.windsurf/workflows/cc-native/research.md +8 -8
  62. package/dist/templates/cc-native/CC-NATIVE-README.md +189 -189
  63. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +304 -304
  64. package/dist/templates/cc-native/_cc-native/agents/CLAUDE.md +143 -143
  65. package/dist/templates/cc-native/_cc-native/agents/PLAN-ORCHESTRATOR.md +213 -213
  66. package/dist/templates/cc-native/_cc-native/agents/plan-questions/PLAN-QUESTIONER.md +70 -70
  67. package/dist/templates/cc-native/_cc-native/cc-native.config.json +96 -96
  68. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +247 -247
  69. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +76 -76
  70. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_subagent.ts +54 -54
  71. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +51 -51
  72. package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +53 -53
  73. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +61 -61
  74. package/dist/templates/cc-native/_cc-native/lib-ts/agent-selection.ts +163 -163
  75. package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +156 -156
  76. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts/format.ts +597 -597
  77. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts/index.ts +26 -26
  78. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts/tracker.ts +107 -107
  79. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts/write.ts +119 -119
  80. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +21 -21
  81. package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +319 -319
  82. package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +144 -144
  83. package/dist/templates/cc-native/_cc-native/lib-ts/config.ts +57 -57
  84. package/dist/templates/cc-native/_cc-native/lib-ts/constants.ts +83 -83
  85. package/dist/templates/cc-native/_cc-native/lib-ts/corroboration.ts +119 -119
  86. package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +79 -79
  87. package/dist/templates/cc-native/_cc-native/lib-ts/graduation.ts +132 -132
  88. package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +116 -116
  89. package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +168 -168
  90. package/dist/templates/cc-native/_cc-native/lib-ts/orchestrator.ts +70 -70
  91. package/dist/templates/cc-native/_cc-native/lib-ts/output-builder.ts +130 -130
  92. package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +80 -80
  93. package/dist/templates/cc-native/_cc-native/lib-ts/plan-enhancement.ts +41 -41
  94. package/dist/templates/cc-native/_cc-native/lib-ts/plan-questions.ts +101 -101
  95. package/dist/templates/cc-native/_cc-native/lib-ts/review-pipeline.ts +511 -511
  96. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/agent.ts +71 -71
  97. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/base/base-agent.ts +217 -217
  98. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/index.ts +12 -12
  99. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/claude-agent.ts +66 -65
  100. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/codex-agent.ts +184 -184
  101. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/gemini-agent.ts +39 -39
  102. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/orchestrator-claude-agent.ts +196 -195
  103. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/schemas.ts +201 -201
  104. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/types.ts +21 -21
  105. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/CLAUDE.md +480 -480
  106. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/embedding-indexer.ts +287 -287
  107. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/hyde.ts +148 -148
  108. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/index.ts +54 -54
  109. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +58 -58
  110. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/ollama-client.ts +208 -208
  111. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +460 -460
  112. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-indexer.ts +446 -447
  113. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-loader.ts +280 -280
  114. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-searcher.ts +274 -274
  115. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +201 -201
  116. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/vector-store.ts +278 -278
  117. package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +184 -184
  118. package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +275 -275
  119. package/dist/templates/cc-native/_cc-native/lib-ts/tsconfig.json +18 -18
  120. package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +329 -329
  121. package/dist/templates/cc-native/_cc-native/lib-ts/verdict.ts +72 -72
  122. package/dist/templates/cc-native/_cc-native/workflows/specdev.md +9 -9
  123. package/oclif.manifest.json +1 -1
  124. package/package.json +108 -108
  125. package/dist/templates/cc-native/_cc-native/lib-ts/nul +0 -3
@@ -1,119 +1,119 @@
1
- /**
2
- * Corroboration-based verdict computation for plan review.
3
- *
4
- * Replaces the old per-verdict aggregation with proportional thresholding:
5
- * high-severity issues in a dimension only block when the total count
6
- * exceeds 2× the number of distinct agents contributing to that dimension.
7
- *
8
- * **Why proportional thresholding:**
9
- * The agent pool has dimensional imbalance (e.g., 10 completeness agents vs
10
- * 1 maintainability agent). A fixed "2+ agents agree = block" would mean
11
- * any 2 completeness agents always block. Proportional scaling (issues > 2×agents)
12
- * sets a fair bar regardless of how many agents focus on each dimension.
13
- *
14
- * **Convergence problem this solves:**
15
- * Agents with opposing philosophies (simplicity-guardian vs completeness-gaps)
16
- * produce contradictory high-severity issues. Because the old system treated
17
- * every agent's finding as independently authoritative, plans oscillated —
18
- * addressing one agent's feedback triggered the opposing agent.
19
- *
20
- * **Revert path:** Change one line in cc-native-plan-review.ts back to
21
- * `computeReviewDecision(allVerdicts)`. Old function kept in verdict.ts.
22
- */
23
-
24
- import type {
25
- ReviewerResult,
26
- ReviewIssue,
27
- IssueDimension,
28
- CorroborationResult,
29
- CorroboratedGroup,
30
- SoloFinding,
31
- } from "./types.js";
32
-
33
- /**
34
- * Compute a corroboration-based review decision from all reviewer results.
35
- *
36
- * Algorithm:
37
- * 1. Collect all high-severity issues with a `dimension` field
38
- * 2. Group by dimension, tracking distinct agent names per group
39
- * 3. For each dimension: block if `issues.length > 2 × agentCount`
40
- * 4. Issues without `dimension` are unclassified (never block)
41
- * 5. Non-high issues are ignored (informational only)
42
- *
43
- * @param allResults - Map of reviewer name → ReviewerResult (CLI + agent)
44
- * @returns CorroborationResult with blocking groups, solo findings, and verdict
45
- */
46
- export function computeCorroboratedDecision(
47
- allResults: Record<string, ReviewerResult>,
48
- ): CorroborationResult {
49
- // Accumulator: dimension → { issues, agentNames }
50
- const dimMap = new Map<
51
- IssueDimension,
52
- {
53
- issues: Array<{ agent: string; issue: ReviewIssue }>;
54
- agentNames: Set<string>;
55
- }
56
- >();
57
-
58
- const unclassified: Array<{ agent: string; issue: ReviewIssue }> = [];
59
-
60
- for (const [agentName, result] of Object.entries(allResults)) {
61
- if (!result.data) continue;
62
- const issues = result.data.issues as ReviewIssue[] | undefined;
63
- if (!Array.isArray(issues)) continue;
64
-
65
- for (const issue of issues) {
66
- // Only high-severity issues participate in corroboration
67
- if (issue.severity !== "high") continue;
68
-
69
- // Issues without dimension are unclassified — cannot block
70
- if (!issue.dimension) {
71
- unclassified.push({ agent: agentName, issue });
72
- continue;
73
- }
74
-
75
- let group = dimMap.get(issue.dimension);
76
- if (!group) {
77
- group = { issues: [], agentNames: new Set() };
78
- dimMap.set(issue.dimension, group);
79
- }
80
- group.issues.push({ agent: agentName, issue });
81
- group.agentNames.add(agentName);
82
- }
83
- }
84
-
85
- const blocking: CorroboratedGroup[] = [];
86
- const solo: SoloFinding[] = [];
87
-
88
- for (const [dimension, group] of dimMap) {
89
- const agentCount = group.agentNames.size;
90
- const threshold = 2 * agentCount;
91
-
92
- if (group.issues.length >= threshold) {
93
- blocking.push({
94
- dimension,
95
- issues: group.issues,
96
- agentCount,
97
- threshold,
98
- });
99
- } else {
100
- solo.push({
101
- dimension,
102
- issues: group.issues,
103
- agentCount,
104
- threshold,
105
- });
106
- }
107
- }
108
-
109
- return {
110
- blocking,
111
- solo,
112
- unclassified,
113
- verdict: blocking.length > 0
114
- ? "fail"
115
- : solo.length > 0
116
- ? "warn"
117
- : "pass",
118
- };
119
- }
1
+ /**
2
+ * Corroboration-based verdict computation for plan review.
3
+ *
4
+ * Replaces the old per-verdict aggregation with proportional thresholding:
5
+ * high-severity issues in a dimension only block when the total count
6
+ * exceeds 2× the number of distinct agents contributing to that dimension.
7
+ *
8
+ * **Why proportional thresholding:**
9
+ * The agent pool has dimensional imbalance (e.g., 10 completeness agents vs
10
+ * 1 maintainability agent). A fixed "2+ agents agree = block" would mean
11
+ * any 2 completeness agents always block. Proportional scaling (issues > 2×agents)
12
+ * sets a fair bar regardless of how many agents focus on each dimension.
13
+ *
14
+ * **Convergence problem this solves:**
15
+ * Agents with opposing philosophies (simplicity-guardian vs completeness-gaps)
16
+ * produce contradictory high-severity issues. Because the old system treated
17
+ * every agent's finding as independently authoritative, plans oscillated —
18
+ * addressing one agent's feedback triggered the opposing agent.
19
+ *
20
+ * **Revert path:** Change one line in cc-native-plan-review.ts back to
21
+ * `computeReviewDecision(allVerdicts)`. Old function kept in verdict.ts.
22
+ */
23
+
24
+ import type {
25
+ ReviewerResult,
26
+ ReviewIssue,
27
+ IssueDimension,
28
+ CorroborationResult,
29
+ CorroboratedGroup,
30
+ SoloFinding,
31
+ } from "./types.js";
32
+
33
+ /**
34
+ * Compute a corroboration-based review decision from all reviewer results.
35
+ *
36
+ * Algorithm:
37
+ * 1. Collect all high-severity issues with a `dimension` field
38
+ * 2. Group by dimension, tracking distinct agent names per group
39
+ * 3. For each dimension: block if `issues.length > 2 × agentCount`
40
+ * 4. Issues without `dimension` are unclassified (never block)
41
+ * 5. Non-high issues are ignored (informational only)
42
+ *
43
+ * @param allResults - Map of reviewer name → ReviewerResult (CLI + agent)
44
+ * @returns CorroborationResult with blocking groups, solo findings, and verdict
45
+ */
46
+ export function computeCorroboratedDecision(
47
+ allResults: Record<string, ReviewerResult>,
48
+ ): CorroborationResult {
49
+ // Accumulator: dimension → { issues, agentNames }
50
+ const dimMap = new Map<
51
+ IssueDimension,
52
+ {
53
+ issues: Array<{ agent: string; issue: ReviewIssue }>;
54
+ agentNames: Set<string>;
55
+ }
56
+ >();
57
+
58
+ const unclassified: Array<{ agent: string; issue: ReviewIssue }> = [];
59
+
60
+ for (const [agentName, result] of Object.entries(allResults)) {
61
+ if (!result.data) continue;
62
+ const issues = result.data.issues as ReviewIssue[] | undefined;
63
+ if (!Array.isArray(issues)) continue;
64
+
65
+ for (const issue of issues) {
66
+ // Only high-severity issues participate in corroboration
67
+ if (issue.severity !== "high") continue;
68
+
69
+ // Issues without dimension are unclassified — cannot block
70
+ if (!issue.dimension) {
71
+ unclassified.push({ agent: agentName, issue });
72
+ continue;
73
+ }
74
+
75
+ let group = dimMap.get(issue.dimension);
76
+ if (!group) {
77
+ group = { issues: [], agentNames: new Set() };
78
+ dimMap.set(issue.dimension, group);
79
+ }
80
+ group.issues.push({ agent: agentName, issue });
81
+ group.agentNames.add(agentName);
82
+ }
83
+ }
84
+
85
+ const blocking: CorroboratedGroup[] = [];
86
+ const solo: SoloFinding[] = [];
87
+
88
+ for (const [dimension, group] of dimMap) {
89
+ const agentCount = group.agentNames.size;
90
+ const threshold = 2 * agentCount;
91
+
92
+ if (group.issues.length >= threshold) {
93
+ blocking.push({
94
+ dimension,
95
+ issues: group.issues,
96
+ agentCount,
97
+ threshold,
98
+ });
99
+ } else {
100
+ solo.push({
101
+ dimension,
102
+ issues: group.issues,
103
+ agentCount,
104
+ threshold,
105
+ });
106
+ }
107
+ }
108
+
109
+ return {
110
+ blocking,
111
+ solo,
112
+ unclassified,
113
+ verdict: blocking.length > 0
114
+ ? "fail"
115
+ : solo.length > 0
116
+ ? "warn"
117
+ : "pass",
118
+ };
119
+ }
@@ -1,80 +1,80 @@
1
- /**
2
- * Per-context debug logging for cc-native hooks.
3
- * Thin delegation layer over the unified logger.
4
- * See cc-native-plan-review-spec.md §4.13
5
- *
6
- * Can be disabled via CCNATIVE_DEBUG_DISABLE=1 environment variable.
7
- */
8
-
9
- import * as fs from "node:fs";
1
+ /**
2
+ * Per-context debug logging for cc-native hooks.
3
+ * Thin delegation layer over the unified logger.
4
+ * See cc-native-plan-review-spec.md §4.13
5
+ *
6
+ * Can be disabled via CCNATIVE_DEBUG_DISABLE=1 environment variable.
7
+ */
8
+
9
+ import * as fs from "node:fs";
10
10
  import * as path from "node:path";
11
-
12
- import { hookLog } from "../../_shared/lib-ts/base/logger.js";
13
-
14
- /** Feature flag — set CCNATIVE_DEBUG_DISABLE=1 to turn off */
15
- const DEBUG_ENABLED = !["1", "true", "yes"].includes(
16
- (process.env.CCNATIVE_DEBUG_DISABLE ?? "").toLowerCase(),
17
- );
18
-
19
- /**
20
- * Get or create debug directory within context folder.
21
- */
22
- export function getDebugDir(contextPath: string): string {
23
- const debugDir = path.join(contextPath, "debug");
24
- fs.mkdirSync(debugDir, { recursive: true });
25
- return debugDir;
26
- }
27
-
28
- /**
29
- * Write a debug log entry. Delegates to unified logger.
30
- */
31
- export function debugLog(
32
- contextPath: string,
33
- sessionName: string,
34
- component: string,
35
- message: string,
36
- data?: unknown,
37
- ): void {
38
- if (!DEBUG_ENABLED) return;
39
-
40
- hookLog("debug", sessionName, message, {
41
- component,
42
- data,
43
- });
44
- }
45
-
46
- /**
47
- * Log raw output (stdout, stderr, etc). Delegates to unified logger.
48
- */
49
- export function debugRaw(
50
- contextPath: string,
51
- sessionName: string,
52
- component: string,
53
- label: string,
54
- raw: string,
55
- maxLen = 10_000,
56
- ): void {
57
- if (!DEBUG_ENABLED) return;
58
-
59
- const truncated = raw.length > maxLen ? raw.slice(0, maxLen) : raw;
60
- const suffix =
61
- raw.length > maxLen ? ` [TRUNCATED from ${raw.length} chars]` : "";
62
-
63
- hookLog("debug", sessionName, `${label}${suffix}: ${truncated}`, {
64
- component,
65
- });
66
- }
67
-
68
- /**
69
- * Remove debug folder during context archive.
70
- */
71
- export function cleanupDebugFolder(contextPath: string): void {
72
- try {
73
- const debugDir = path.join(contextPath, "debug");
74
- if (fs.existsSync(debugDir)) {
75
- fs.rmSync(debugDir, { recursive: true, force: true });
76
- }
77
- } catch {
78
- // Best effort cleanup
79
- }
80
- }
11
+
12
+ import { hookLog } from "../../_shared/lib-ts/base/logger.js";
13
+
14
+ /** Feature flag — set CCNATIVE_DEBUG_DISABLE=1 to turn off */
15
+ const DEBUG_ENABLED = !["1", "true", "yes"].includes(
16
+ (process.env.CCNATIVE_DEBUG_DISABLE ?? "").toLowerCase(),
17
+ );
18
+
19
+ /**
20
+ * Get or create debug directory within context folder.
21
+ */
22
+ export function getDebugDir(contextPath: string): string {
23
+ const debugDir = path.join(contextPath, "debug");
24
+ fs.mkdirSync(debugDir, { recursive: true });
25
+ return debugDir;
26
+ }
27
+
28
+ /**
29
+ * Write a debug log entry. Delegates to unified logger.
30
+ */
31
+ export function debugLog(
32
+ contextPath: string,
33
+ sessionName: string,
34
+ component: string,
35
+ message: string,
36
+ data?: unknown,
37
+ ): void {
38
+ if (!DEBUG_ENABLED) return;
39
+
40
+ hookLog("debug", sessionName, message, {
41
+ component,
42
+ data,
43
+ });
44
+ }
45
+
46
+ /**
47
+ * Log raw output (stdout, stderr, etc). Delegates to unified logger.
48
+ */
49
+ export function debugRaw(
50
+ contextPath: string,
51
+ sessionName: string,
52
+ component: string,
53
+ label: string,
54
+ raw: string,
55
+ maxLen = 10_000,
56
+ ): void {
57
+ if (!DEBUG_ENABLED) return;
58
+
59
+ const truncated = raw.length > maxLen ? raw.slice(0, maxLen) : raw;
60
+ const suffix =
61
+ raw.length > maxLen ? ` [TRUNCATED from ${raw.length} chars]` : "";
62
+
63
+ hookLog("debug", sessionName, `${label}${suffix}: ${truncated}`, {
64
+ component,
65
+ });
66
+ }
67
+
68
+ /**
69
+ * Remove debug folder during context archive.
70
+ */
71
+ export function cleanupDebugFolder(contextPath: string): void {
72
+ try {
73
+ const debugDir = path.join(contextPath, "debug");
74
+ if (fs.existsSync(debugDir)) {
75
+ fs.rmSync(debugDir, { recursive: true, force: true });
76
+ }
77
+ } catch {
78
+ // Best effort cleanup
79
+ }
80
+ }
@@ -1,132 +1,132 @@
1
- /**
2
- * Graduation logic: pass eligibility, pass streaks, graduation threshold, iteration advancement.
3
- * Extracted from cc-native-plan-review.ts.
4
- */
5
-
6
- import type {
7
- IterationState,
8
- ReviewerResult,
9
- CombinedReviewResult,
10
- IterationAdvancement,
11
- } from "./types.js";
12
-
13
- // ---------------------------------------------------------------------------
14
- // Pass Eligibility
15
- // ---------------------------------------------------------------------------
16
-
17
- /**
18
- * Determine which agents are pass-eligible this iteration.
19
- * Criteria: verdict === "pass" OR zero high-severity issues.
20
- * Agents with "skip"/"error" are NOT eligible (no signal).
21
- */
22
- export function computePassEligible(agentResults: Record<string, ReviewerResult>): string[] {
23
- const eligible: string[] = [];
24
- for (const [name, result] of Object.entries(agentResults)) {
25
- if (result.verdict === "skip" || result.verdict === "error") continue;
26
- if (result.verdict === "pass") { eligible.push(name); continue; }
27
- const issues = Array.isArray(result.data?.issues)
28
- ? (result.data.issues as Array<{ severity?: string }>) : [];
29
- if (issues.filter(i => i.severity === "high").length === 0) {
30
- eligible.push(name);
31
- }
32
- }
33
- return eligible;
34
- }
35
-
36
- // ---------------------------------------------------------------------------
37
- // Tracker Issue Extraction
38
- // ---------------------------------------------------------------------------
39
-
40
- /**
41
- * Extract top high-severity issues for the review tracker.
42
- */
43
- export function extractTopIssuesForTracker(
44
- combined: CombinedReviewResult,
45
- maxCount = 5,
46
- ): string[] {
47
- const allReviewers = Object.values(combined.agents);
48
- const issues: string[] = [];
49
- for (const r of allReviewers) {
50
- if (!r.data) continue;
51
- const issueList = r.data.issues as Array<Record<string, unknown>> | undefined;
52
- if (!issueList) continue;
53
- for (const issue of issueList) {
54
- if (issue.severity === "high") {
55
- const text = String(issue.issue ?? "").trim();
56
- if (text) {
57
- issues.push(`[${r.name}] ${text}`);
58
- }
59
- }
60
- }
61
- if (issues.length >= maxCount) break;
62
- }
63
- return issues.slice(0, maxCount);
64
- }
65
-
66
- // ---------------------------------------------------------------------------
67
- // Iteration Advancement
68
- // ---------------------------------------------------------------------------
69
-
70
- const GRADUATION_THRESHOLD = 2;
71
-
72
- /**
73
- * Advance iteration state after a review cycle. Returns a new state copy
74
- * (does not mutate input).
75
- *
76
- * - On pass/warrant: sets current past max (stop iterating)
77
- * - On deny: increments current toward max (safety valve)
78
- * - Updates pass streaks and graduates agents that reached threshold
79
- */
80
- export function advanceIterationState(
81
- state: IterationState,
82
- planHash: string,
83
- planPath: string,
84
- verdict: string,
85
- shouldDeny: boolean,
86
- passEligible: string[],
87
- agentResults: Record<string, ReviewerResult>,
88
- graduationThreshold = GRADUATION_THRESHOLD,
89
- ): IterationAdvancement {
90
- const updated: IterationState = {
91
- ...state,
92
- history: [...state.history, { hash: planHash, verdict, timestamp: new Date().toISOString() }],
93
- lastPlanHash: planHash,
94
- lastPlanPath: planPath,
95
- graduated: [...state.graduated],
96
- passStreaks: { ...(state.passStreaks ?? {}) },
97
- };
98
-
99
- if (!shouldDeny) {
100
- // Pass/warrant: stop iterating
101
- updated.current = updated.max + 1;
102
- } else {
103
- // Deny: advance toward max
104
- updated.current = state.current + 1;
105
- }
106
-
107
- // Update pass streaks — only for agents that actually ran this iteration
108
- const passEligibleSet = new Set(passEligible);
109
- const graduatedSet = new Set(updated.graduated);
110
-
111
- for (const name of Object.keys(agentResults)) {
112
- if (graduatedSet.has(name)) continue;
113
- if (passEligibleSet.has(name)) {
114
- updated.passStreaks[name] = (updated.passStreaks[name] ?? 0) + 1;
115
- } else {
116
- updated.passStreaks[name] = 0;
117
- }
118
- }
119
-
120
- // Graduate agents that reached threshold
121
- const newGraduates: string[] = [];
122
- for (const [name, streak] of Object.entries(updated.passStreaks)) {
123
- if (streak >= graduationThreshold && !graduatedSet.has(name)) {
124
- newGraduates.push(name);
125
- }
126
- }
127
- if (newGraduates.length > 0) {
128
- updated.graduated = [...updated.graduated, ...newGraduates];
129
- }
130
-
131
- return { updatedState: updated, newGraduates };
132
- }
1
+ /**
2
+ * Graduation logic: pass eligibility, pass streaks, graduation threshold, iteration advancement.
3
+ * Extracted from cc-native-plan-review.ts.
4
+ */
5
+
6
+ import type {
7
+ IterationState,
8
+ ReviewerResult,
9
+ CombinedReviewResult,
10
+ IterationAdvancement,
11
+ } from "./types.js";
12
+
13
+ // ---------------------------------------------------------------------------
14
+ // Pass Eligibility
15
+ // ---------------------------------------------------------------------------
16
+
17
+ /**
18
+ * Determine which agents are pass-eligible this iteration.
19
+ * Criteria: verdict === "pass" OR zero high-severity issues.
20
+ * Agents with "skip"/"error" are NOT eligible (no signal).
21
+ */
22
+ export function computePassEligible(agentResults: Record<string, ReviewerResult>): string[] {
23
+ const eligible: string[] = [];
24
+ for (const [name, result] of Object.entries(agentResults)) {
25
+ if (result.verdict === "skip" || result.verdict === "error") continue;
26
+ if (result.verdict === "pass") { eligible.push(name); continue; }
27
+ const issues = Array.isArray(result.data?.issues)
28
+ ? (result.data.issues as Array<{ severity?: string }>) : [];
29
+ if (issues.filter(i => i.severity === "high").length === 0) {
30
+ eligible.push(name);
31
+ }
32
+ }
33
+ return eligible;
34
+ }
35
+
36
+ // ---------------------------------------------------------------------------
37
+ // Tracker Issue Extraction
38
+ // ---------------------------------------------------------------------------
39
+
40
+ /**
41
+ * Extract top high-severity issues for the review tracker.
42
+ */
43
+ export function extractTopIssuesForTracker(
44
+ combined: CombinedReviewResult,
45
+ maxCount = 5,
46
+ ): string[] {
47
+ const allReviewers = Object.values(combined.agents);
48
+ const issues: string[] = [];
49
+ for (const r of allReviewers) {
50
+ if (!r.data) continue;
51
+ const issueList = r.data.issues as Array<Record<string, unknown>> | undefined;
52
+ if (!issueList) continue;
53
+ for (const issue of issueList) {
54
+ if (issue.severity === "high") {
55
+ const text = String(issue.issue ?? "").trim();
56
+ if (text) {
57
+ issues.push(`[${r.name}] ${text}`);
58
+ }
59
+ }
60
+ }
61
+ if (issues.length >= maxCount) break;
62
+ }
63
+ return issues.slice(0, maxCount);
64
+ }
65
+
66
+ // ---------------------------------------------------------------------------
67
+ // Iteration Advancement
68
+ // ---------------------------------------------------------------------------
69
+
70
+ const GRADUATION_THRESHOLD = 2;
71
+
72
+ /**
73
+ * Advance iteration state after a review cycle. Returns a new state copy
74
+ * (does not mutate input).
75
+ *
76
+ * - On pass/warrant: sets current past max (stop iterating)
77
+ * - On deny: increments current toward max (safety valve)
78
+ * - Updates pass streaks and graduates agents that reached threshold
79
+ */
80
+ export function advanceIterationState(
81
+ state: IterationState,
82
+ planHash: string,
83
+ planPath: string,
84
+ verdict: string,
85
+ shouldDeny: boolean,
86
+ passEligible: string[],
87
+ agentResults: Record<string, ReviewerResult>,
88
+ graduationThreshold = GRADUATION_THRESHOLD,
89
+ ): IterationAdvancement {
90
+ const updated: IterationState = {
91
+ ...state,
92
+ history: [...state.history, { hash: planHash, verdict, timestamp: new Date().toISOString() }],
93
+ lastPlanHash: planHash,
94
+ lastPlanPath: planPath,
95
+ graduated: [...state.graduated],
96
+ passStreaks: { ...(state.passStreaks ?? {}) },
97
+ };
98
+
99
+ if (!shouldDeny) {
100
+ // Pass/warrant: stop iterating
101
+ updated.current = updated.max + 1;
102
+ } else {
103
+ // Deny: advance toward max
104
+ updated.current = state.current + 1;
105
+ }
106
+
107
+ // Update pass streaks — only for agents that actually ran this iteration
108
+ const passEligibleSet = new Set(passEligible);
109
+ const graduatedSet = new Set(updated.graduated);
110
+
111
+ for (const name of Object.keys(agentResults)) {
112
+ if (graduatedSet.has(name)) continue;
113
+ if (passEligibleSet.has(name)) {
114
+ updated.passStreaks[name] = (updated.passStreaks[name] ?? 0) + 1;
115
+ } else {
116
+ updated.passStreaks[name] = 0;
117
+ }
118
+ }
119
+
120
+ // Graduate agents that reached threshold
121
+ const newGraduates: string[] = [];
122
+ for (const [name, streak] of Object.entries(updated.passStreaks)) {
123
+ if (streak >= graduationThreshold && !graduatedSet.has(name)) {
124
+ newGraduates.push(name);
125
+ }
126
+ }
127
+ if (newGraduates.length > 0) {
128
+ updated.graduated = [...updated.graduated, ...newGraduates];
129
+ }
130
+
131
+ return { updatedState: updated, newGraduates };
132
+ }