aiwcli 0.12.8 → 0.13.1
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/commands/clean.d.ts +7 -0
- package/dist/commands/clean.js +17 -8
- package/dist/commands/clear.d.ts +85 -0
- package/dist/commands/clear.js +455 -347
- package/dist/commands/init/index.d.ts +15 -0
- package/dist/commands/init/index.js +79 -38
- package/dist/lib/gitignore-manager.js +12 -13
- package/dist/lib/settings-hierarchy.d.ts +13 -1
- package/dist/lib/settings-hierarchy.js +1 -1
- package/dist/lib/template-linter.d.ts +4 -0
- package/dist/lib/template-linter.js +1 -1
- package/dist/lib/tty-detection.d.ts +1 -0
- package/dist/lib/tty-detection.js +1 -0
- package/dist/templates/CLAUDE.md +1 -1
- package/dist/templates/_shared/.claude/settings.json +64 -9
- package/dist/templates/_shared/.claude/skills/handoff/SKILL.md +1 -1
- package/dist/templates/_shared/.claude/skills/handoff-resume/SKILL.md +1 -1
- package/dist/templates/_shared/.claude/skills/meta-plan/SKILL.md +43 -0
- package/dist/templates/_shared/.codex/workflows/handoff.md +1 -1
- package/dist/templates/_shared/.codex/workflows/meta-plan.md +347 -0
- package/dist/templates/_shared/.windsurf/workflows/handoff.md +4 -221
- package/dist/templates/_shared/.windsurf/workflows/meta-plan.md +11 -0
- package/dist/templates/_shared/hooks-ts/context_monitor.ts +2 -2
- package/dist/templates/_shared/hooks-ts/lint_after_edit.ts +59 -0
- package/dist/templates/_shared/hooks-ts/session_end.ts +11 -10
- package/dist/templates/_shared/hooks-ts/session_start.ts +15 -12
- package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +12 -12
- package/dist/templates/_shared/lib-ts/CLAUDE.md +27 -2
- package/dist/templates/_shared/lib-ts/base/hook-utils.ts +26 -7
- package/dist/templates/_shared/lib-ts/base/inference.ts +16 -16
- package/dist/templates/_shared/lib-ts/base/lint-dispatch.ts +339 -0
- package/dist/templates/_shared/lib-ts/base/state-io.ts +4 -3
- package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +3 -3
- package/dist/templates/_shared/lib-ts/context/context-formatter.ts +16 -15
- package/dist/templates/_shared/lib-ts/context/context-selector.ts +16 -16
- package/dist/templates/_shared/lib-ts/context/context-store.ts +15 -14
- package/dist/templates/_shared/lib-ts/context/plan-manager.ts +2 -2
- package/dist/templates/_shared/scripts/resolve-run.ts +62 -0
- package/dist/templates/_shared/scripts/resolve_context.ts +1 -1
- package/dist/templates/_shared/scripts/status_line.ts +74 -65
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/CLAUDE.md +14 -14
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/lib/document-generator.ts +10 -9
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/lib/handoff-reader.ts +5 -4
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/scripts/resume_handoff.ts +6 -6
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/scripts/save_handoff.ts +19 -20
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/workflows/handoff-resume.md +2 -2
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/workflows/handoff.md +5 -5
- package/dist/templates/_shared/skills/meta-plan/CLAUDE.md +46 -0
- package/dist/templates/_shared/skills/meta-plan/workflows/meta-plan.md +277 -0
- package/dist/templates/cc-native/.claude/settings.json +13 -111
- package/dist/templates/cc-native/_cc-native/artifacts/lib/format.ts +22 -20
- package/dist/templates/cc-native/_cc-native/artifacts/lib/index.ts +11 -11
- package/dist/templates/cc-native/_cc-native/artifacts/lib/tracker.ts +7 -6
- package/dist/templates/cc-native/_cc-native/artifacts/lib/write.ts +17 -16
- package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +32 -2
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +9 -7
- package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +25 -0
- package/dist/templates/cc-native/_cc-native/hooks/validate_task_prompt.ts +2 -2
- package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +15 -16
- package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +19 -19
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +3 -3
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-enhancement.ts +6 -1
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/embedding-indexer.ts +16 -12
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/hyde.ts +2 -3
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/index.ts +31 -31
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +7 -6
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/ollama-client.ts +9 -7
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +17 -14
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-indexer.ts +41 -37
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-loader.ts +43 -33
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-searcher.ts +20 -20
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +9 -8
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/vector-store.ts +4 -3
- package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +8 -9
- package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +20 -19
- package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +1 -1
- package/dist/templates/cc-native/_cc-native/plan-review/CLAUDE.md +1 -0
- package/dist/templates/cc-native/_cc-native/plan-review/CODING-STANDARDS-CHECKLIST.md +75 -0
- package/dist/templates/cc-native/_cc-native/plan-review/lib/agent-selection.ts +2 -3
- package/dist/templates/cc-native/_cc-native/plan-review/lib/corroboration.ts +69 -16
- package/dist/templates/cc-native/_cc-native/plan-review/lib/graduation.ts +1 -1
- package/dist/templates/cc-native/_cc-native/plan-review/lib/orchestrator.ts +1 -1
- package/dist/templates/cc-native/_cc-native/plan-review/lib/output-builder.ts +12 -21
- package/dist/templates/cc-native/_cc-native/plan-review/lib/plan-questions.ts +3 -4
- package/dist/templates/cc-native/_cc-native/plan-review/lib/review-pipeline.ts +35 -39
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/agent.ts +2 -3
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/codex-agent.ts +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +6 -5
|
@@ -273,7 +273,7 @@ export interface Reviewer {
|
|
|
273
273
|
// JSON Schemas (moved to reviewers/schemas.ts)
|
|
274
274
|
// ---------------------------------------------------------------------------
|
|
275
275
|
// Re-export for backwards compatibility
|
|
276
|
-
export {
|
|
276
|
+
export { AGENT_REVIEW_PROMPT_PREFIX, ORCHESTRATOR_SCHEMA, REVIEW_PROMPT_PREFIX, REVIEW_SCHEMA } from "../plan-review/lib/reviewers/schemas.js";
|
|
277
277
|
|
|
278
278
|
// ---------------------------------------------------------------------------
|
|
279
279
|
// Display Defaults
|
|
@@ -13,6 +13,7 @@ When a Claude Code agent exits plan mode (`ExitPlanMode`), the plan review hook
|
|
|
13
13
|
```
|
|
14
14
|
plan-review/
|
|
15
15
|
├── CLAUDE.md ← This file
|
|
16
|
+
├── CODING-STANDARDS-CHECKLIST.md ← Standards injected during plan mode via plan_questions_early.ts
|
|
16
17
|
├── agents/
|
|
17
18
|
│ ├── CLAUDE.md ← Agent file format, frontmatter fields, selection rules
|
|
18
19
|
│ ├── PLAN-ORCHESTRATOR.md ← Orchestrator agent (complexity analysis)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Coding Standards Checklist
|
|
2
|
+
|
|
3
|
+
Standards that address the most common plan review failure modes. Reference this
|
|
4
|
+
when planning code changes in established codebases.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Test-First Design Thinking
|
|
9
|
+
|
|
10
|
+
Tests are an architectural constraint, not an afterthought. Design from the test
|
|
11
|
+
perspective first.
|
|
12
|
+
|
|
13
|
+
- **Interface-first:** Before describing implementation, ask: "Can I write the test
|
|
14
|
+
for this before the implementation exists?" If the answer is unclear, the interface
|
|
15
|
+
needs more thought.
|
|
16
|
+
- **Structure tests before code:** Plans that describe "implement then test" consistently
|
|
17
|
+
fail review. Restructure: define what the tests assert, then describe the implementation
|
|
18
|
+
that satisfies them.
|
|
19
|
+
- **Testability as architecture:** Design for dependency injection, interface seams, and
|
|
20
|
+
fakes. If a component can't be tested in isolation, the coupling is too tight.
|
|
21
|
+
- **Test categories:** Consider which test types apply — unit (isolated logic), integration
|
|
22
|
+
(module boundaries), contract (API surfaces), and characterization (existing behavior
|
|
23
|
+
preservation during refactoring).
|
|
24
|
+
- **Verification clarity:** Each planned change should have a corresponding verification
|
|
25
|
+
step that is binary-testable (pass/fail in one check, no subjective judgment).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 2. File Structure & Codebase Convention Fit
|
|
30
|
+
|
|
31
|
+
Don't pick a "plausible" location — pick the location that matches the project's
|
|
32
|
+
established patterns.
|
|
33
|
+
|
|
34
|
+
- **Discover before proposing:** Before suggesting new files or directories, verify where
|
|
35
|
+
similar things already live in this project. Use Glob/Grep to find existing patterns.
|
|
36
|
+
- **Naming conventions:** Match existing module and file naming patterns. If the project
|
|
37
|
+
uses `kebab-case.ts`, don't introduce `camelCase.ts`. If hooks live in `hooks/`, don't
|
|
38
|
+
create a `hook-handlers/` directory.
|
|
39
|
+
- **Co-location patterns:** Check if the project follows co-location (tests next to source,
|
|
40
|
+
types with implementation) or separation (dedicated `__tests__/`, `types/` directories).
|
|
41
|
+
Follow what exists.
|
|
42
|
+
- **Import depth:** Verify that new files fit the existing import hierarchy. Adding a file
|
|
43
|
+
that requires imports to cross architectural boundaries (e.g., shared lib importing from
|
|
44
|
+
feature code) signals a structural problem.
|
|
45
|
+
- **Existing system boundaries:** Check if the project has documented system boundaries
|
|
46
|
+
(CLAUDE.md, architecture docs). New files should respect these boundaries rather than
|
|
47
|
+
create cross-cutting dependencies.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 3. Extensibility & Future-Proofing Analysis
|
|
52
|
+
|
|
53
|
+
Balance: don't over-engineer (YAGNI), but don't create designs that actively resist
|
|
54
|
+
extension.
|
|
55
|
+
|
|
56
|
+
- **Adjacent features:** What features are most commonly built after this one? Does the
|
|
57
|
+
design accommodate those extensions without major restructuring?
|
|
58
|
+
- **Extension points:** Where would future developers need to hook in? Are those seams
|
|
59
|
+
accessible, or does the design require forking/copying to extend?
|
|
60
|
+
- **Configuration vs. code changes:** Will common customizations require code changes, or
|
|
61
|
+
can they be handled through configuration? Prefer the latter when the variation space
|
|
62
|
+
is predictable.
|
|
63
|
+
- **Data model flexibility:** Are data structures designed to accommodate likely additions
|
|
64
|
+
(new fields, new types) without breaking existing consumers?
|
|
65
|
+
- **Inversion of control:** Does the design allow callers to inject behavior, or does it
|
|
66
|
+
hardcode decisions that callers will need to override? Prefer interfaces and callbacks
|
|
67
|
+
over concrete implementations when variation is expected.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Applicability
|
|
72
|
+
|
|
73
|
+
These standards apply to production code in established codebases with existing conventions.
|
|
74
|
+
For prototypes, scripts, spike explorations, or greenfield projects without established
|
|
75
|
+
patterns, use judgment on which standards apply — not all will be relevant.
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import { logDebug, logInfo, logWarn } from "../../../_shared/lib-ts/base/logger.js";
|
|
7
7
|
import { findExecutable } from "../../../_shared/lib-ts/base/subprocess-utils.js";
|
|
8
|
-
|
|
9
8
|
import type {
|
|
10
9
|
AgentConfig,
|
|
11
10
|
ModelsConfig,
|
|
@@ -31,7 +30,7 @@ export function resolveMandatoryAgents(
|
|
|
31
30
|
return new Set(configValue as string[]);
|
|
32
31
|
}
|
|
33
32
|
if (!configValue || typeof configValue !== "object") {
|
|
34
|
-
return new Set(["
|
|
33
|
+
return new Set(["clarity-auditor", "handoff-readiness", "skeptic"]);
|
|
35
34
|
}
|
|
36
35
|
const cfg = configValue as Record<string, string[]>;
|
|
37
36
|
const names = new Set(cfg.always ?? []);
|
|
@@ -64,7 +63,7 @@ export function assignModelsToAgents(
|
|
|
64
63
|
if (!found) {
|
|
65
64
|
logWarn(HOOK, `Provider '${name}' enabled but CLI '${cliName}' not found on PATH — skipping`);
|
|
66
65
|
}
|
|
67
|
-
return
|
|
66
|
+
return Boolean(found);
|
|
68
67
|
});
|
|
69
68
|
|
|
70
69
|
if (enabledProviders.length === 0) {
|
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Corroboration-based verdict computation for plan review.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Uses agent-agreement thresholding: a dimension blocks only when a sufficient
|
|
5
|
+
* number of *distinct agents* independently flag it. This measures true
|
|
6
|
+
* corroboration (multiple independent reviewers converge) rather than issue
|
|
7
|
+
* density (one verbose agent floods a dimension).
|
|
7
8
|
*
|
|
8
|
-
* **
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* **Algorithm:**
|
|
10
|
+
* For each dimension, compute: `effective_threshold = max(minAgreement, ceil(minRatio × totalAgents))`
|
|
11
|
+
* Block when `distinct_agents_in_dimension >= effective_threshold`.
|
|
12
|
+
*
|
|
13
|
+
* **Default config:** `minAgreement=2, minRatio=0.40`
|
|
14
|
+
* - At 6 agents: threshold=3 (50% must agree)
|
|
15
|
+
* - At 10 agents: threshold=4 (40% must agree)
|
|
16
|
+
* - At 20 agents: threshold=8 (40% must agree)
|
|
17
|
+
*
|
|
18
|
+
* **Why agent-agreement over issue-density:**
|
|
19
|
+
* The previous system (issues >= 2×agents_in_dimension) allowed a single agent
|
|
20
|
+
* to self-corroborate by raising 2+ issues, and made blocking harder as more
|
|
21
|
+
* agents covered a dimension (inverted scaling). Agent-agreement fixes both:
|
|
22
|
+
* a single agent can never self-corroborate, and more agents agreeing is a
|
|
23
|
+
* stronger signal, not a weaker one.
|
|
13
24
|
*
|
|
14
25
|
* **Convergence problem this solves:**
|
|
15
26
|
* Agents with opposing philosophies (simplicity-guardian vs completeness-gaps)
|
|
16
27
|
* produce contradictory high-severity issues. Because the old system treated
|
|
17
28
|
* every agent's finding as independently authoritative, plans oscillated —
|
|
18
|
-
* addressing one agent's feedback triggered the opposing agent.
|
|
29
|
+
* addressing one agent's feedback triggered the opposing agent. The minAgreement
|
|
30
|
+
* floor prevents any single agent's philosophy from blocking alone.
|
|
19
31
|
*
|
|
20
|
-
* **Revert path:** Change one line in
|
|
32
|
+
* **Revert path:** Change one line in review-pipeline.ts back to
|
|
21
33
|
* `computeReviewDecision(allVerdicts)`. Old function kept in verdict.ts.
|
|
22
34
|
*/
|
|
23
35
|
|
|
@@ -30,22 +42,55 @@ import type {
|
|
|
30
42
|
SoloFinding,
|
|
31
43
|
} from "../../lib-ts/types.js";
|
|
32
44
|
|
|
45
|
+
/** Configuration for corroboration thresholds */
|
|
46
|
+
export interface CorroborationConfig {
|
|
47
|
+
/** Minimum distinct agents that must agree to trigger blocking (default: 2) */
|
|
48
|
+
minAgreement?: number;
|
|
49
|
+
/** Minimum fraction of total agent pool that must agree (default: 0.40) */
|
|
50
|
+
minRatio?: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const DEFAULT_MIN_AGREEMENT = 2;
|
|
54
|
+
const DEFAULT_MIN_RATIO = 0.40;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Compute the effective blocking threshold for a given agent pool size.
|
|
58
|
+
*
|
|
59
|
+
* Returns `max(minAgreement, ceil(minRatio × totalAgents))`.
|
|
60
|
+
* This ensures a fixed floor (no single-agent self-corroboration) while
|
|
61
|
+
* scaling proportionally at larger pool sizes.
|
|
62
|
+
*/
|
|
63
|
+
export function getEffectiveThreshold(
|
|
64
|
+
totalAgents: number,
|
|
65
|
+
config: CorroborationConfig = {},
|
|
66
|
+
): number {
|
|
67
|
+
const minAgreement = config.minAgreement ?? DEFAULT_MIN_AGREEMENT;
|
|
68
|
+
const minRatio = config.minRatio ?? DEFAULT_MIN_RATIO;
|
|
69
|
+
return Math.max(minAgreement, Math.ceil(totalAgents * minRatio));
|
|
70
|
+
}
|
|
71
|
+
|
|
33
72
|
/**
|
|
34
73
|
* Compute a corroboration-based review decision from all reviewer results.
|
|
35
74
|
*
|
|
36
75
|
* Algorithm:
|
|
37
76
|
* 1. Collect all high-severity issues with a `dimension` field
|
|
38
77
|
* 2. Group by dimension, tracking distinct agent names per group
|
|
39
|
-
* 3.
|
|
40
|
-
* 4.
|
|
41
|
-
* 5.
|
|
78
|
+
* 3. Compute effective threshold: `max(minAgreement, ceil(minRatio × totalAgents))`
|
|
79
|
+
* 4. For each dimension: block if `distinct_agents >= effective_threshold`
|
|
80
|
+
* 5. Issues without `dimension` are unclassified (logged as warning, never block)
|
|
81
|
+
* 6. Non-high issues are ignored (informational only)
|
|
42
82
|
*
|
|
43
83
|
* @param allResults - Map of reviewer name → ReviewerResult (CLI + agent)
|
|
84
|
+
* @param config - Optional threshold configuration
|
|
44
85
|
* @returns CorroborationResult with blocking groups, solo findings, and verdict
|
|
45
86
|
*/
|
|
46
87
|
export function computeCorroboratedDecision(
|
|
47
88
|
allResults: Record<string, ReviewerResult>,
|
|
89
|
+
config: CorroborationConfig = {},
|
|
48
90
|
): CorroborationResult {
|
|
91
|
+
const totalAgents = Object.keys(allResults).length;
|
|
92
|
+
const threshold = getEffectiveThreshold(totalAgents, config);
|
|
93
|
+
|
|
49
94
|
// Accumulator: dimension → { issues, agentNames }
|
|
50
95
|
const dimMap = new Map<
|
|
51
96
|
IssueDimension,
|
|
@@ -66,7 +111,7 @@ export function computeCorroboratedDecision(
|
|
|
66
111
|
// Only high-severity issues participate in corroboration
|
|
67
112
|
if (issue.severity !== "high") continue;
|
|
68
113
|
|
|
69
|
-
// Issues without dimension are unclassified — cannot block
|
|
114
|
+
// Issues without dimension are unclassified — logged but cannot block
|
|
70
115
|
if (!issue.dimension) {
|
|
71
116
|
unclassified.push({ agent: agentName, issue });
|
|
72
117
|
continue;
|
|
@@ -82,14 +127,22 @@ export function computeCorroboratedDecision(
|
|
|
82
127
|
}
|
|
83
128
|
}
|
|
84
129
|
|
|
130
|
+
// Warn about unclassified issues so they don't silently disappear
|
|
131
|
+
if (unclassified.length > 0) {
|
|
132
|
+
const agents = [...new Set(unclassified.map(u => u.agent))];
|
|
133
|
+
process.stderr.write(
|
|
134
|
+
`[corroboration] WARNING: ${unclassified.length} high-severity issue(s) from [${agents.join(", ")}] lack dimension classification and cannot participate in corroboration\n`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
85
138
|
const blocking: CorroboratedGroup[] = [];
|
|
86
139
|
const solo: SoloFinding[] = [];
|
|
87
140
|
|
|
88
141
|
for (const [dimension, group] of dimMap) {
|
|
89
142
|
const agentCount = group.agentNames.size;
|
|
90
|
-
const threshold = 2 * agentCount;
|
|
91
143
|
|
|
92
|
-
|
|
144
|
+
// Block when enough distinct agents independently flag this dimension
|
|
145
|
+
if (agentCount >= threshold) {
|
|
93
146
|
blocking.push({
|
|
94
147
|
dimension,
|
|
95
148
|
issues: group.issues,
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { OrchestratorClaudeAgent } from "./reviewers/providers/orchestrator-claude-agent.js";
|
|
8
|
-
import type { AgentConfig, OrchestratorConfig, OrchestratorResult } from "../../lib-ts/types.js";
|
|
9
8
|
import { logInfo, logWarn } from "../../../_shared/lib-ts/base/logger.js";
|
|
9
|
+
import type { AgentConfig, OrchestratorConfig, OrchestratorResult } from "../../lib-ts/types.js";
|
|
10
10
|
|
|
11
11
|
// Re-export for backward compatibility (moved to reviewers/schemas.ts)
|
|
12
12
|
export { buildOrchestratorSchema } from "./reviewers/schemas.js";
|
|
@@ -4,18 +4,16 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { logInfo } from "../../../_shared/lib-ts/base/logger.js";
|
|
7
|
-
|
|
7
|
+
import {
|
|
8
|
+
buildInlineReviewSummary,
|
|
9
|
+
extractTopIssuesText,
|
|
10
|
+
} from "../../artifacts/lib/format.js";
|
|
8
11
|
import type {
|
|
9
12
|
ReviewerResult,
|
|
10
13
|
CombinedReviewResult,
|
|
11
14
|
CorroborationResult,
|
|
12
15
|
IterationState,
|
|
13
16
|
} from "../../lib-ts/types.js";
|
|
14
|
-
import {
|
|
15
|
-
buildInlineReviewSummary,
|
|
16
|
-
extractTopIssuesText,
|
|
17
|
-
} from "../../artifacts/lib/format.js";
|
|
18
|
-
import { extractTopIssuesForTracker } from "./graduation.js";
|
|
19
17
|
|
|
20
18
|
const HOOK = "output-builder";
|
|
21
19
|
|
|
@@ -28,7 +26,7 @@ const RESUBMIT_INSTRUCTION = "IMPORTANT: After revising the plan file, you MUST
|
|
|
28
26
|
|
|
29
27
|
/**
|
|
30
28
|
* Truncate per-agent issues to top N by severity.
|
|
31
|
-
*
|
|
29
|
+
* Mutates agentResults[name].data.issues in place.
|
|
32
30
|
*/
|
|
33
31
|
export function truncateAgentIssues(
|
|
34
32
|
agentResults: Record<string, ReviewerResult>,
|
|
@@ -52,7 +50,7 @@ export function truncateAgentIssues(
|
|
|
52
50
|
|
|
53
51
|
/**
|
|
54
52
|
* Override verdict to "fail" for agents exceeding high-issue threshold.
|
|
55
|
-
*
|
|
53
|
+
* Mutates agentResults[name].verdict in place.
|
|
56
54
|
*/
|
|
57
55
|
export function overrideVerdictsByThreshold(
|
|
58
56
|
agentResults: Record<string, ReviewerResult>,
|
|
@@ -94,18 +92,12 @@ export function buildReviewOutput(params: ReviewOutputParams): ReviewOutput {
|
|
|
94
92
|
const { combinedResult, corroborationResult, iterationState } = params;
|
|
95
93
|
|
|
96
94
|
const shouldDeny = corroborationResult.blocking.length > 0;
|
|
97
|
-
const reviewScore = shouldDeny ? 1
|
|
95
|
+
const reviewScore = shouldDeny ? 1 : 0;
|
|
98
96
|
const overall = corroborationResult.verdict;
|
|
99
97
|
|
|
100
|
-
// Build inline summary
|
|
101
|
-
const inlineSummary = buildInlineReviewSummary(combinedResult,
|
|
98
|
+
// Build inline summary (no individual issues — those go in blockReason)
|
|
99
|
+
const inlineSummary = buildInlineReviewSummary(combinedResult, 0, 800, corroborationResult);
|
|
102
100
|
const contextParts = [inlineSummary];
|
|
103
|
-
|
|
104
|
-
// Top issues
|
|
105
|
-
const topIssuesList = extractTopIssuesForTracker(combinedResult, 5);
|
|
106
|
-
if (topIssuesList.length > 0) {
|
|
107
|
-
contextParts.push(`\nTop high-severity issues:\n${topIssuesList.map(i => `- ${i}`).join("\n")}`);
|
|
108
|
-
}
|
|
109
101
|
contextParts.push(`\nFull review: \`${params.reviewFile}\`\n`);
|
|
110
102
|
|
|
111
103
|
const contextText = contextParts.join("");
|
|
@@ -113,11 +105,10 @@ export function buildReviewOutput(params: ReviewOutputParams): ReviewOutput {
|
|
|
113
105
|
|
|
114
106
|
let blockReason: string;
|
|
115
107
|
if (shouldDeny) {
|
|
116
|
-
const topIssuesText = extractTopIssuesText(combinedResult,
|
|
108
|
+
const topIssuesText = extractTopIssuesText(combinedResult, 15, "high");
|
|
117
109
|
blockReason = `Plan review FAILED${iterInfo}. ` +
|
|
118
|
-
`
|
|
119
|
-
`
|
|
120
|
-
`this file contains only the most critical findings, no noise. ` +
|
|
110
|
+
`High-severity issues:\n${topIssuesText}\n\n` +
|
|
111
|
+
`Full details: \`${params.highIssuesPath}\`\n` +
|
|
121
112
|
`${REVIEWER_CAVEAT} ` +
|
|
122
113
|
`Revise the plan to address these issues, then call ExitPlanMode again. ` +
|
|
123
114
|
RESUBMIT_INSTRUCTION;
|
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
|
|
9
|
-
import { aggregateAgents } from "../../lib-ts/aggregate-agents.js";
|
|
10
9
|
import { runAgentReview } from "./reviewers/index.js";
|
|
11
10
|
import { QUESTIONS_SCHEMA } from "./reviewers/schemas.js";
|
|
12
|
-
import type { AgentConfig, ModelsConfig } from "../../lib-ts/types.js";
|
|
13
11
|
import { logInfo, logWarn, logError } from "../../../_shared/lib-ts/base/logger.js";
|
|
12
|
+
import { findExecutable } from "../../../_shared/lib-ts/base/subprocess-utils.js";
|
|
13
|
+
import { aggregateAgents } from "../../lib-ts/aggregate-agents.js";
|
|
14
|
+
import type { AgentConfig } from "../../lib-ts/types.js";
|
|
14
15
|
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
16
17
|
// Types
|
|
@@ -26,8 +27,6 @@ export interface PlanQuestionsResult {
|
|
|
26
27
|
// Provider assignment (local copy — avoids circular import from hook)
|
|
27
28
|
// ---------------------------------------------------------------------------
|
|
28
29
|
|
|
29
|
-
import { findExecutable } from "../../../_shared/lib-ts/base/subprocess-utils.js";
|
|
30
|
-
|
|
31
30
|
function assignProvider(agent: AgentConfig): AgentConfig {
|
|
32
31
|
// Default to claude provider with the agent's configured model
|
|
33
32
|
const found = findExecutable("claude");
|
|
@@ -7,37 +7,26 @@
|
|
|
7
7
|
import * as fs from "node:fs";
|
|
8
8
|
import * as path from "node:path";
|
|
9
9
|
|
|
10
|
+
import { resolveMandatoryAgents, assignModelsToAgents, selectAgents } from "./agent-selection.js";
|
|
11
|
+
import { computeCorroboratedDecision } from "./corroboration.js";
|
|
12
|
+
import { computePassEligible, extractTopIssuesForTracker, advanceIterationState } from "./graduation.js";
|
|
13
|
+
import { runOrchestrator } from "./orchestrator.js";
|
|
14
|
+
import { truncateAgentIssues, overrideVerdictsByThreshold, buildReviewOutput } from "./output-builder.js";
|
|
15
|
+
import { runPlanQuestions } from "./plan-questions.js";
|
|
16
|
+
import { runAgentReview } from "./reviewers/index.js";
|
|
17
|
+
import { getContextReviewsDir, getContextDir, getReviewFolderPath } from "../../../_shared/lib-ts/base/constants.js";
|
|
18
|
+
import { logDiagnostic } from "../../../_shared/lib-ts/base/hook-utils.js";
|
|
10
19
|
import {
|
|
11
20
|
logDebug,
|
|
12
21
|
logInfo,
|
|
13
22
|
logWarn,
|
|
14
23
|
logError,
|
|
15
24
|
} from "../../../_shared/lib-ts/base/logger.js";
|
|
16
|
-
import { logDiagnostic } from "../../../_shared/lib-ts/base/hook-utils.js";
|
|
17
25
|
import { eprint } from "../../../_shared/lib-ts/base/utils.js";
|
|
18
|
-
import { getContextReviewsDir, getContextDir, getReviewFolderPath } from "../../../_shared/lib-ts/base/constants.js";
|
|
19
26
|
import { getContextBySessionId, getAllContexts } from "../../../_shared/lib-ts/context/context-store.js";
|
|
20
|
-
|
|
21
|
-
import type {
|
|
22
|
-
AgentConfig,
|
|
23
|
-
OrchestratorConfig,
|
|
24
|
-
ReviewerResult,
|
|
25
|
-
CombinedReviewResult,
|
|
26
|
-
OrchestratorResult,
|
|
27
|
-
IterationState,
|
|
28
|
-
PipelineInput,
|
|
29
|
-
PipelineResult,
|
|
30
|
-
} from "../../lib-ts/types.js";
|
|
31
|
-
import { REVIEW_SCHEMA } from "../../lib-ts/types.js";
|
|
32
27
|
import type { ContextState } from "../../../_shared/lib-ts/types.js";
|
|
33
|
-
|
|
34
|
-
import {
|
|
35
|
-
import { loadSettings, loadModelsConfig, loadAgentLibrary, DEFAULT_ORCHESTRATOR } from "../../lib-ts/settings.js";
|
|
36
|
-
import { resolveMandatoryAgents, assignModelsToAgents, selectAgents } from "./agent-selection.js";
|
|
37
|
-
import { computePassEligible, extractTopIssuesForTracker, advanceIterationState } from "./graduation.js";
|
|
38
|
-
import { truncateAgentIssues, overrideVerdictsByThreshold, buildReviewOutput } from "./output-builder.js";
|
|
39
|
-
import { DEFAULT_REVIEW_ITERATIONS, loadIterationState, saveIterationState } from "../../lib-ts/state.js";
|
|
40
|
-
|
|
28
|
+
import { writeCombinedArtifacts, buildCorroborationReport, buildHighIssuesDocument, writeReviewTracker } from "../../artifacts/lib/index.js";
|
|
29
|
+
import type { ReviewTrackerEntry } from "../../artifacts/lib/index.js";
|
|
41
30
|
import {
|
|
42
31
|
isPlanAlreadyReviewed,
|
|
43
32
|
wasPlanPreviouslyDenied,
|
|
@@ -47,14 +36,21 @@ import {
|
|
|
47
36
|
markQuestionsAsked,
|
|
48
37
|
resetPlanQuestionsAsked,
|
|
49
38
|
} from "../../lib-ts/cc-native-state.js";
|
|
50
|
-
|
|
51
|
-
import { computeCorroboratedDecision } from "./corroboration.js";
|
|
52
|
-
import { runOrchestrator } from "./orchestrator.js";
|
|
53
39
|
import { debugLog } from "../../lib-ts/debug.js";
|
|
54
|
-
import {
|
|
55
|
-
import
|
|
56
|
-
import {
|
|
57
|
-
import {
|
|
40
|
+
import { discoverPlan } from "../../lib-ts/plan-discovery.js";
|
|
41
|
+
import { loadSettings, loadModelsConfig, loadAgentLibrary, DEFAULT_ORCHESTRATOR } from "../../lib-ts/settings.js";
|
|
42
|
+
import { DEFAULT_REVIEW_ITERATIONS, loadIterationState, saveIterationState } from "../../lib-ts/state.js";
|
|
43
|
+
import type {
|
|
44
|
+
AgentConfig,
|
|
45
|
+
OrchestratorConfig,
|
|
46
|
+
ReviewerResult,
|
|
47
|
+
CombinedReviewResult,
|
|
48
|
+
OrchestratorResult,
|
|
49
|
+
IterationState,
|
|
50
|
+
PipelineInput,
|
|
51
|
+
PipelineResult,
|
|
52
|
+
} from "../../lib-ts/types.js";
|
|
53
|
+
import { REVIEW_SCHEMA } from "../../lib-ts/types.js";
|
|
58
54
|
|
|
59
55
|
const HOOK = "review-pipeline";
|
|
60
56
|
|
|
@@ -143,7 +139,7 @@ export async function runReviewPipeline(input: PipelineInput): Promise<PipelineR
|
|
|
143
139
|
current: 1, max: 1, complexity: "medium",
|
|
144
140
|
history: [], graduated: [], passStreaks: {},
|
|
145
141
|
lastPlanHash: "", lastPlanPath: "",
|
|
146
|
-
sessionId
|
|
142
|
+
sessionId,
|
|
147
143
|
};
|
|
148
144
|
saveIterationState(reviewsDir, iterationState);
|
|
149
145
|
}
|
|
@@ -156,7 +152,7 @@ export async function runReviewPipeline(input: PipelineInput): Promise<PipelineR
|
|
|
156
152
|
current: 1, max: 1, complexity: "medium",
|
|
157
153
|
history: [], graduated: [], passStreaks: {},
|
|
158
154
|
lastPlanHash: "", lastPlanPath: "",
|
|
159
|
-
sessionId
|
|
155
|
+
sessionId,
|
|
160
156
|
};
|
|
161
157
|
saveIterationState(reviewsDir, iterationState);
|
|
162
158
|
resetPlanQuestionsAsked(sessionId, base);
|
|
@@ -213,10 +209,10 @@ export async function runReviewPipeline(input: PipelineInput): Promise<PipelineR
|
|
|
213
209
|
contextText: "[Plan Review] Plan content unchanged since last review which found issues.",
|
|
214
210
|
blockReason: "Plan unchanged since denial. Modify the plan to address review findings, then attempt ExitPlanMode again.",
|
|
215
211
|
};
|
|
216
|
-
}
|
|
212
|
+
}
|
|
217
213
|
const verdict = lastReview?.iteration?.latest_verdict || "pass";
|
|
218
214
|
return { action: "skip", reason: `Plan already reviewed (verdict: ${verdict}). Skipping re-review.` };
|
|
219
|
-
|
|
215
|
+
|
|
220
216
|
}
|
|
221
217
|
|
|
222
218
|
// 7. Iteration bounds check
|
|
@@ -316,7 +312,7 @@ export async function runReviewPipeline(input: PipelineInput): Promise<PipelineR
|
|
|
316
312
|
// Update iteration state with complexity/max
|
|
317
313
|
const reviewIterations: Record<string, number> = {
|
|
318
314
|
...DEFAULT_REVIEW_ITERATIONS,
|
|
319
|
-
...
|
|
315
|
+
...agentSettings.reviewIterations,
|
|
320
316
|
};
|
|
321
317
|
iterationState.complexity = detectedComplexity;
|
|
322
318
|
iterationState.max = reviewIterations[detectedComplexity] ?? iterationState.max;
|
|
@@ -401,8 +397,8 @@ export async function runReviewPipeline(input: PipelineInput): Promise<PipelineR
|
|
|
401
397
|
};
|
|
402
398
|
|
|
403
399
|
const displaySettings = {
|
|
404
|
-
...
|
|
405
|
-
...
|
|
400
|
+
...planSettings.display,
|
|
401
|
+
...agentSettings.display,
|
|
406
402
|
};
|
|
407
403
|
const combinedSettings = { display: displaySettings };
|
|
408
404
|
|
|
@@ -427,8 +423,8 @@ export async function runReviewPipeline(input: PipelineInput): Promise<PipelineR
|
|
|
427
423
|
try {
|
|
428
424
|
fs.writeFileSync(path.join(reviewFolder, "plan.md"), plan, "utf-8");
|
|
429
425
|
logDebug(HOOK, `Saved plan snapshot: ${path.join(reviewFolder, "plan.md")}`);
|
|
430
|
-
} catch (
|
|
431
|
-
logWarn(HOOK, `Failed to save plan snapshot: ${
|
|
426
|
+
} catch (error) {
|
|
427
|
+
logWarn(HOOK, `Failed to save plan snapshot: ${error}`);
|
|
432
428
|
}
|
|
433
429
|
|
|
434
430
|
// Build high-issues document
|
|
@@ -438,7 +434,7 @@ export async function runReviewPipeline(input: PipelineInput): Promise<PipelineR
|
|
|
438
434
|
|
|
439
435
|
// 15. Build output
|
|
440
436
|
const shouldDeny = corroborationResult.blocking.length > 0;
|
|
441
|
-
const reviewScore = shouldDeny ? 1
|
|
437
|
+
const reviewScore = shouldDeny ? 1 : 0;
|
|
442
438
|
const denyReason = shouldDeny ? "corroborated_issues" : "no_corroboration";
|
|
443
439
|
|
|
444
440
|
logInfo(HOOK, `REVIEW_DECISION: verdict=${combinedResult.overall_verdict}, deny=${shouldDeny}, reason=${denyReason}, score=${reviewScore.toFixed(2)}`);
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
* See cc-native-plan-review-spec.md §4.10
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { logWarn } from "../../../../_shared/lib-ts/base/logger.js";
|
|
8
|
-
import type { AgentConfig, ReviewerResult, ReviewOptions } from "../../../lib-ts/types.js";
|
|
9
7
|
import { ClaudeAgent } from "./providers/claude-agent.js";
|
|
10
8
|
import { CodexAgent } from "./providers/codex-agent.js";
|
|
11
9
|
import { GeminiAgent } from "./providers/gemini-agent.js";
|
|
12
10
|
import type { Reviewer } from "./types.js";
|
|
13
11
|
import { makeResult } from "./types.js";
|
|
12
|
+
import { logWarn } from "../../../../_shared/lib-ts/base/logger.js";
|
|
13
|
+
import type { AgentConfig, ReviewerResult, ReviewOptions } from "../../../lib-ts/types.js";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Agent reviewer — runs a CLI instance with a custom persona.
|
|
@@ -59,7 +59,6 @@ export async function runAgentReview(
|
|
|
59
59
|
reviewer = new GeminiAgent(agent, schema, timeout, contextPath, sessionName);
|
|
60
60
|
break;
|
|
61
61
|
}
|
|
62
|
-
case "claude":
|
|
63
62
|
default: {
|
|
64
63
|
reviewer = new ClaudeAgent(agent, schema, timeout, contextPath, sessionName);
|
|
65
64
|
break;
|
package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/codex-agent.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { AGENT_REVIEW_PROMPT_PREFIX } from "../schemas.js";
|
|
|
17
17
|
import { makeResult } from "../types.js";
|
|
18
18
|
|
|
19
19
|
/** Temp directory for Codex schema/output files */
|
|
20
|
-
const
|
|
20
|
+
const _tmpDir: string | null = null;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Codex CLI-based agent reviewer.
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiwcli",
|
|
3
3
|
"description": "AI Workflow CLI - Command-line interface for AI-powered workflows",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.13.1",
|
|
5
5
|
"author": "jofu-tofu",
|
|
6
6
|
"bin": {
|
|
7
7
|
"aiw": "bin/run.js"
|
|
@@ -10,11 +10,13 @@
|
|
|
10
10
|
"url": "https://github.com/jofu-tofu/AI-Workflow-CLI/issues"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@inquirer/
|
|
13
|
+
"@inquirer/checkbox": "^5.0.0",
|
|
14
|
+
"@inquirer/confirm": "^6.0.0",
|
|
15
|
+
"@inquirer/input": "^5.0.0",
|
|
16
|
+
"@inquirer/select": "^5.0.0",
|
|
14
17
|
"@oclif/core": "^4",
|
|
15
18
|
"@oclif/plugin-autocomplete": "^3.2.39",
|
|
16
19
|
"@oclif/plugin-help": "^6",
|
|
17
|
-
"@oclif/plugin-plugins": "^5",
|
|
18
20
|
"chalk": "^5.6.2",
|
|
19
21
|
"clipboardy": "^5.0.2",
|
|
20
22
|
"ora": "^9.0.0"
|
|
@@ -69,8 +71,7 @@
|
|
|
69
71
|
"commands": "./dist/commands",
|
|
70
72
|
"plugins": [
|
|
71
73
|
"@oclif/plugin-autocomplete",
|
|
72
|
-
"@oclif/plugin-help"
|
|
73
|
-
"@oclif/plugin-plugins"
|
|
74
|
+
"@oclif/plugin-help"
|
|
74
75
|
],
|
|
75
76
|
"repositoryPrefix": "https://github.com/jofu-tofu/AI-Workflow-CLI/blob/main/<%- commandPath %>",
|
|
76
77
|
"topicSeparator": " "
|