wogiflow 2.20.1 → 2.22.0
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/.claude/commands/wogi-finalize.md +83 -0
- package/.claude/rules/_internal/self-maintenance.md +1 -1
- package/.claude/settings.json +1 -1
- package/lib/commands/login.js +1 -1
- package/lib/installer.js +5 -5
- package/lib/release-channel.js +1 -1
- package/lib/skill-registry.js +3 -3
- package/lib/workspace-events.js +1 -1
- package/lib/workspace-gates.js +2 -2
- package/lib/workspace-intelligence.js +1 -1
- package/lib/workspace-routing.js +1 -1
- package/lib/workspace.js +16 -17
- package/package.json +2 -2
- package/scripts/base-workflow-step.js +2 -2
- package/scripts/flow-adaptive-learning.js +6 -6
- package/scripts/flow-api-index.js +2 -2
- package/scripts/flow-architect-pass.js +1 -1
- package/scripts/flow-ask.js +1 -1
- package/scripts/flow-assumption-detector.js +1 -1
- package/scripts/flow-audit-gates.js +38 -12
- package/scripts/flow-audit.js +4 -4
- package/scripts/flow-auto-context.js +3 -3
- package/scripts/flow-background.js +1 -1
- package/scripts/flow-best-of-n.js +7 -7
- package/scripts/flow-bridge.js +3 -3
- package/scripts/flow-bug.js +2 -2
- package/scripts/flow-bulk-loop.js +7 -7
- package/scripts/flow-cascade-completion.js +2 -2
- package/scripts/flow-cascade.js +1 -1
- package/scripts/flow-checkpoint.js +2 -2
- package/scripts/flow-clarifying-questions.js +2 -2
- package/scripts/flow-cli.js +2 -2
- package/scripts/flow-code-intelligence.js +4 -4
- package/scripts/flow-community-sync.js +6 -6
- package/scripts/flow-community.js +1 -1
- package/scripts/flow-completion-truth-gate.js +161 -5
- package/scripts/flow-complexity.js +1 -1
- package/scripts/flow-config-defaults.js +16 -4
- package/scripts/flow-config-interactive.js +2 -2
- package/scripts/flow-config-loader.js +1 -1
- package/scripts/flow-config-migrate.js +5 -6
- package/scripts/flow-consistency-check.js +5 -5
- package/scripts/flow-context-compact/expander.js +1 -1
- package/scripts/flow-context-compact/index.js +2 -2
- package/scripts/flow-context-compact/section-extractor.js +3 -3
- package/scripts/flow-context-compact/summary-tree.js +1 -1
- package/scripts/flow-context-estimator.js +1 -1
- package/scripts/flow-context-gatherer.js +6 -6
- package/scripts/flow-context-generator.js +6 -6
- package/scripts/flow-context-init.js +2 -2
- package/scripts/flow-context-manager.js +1 -1
- package/scripts/flow-context-manifest.js +1 -1
- package/scripts/flow-context-monitor.js +5 -5
- package/scripts/flow-context-orchestrator.js +2 -2
- package/scripts/flow-context-scoring.js +4 -4
- package/scripts/flow-contract-scan.js +1 -1
- package/scripts/flow-correct.js +3 -3
- package/scripts/flow-damage-control.js +2 -2
- package/scripts/flow-deploy-gate.js +2 -2
- package/scripts/flow-deploy-history.js +1 -1
- package/scripts/flow-diff.js +3 -3
- package/scripts/flow-done-gates.js +1 -1
- package/scripts/flow-done.js +7 -7
- package/scripts/flow-durable-session.js +1 -1
- package/scripts/flow-entropy-monitor.js +3 -3
- package/scripts/flow-epics.js +5 -5
- package/scripts/flow-error-recovery.js +4 -4
- package/scripts/flow-eval-judge.js +5 -5
- package/scripts/flow-eval.js +7 -7
- package/scripts/flow-export-scanner.js +5 -5
- package/scripts/flow-extraction-review.js +1 -1
- package/scripts/flow-failure-learning.js +9 -9
- package/scripts/flow-feature.js +5 -5
- package/scripts/flow-figma-confirm.js +1 -1
- package/scripts/flow-figma-extract.js +2 -2
- package/scripts/flow-figma-index.js +2 -2
- package/scripts/flow-figma-match.js +1 -1
- package/scripts/flow-figma-mcp-server.js +3 -3
- package/scripts/flow-figma-orchestrator.js +1 -1
- package/scripts/flow-figma-registry.js +2 -2
- package/scripts/flow-function-index.js +2 -2
- package/scripts/flow-gate-confidence.js +2 -2
- package/scripts/flow-gate-telemetry.js +1 -1
- package/scripts/flow-gitignore.js +1 -1
- package/scripts/flow-guided-edit.js +3 -3
- package/scripts/flow-health.js +95 -8
- package/scripts/flow-hooks.js +3 -3
- package/scripts/flow-hybrid-detect.js +2 -2
- package/scripts/flow-hybrid-interactive.js +1 -1
- package/scripts/flow-hybrid-test.js +1 -1
- package/scripts/flow-hypothesis-generator.js +4 -4
- package/scripts/flow-instruction-richness.js +11 -11
- package/scripts/flow-intent-bootstrap.js +1 -1
- package/scripts/flow-intent-framing.js +1 -1
- package/scripts/flow-item-link.js +2 -2
- package/scripts/flow-knowledge-router.js +7 -7
- package/scripts/flow-knowledge-sync.js +3 -3
- package/scripts/flow-learning-orchestrator.js +1 -1
- package/scripts/flow-links.js +2 -2
- package/scripts/flow-log-manager.js +2 -2
- package/scripts/flow-logic-adversary.js +5 -4
- package/scripts/flow-long-input-chunking.js +1 -1
- package/scripts/flow-long-input-cli.js +3 -3
- package/scripts/flow-long-input.js +18 -18
- package/scripts/flow-loop-retry-learning.js +2 -2
- package/scripts/flow-lsp.js +4 -4
- package/scripts/flow-mcp-docs.js +1 -1
- package/scripts/flow-memory-blocks.js +5 -5
- package/scripts/flow-memory-compactor.js +3 -3
- package/scripts/flow-memory-db.js +4 -4
- package/scripts/flow-memory-sync.js +3 -3
- package/scripts/flow-metrics.js +2 -2
- package/scripts/flow-migrate-igr.js +2 -2
- package/scripts/flow-migrate.js +2 -2
- package/scripts/flow-model-adapter.js +4 -4
- package/scripts/flow-model-caller.js +8 -8
- package/scripts/flow-model-config.js +5 -5
- package/scripts/flow-model-profile.js +7 -7
- package/scripts/flow-model-router.js +5 -5
- package/scripts/flow-model-types.js +3 -3
- package/scripts/flow-models.js +8 -8
- package/scripts/flow-morning.js +1 -1
- package/scripts/flow-multi-approach.js +1 -1
- package/scripts/flow-orchestrate-context.js +2 -2
- package/scripts/flow-orchestrate-llm.js +4 -4
- package/scripts/flow-orchestrate-rollback.js +1 -1
- package/scripts/flow-orchestrate-state.js +6 -6
- package/scripts/flow-orchestrate-templates.js +1 -1
- package/scripts/flow-orchestrate-validation.js +2 -2
- package/scripts/flow-orchestrate-validator.js +1 -1
- package/scripts/flow-orchestrate.js +25 -25
- package/scripts/flow-parallel.js +1 -1
- package/scripts/flow-pattern-enforcer.js +7 -7
- package/scripts/flow-pattern-extractor.js +3 -3
- package/scripts/flow-peer-review.js +8 -8
- package/scripts/flow-pending.js +1 -1
- package/scripts/flow-permissions.js +1 -1
- package/scripts/flow-phased-task.js +1 -1
- package/scripts/flow-plan.js +1 -1
- package/scripts/flow-prd-manager.js +2 -2
- package/scripts/flow-product-scanner.js +2 -2
- package/scripts/flow-progress-tracker.js +2 -2
- package/scripts/flow-progress.js +1 -1
- package/scripts/flow-project-analyzer.js +3 -3
- package/scripts/flow-prompt-capture.js +2 -2
- package/scripts/flow-prompt-composer.js +3 -3
- package/scripts/flow-prompt-template.js +4 -4
- package/scripts/flow-providers.js +31 -23
- package/scripts/flow-queue.js +1 -1
- package/scripts/flow-registry-manager.js +4 -4
- package/scripts/flow-regression.js +1 -1
- package/scripts/flow-response-parser.js +1 -1
- package/scripts/flow-resume.js +1 -1
- package/scripts/flow-review-passes/index.js +2 -2
- package/scripts/flow-review-passes/integration.js +3 -3
- package/scripts/flow-review-passes/logic.js +3 -3
- package/scripts/flow-review-passes/security.js +2 -2
- package/scripts/flow-review-passes/structure.js +1 -1
- package/scripts/flow-review.js +11 -11
- package/scripts/flow-revision-tracker.js +2 -2
- package/scripts/flow-roadmap.js +2 -2
- package/scripts/flow-run-trace.js +1 -1
- package/scripts/flow-safety.js +3 -3
- package/scripts/flow-scanner-base.js +1 -1
- package/scripts/flow-scenario-engine.js +7 -7
- package/scripts/flow-schema-drift.js +4 -3
- package/scripts/flow-section-index.js +2 -2
- package/scripts/flow-section-resolver.js +4 -4
- package/scripts/flow-semantic-match.js +3 -3
- package/scripts/flow-session-end.js +56 -0
- package/scripts/flow-session-learning.js +2 -2
- package/scripts/flow-setup-hooks.js +1 -1
- package/scripts/flow-skill-create.js +3 -3
- package/scripts/flow-skill-freshness.js +2 -2
- package/scripts/flow-skill-generator.js +6 -6
- package/scripts/flow-skill-learn.js +7 -7
- package/scripts/flow-skill-matcher.js +2 -2
- package/scripts/flow-solution-optimizer.js +1 -1
- package/scripts/flow-spec-generator.js +5 -5
- package/scripts/flow-spec-verifier.js +2 -2
- package/scripts/flow-stack-wizard.js +6 -6
- package/scripts/flow-standards-checker.js +8 -8
- package/scripts/flow-standards-gate.js +4 -4
- package/scripts/flow-standards-learner.js +2 -2
- package/scripts/flow-start.js +9 -9
- package/scripts/flow-stats-collector.js +2 -2
- package/scripts/flow-status.js +1 -1
- package/scripts/flow-step-changelog.js +3 -3
- package/scripts/flow-step-complexity.js +1 -1
- package/scripts/flow-step-coverage.js +3 -3
- package/scripts/flow-step-knowledge.js +2 -2
- package/scripts/flow-step-pr-tests.js +2 -2
- package/scripts/flow-step-regression.js +3 -3
- package/scripts/flow-step-review.js +5 -5
- package/scripts/flow-story.js +2 -2
- package/scripts/flow-strict-adherence.js +2 -2
- package/scripts/flow-structure-sensor.js +283 -0
- package/scripts/flow-sync-anonymizer.js +3 -3
- package/scripts/flow-task-checkpoint.js +2 -2
- package/scripts/flow-task-classifier.js +2 -2
- package/scripts/flow-task-completion-summary.js +1 -1
- package/scripts/flow-task-enforcer.js +5 -5
- package/scripts/flow-tech-debt.js +3 -3
- package/scripts/flow-template-extractor.js +3 -3
- package/scripts/flow-templates.js +1 -1
- package/scripts/flow-test-api.js +12 -12
- package/scripts/flow-test-discovery.js +9 -9
- package/scripts/flow-test-generate.js +5 -5
- package/scripts/flow-test-integrity.js +3 -3
- package/scripts/flow-test-ui.js +8 -8
- package/scripts/flow-testing-deps.js +4 -4
- package/scripts/flow-tiered-learning.js +3 -3
- package/scripts/flow-todowrite-sync.js +1 -1
- package/scripts/flow-trap-zone.js +1 -1
- package/scripts/flow-verification-profile.js +9 -9
- package/scripts/flow-verify.js +2 -2
- package/scripts/flow-version-check.js +2 -2
- package/scripts/flow-webmcp-generator.js +3 -3
- package/scripts/flow-wiring-verifier.js +13 -13
- package/scripts/flow-worker-question-classifier.js +256 -0
- package/scripts/flow-workflow-steps.js +3 -3
- package/scripts/flow-workflow.js +1 -1
- package/scripts/flow-worktree.js +1 -1
- package/scripts/hooks/adapters/base-adapter.js +2 -2
- package/scripts/hooks/core/commit-log-gate.js +2 -2
- package/scripts/hooks/core/component-check.js +3 -3
- package/scripts/hooks/core/config-change.js +1 -1
- package/scripts/hooks/core/deploy-gate.js +2 -1
- package/scripts/hooks/core/git-safety-gate.js +1 -1
- package/scripts/hooks/core/instructions-loaded.js +1 -1
- package/scripts/hooks/core/loop-check.js +1 -1
- package/scripts/hooks/core/manager-boundary-gate.js +3 -2
- package/scripts/hooks/core/observation-capture.js +6 -6
- package/scripts/hooks/core/phase-gate.js +4 -4
- package/scripts/hooks/core/pre-compact.js +1 -1
- package/scripts/hooks/core/pre-tool-orchestrator.js +1 -1
- package/scripts/hooks/core/routing-gate.js +2 -84
- package/scripts/hooks/core/session-context.js +1 -1
- package/scripts/hooks/core/session-end.js +3 -3
- package/scripts/hooks/core/session-history.js +1 -1
- package/scripts/hooks/core/setup-handler.js +1 -1
- package/scripts/hooks/core/task-boundary-reset.js +2 -4
- package/scripts/hooks/core/task-completed.js +13 -7
- package/scripts/hooks/core/task-created.js +1 -1
- package/scripts/hooks/core/worktree-lifecycle.js +1 -1
- package/scripts/hooks/entry/claude-code/permission-denied.js +4 -2
- package/scripts/hooks/entry/claude-code/stop.js +60 -0
- package/scripts/hooks/entry/claude-code/user-prompt-submit.js +1 -1
- package/scripts/hooks/git/post-commit.js +1 -1
- package/scripts/postinstall.js +7 -7
- package/scripts/preuninstall.js +5 -5
- package/scripts/registries/component-registry.js +2 -2
- package/scripts/registries/contract-scanner.js +11 -11
- package/scripts/registries/schema-registry.js +5 -5
- package/scripts/registries/service-registry.js +9 -9
|
@@ -79,6 +79,79 @@ Pre-finalization checks:
|
|
|
79
79
|
|
|
80
80
|
If checks fail, display warnings and suggest fixes before proceeding.
|
|
81
81
|
|
|
82
|
+
### Step 2.5: Merge-Plan Gate (when `mergePlan.threshold` exceeded)
|
|
83
|
+
|
|
84
|
+
**Activates when** the branch carries more commits than `config.finalization.mergePlan.threshold` (default **5**) OR the diff is flagged cross-repo by the workspace manifest. The gate writes — and requires the AI to fill in — `.workflow/scratch/merge-plan.md`. The gate exists because the "1-2h mostly mechanical" audit that predicted a 27-conflict merge (wogi-hub, 2026-04-16) counted commits-per-file without reading diff content; the fix is to force per-commit action assignment in a file.
|
|
85
|
+
|
|
86
|
+
**Mechanical invariants (gate blocks on violation):**
|
|
87
|
+
|
|
88
|
+
1. For every commit in `git log <base>..<branch>`, the plan MUST contain one line starting with the short SHA and a tagged action. No commits in an "unaccounted" bucket.
|
|
89
|
+
2. Allowed actions: `port | adapt | skip-style | superseded | skip-with-reason`.
|
|
90
|
+
3. `git log <base>..<branch> | wc -l` MUST equal the count of SHA-prefixed lines in the plan. Mismatch → hard-stop until reconciled.
|
|
91
|
+
4. `skip-with-reason` entries MUST include a one-line reason after a `—` (em dash).
|
|
92
|
+
|
|
93
|
+
**Structural-change detection (before plan write):**
|
|
94
|
+
|
|
95
|
+
Run the structure-change sensor (`scripts/flow-structure-sensor.js`) on the diff. If ≥ `config.finalization.mergePlan.restructureThreshold` (default **20%**) of changed files match one of these restructure patterns, display a STRUCTURAL CHANGE warning at the top of the plan and bias the default action for affected commits to `adapt`:
|
|
96
|
+
|
|
97
|
+
| Pattern | Example | Meaning |
|
|
98
|
+
|---------|---------|---------|
|
|
99
|
+
| `X.tsx` deleted + `X/X.tsx` added | `Card.tsx` → `Card/Card.tsx` | folder-per-component |
|
|
100
|
+
| `X.ts` deleted + `<dir>/X.ts` added at deeper depth | `utils.ts` → `utils/date.ts` | split into submodule |
|
|
101
|
+
| `X` deleted + `X.<ext>` added elsewhere | `types.ts` → `types/index.ts` | barrel introduction |
|
|
102
|
+
|
|
103
|
+
**Procedure:**
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# 1. Gather commit list
|
|
107
|
+
git log --pretty='%h %s' <base>..<branch> > .workflow/scratch/.merge-plan-commits.txt
|
|
108
|
+
|
|
109
|
+
# 2. Run structure sensor
|
|
110
|
+
node node_modules/wogiflow/scripts/flow-structure-sensor.js <base>..<branch> > .workflow/scratch/.merge-plan-sensor.json
|
|
111
|
+
|
|
112
|
+
# 3. Write .workflow/scratch/merge-plan.md using the template below,
|
|
113
|
+
# one SHA-prefixed line per commit. Read the FULL diff of each commit
|
|
114
|
+
# (not just the subject line) before assigning an action — that is
|
|
115
|
+
# the whole point of this gate.
|
|
116
|
+
|
|
117
|
+
# 4. Verify the mechanical invariant
|
|
118
|
+
test "$(git log --oneline <base>..<branch> | wc -l)" -eq \
|
|
119
|
+
"$(grep -cE '^[a-f0-9]{7,}\s' .workflow/scratch/merge-plan.md)"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Plan template** (write verbatim, then fill each row by reading the full diff):
|
|
123
|
+
|
|
124
|
+
```markdown
|
|
125
|
+
# Merge plan: <branch> → <base>
|
|
126
|
+
|
|
127
|
+
Commits: N (from `git log <base>..<branch>`)
|
|
128
|
+
Structural-change sensor: <WARN|clean> — N/M files match restructure patterns
|
|
129
|
+
Cross-repo impact: <list workspace members affected, or "single-repo">
|
|
130
|
+
|
|
131
|
+
## Per-commit actions
|
|
132
|
+
|
|
133
|
+
| SHA | Subject | Action | Notes |
|
|
134
|
+
|-----|---------|--------|-------|
|
|
135
|
+
| abc1234 | feat: add login form | port | — |
|
|
136
|
+
| def5678 | refactor: split Card.tsx into Card/ | adapt | folder-per-component restructure |
|
|
137
|
+
| ghi9012 | chore: lint fixes | skip-style | — |
|
|
138
|
+
| jkl3456 | revert: roll back header | skip-with-reason | superseded by mno7890 |
|
|
139
|
+
|
|
140
|
+
## Structural risks
|
|
141
|
+
|
|
142
|
+
<leave empty if sensor is clean; otherwise list each pattern hit>
|
|
143
|
+
|
|
144
|
+
## Content risks
|
|
145
|
+
|
|
146
|
+
<list overlaps in shared types, DTOs, API surface that need manual review>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**When the plan is complete**, the gate verifies the commit-count invariant (step 4) and proceeds to Step 3 (options). If invariant fails, the command stops with the reconciliation command printed.
|
|
150
|
+
|
|
151
|
+
**Skip conditions:**
|
|
152
|
+
- `config.finalization.mergePlan.enabled: false` — opt-out for users who don't want the gate
|
|
153
|
+
- Branch commits ≤ threshold AND single-repo — small merges don't need a plan
|
|
154
|
+
|
|
82
155
|
### Step 3: Present Options
|
|
83
156
|
|
|
84
157
|
```
|
|
@@ -241,6 +314,12 @@ When `/wogi-start` completes a task that was executed in a worktree, the finaliz
|
|
|
241
314
|
"includeTaskSpec": true,
|
|
242
315
|
"includeCommitList": true,
|
|
243
316
|
"includeFileSummary": true
|
|
317
|
+
},
|
|
318
|
+
"mergePlan": {
|
|
319
|
+
"enabled": true,
|
|
320
|
+
"threshold": 5,
|
|
321
|
+
"restructureThreshold": 0.20,
|
|
322
|
+
"alwaysForCrossRepo": true
|
|
244
323
|
}
|
|
245
324
|
}
|
|
246
325
|
}
|
|
@@ -254,6 +333,10 @@ When `/wogi-start` completes a task that was executed in a worktree, the finaliz
|
|
|
254
333
|
| `requirePRForTypes` | `[]` | Task types that must create a PR (useful for teams) |
|
|
255
334
|
| `squashOnMerge` | `true` | Squash commits when merging |
|
|
256
335
|
| `prTemplate` | `{...}` | What to include in auto-generated PR body |
|
|
336
|
+
| `mergePlan.enabled` | `true` | Require per-commit merge plan on large or cross-repo merges |
|
|
337
|
+
| `mergePlan.threshold` | `5` | Commit count above which the merge plan is required |
|
|
338
|
+
| `mergePlan.restructureThreshold` | `0.20` | % of changed files matching restructure patterns that triggers a structural-change warning |
|
|
339
|
+
| `mergePlan.alwaysForCrossRepo` | `true` | Require the plan on any cross-repo merge regardless of commit count |
|
|
257
340
|
|
|
258
341
|
## Examples
|
|
259
342
|
|
|
@@ -75,7 +75,7 @@ Don't confuse them. `agents/security.md` (persona) is different from `.workflow/
|
|
|
75
75
|
|
|
76
76
|
When modifying flow-*.js scripts:
|
|
77
77
|
- Run `node --check scripts/<file>.js` after edits
|
|
78
|
-
- WogiFlow has
|
|
78
|
+
- Run `npm test` — WogiFlow has a native-Node test suite (50+ files under `tests/`, 1800+ assertions) covering hooks, flow-io, security, session state, workspace gates, and more
|
|
79
79
|
- Check for circular dependencies when moving shared functions
|
|
80
80
|
|
|
81
81
|
## 8. Feature Refactoring Cleanup
|
package/.claude/settings.json
CHANGED
|
@@ -170,6 +170,6 @@
|
|
|
170
170
|
},
|
|
171
171
|
"_comment_dynamicHooks": "TaskCreated (2.1.84+) and PermissionDenied (2.1.88+) are added by postinstall.js when the CC version supports them. They must NOT be committed statically — CC rejects the entire settings file if it encounters an unknown hook event name.",
|
|
172
172
|
"_wogiFlowManaged": true,
|
|
173
|
-
"_wogiFlowVersion": "2.
|
|
173
|
+
"_wogiFlowVersion": "2.22.0",
|
|
174
174
|
"_comment": "Shared WogiFlow hook configuration. Committed to repo for team use. User-specific overrides go in settings.local.json."
|
|
175
175
|
}
|
package/lib/commands/login.js
CHANGED
package/lib/installer.js
CHANGED
|
@@ -194,7 +194,7 @@ function detectProjectScripts(projectRoot) {
|
|
|
194
194
|
let pkgData;
|
|
195
195
|
try {
|
|
196
196
|
pkgData = safeReadJson(packageJsonPath);
|
|
197
|
-
} catch (
|
|
197
|
+
} catch (_err) {
|
|
198
198
|
return detected;
|
|
199
199
|
}
|
|
200
200
|
|
|
@@ -989,7 +989,7 @@ async function init(args) {
|
|
|
989
989
|
try {
|
|
990
990
|
const analyzer = require('../scripts/flow-project-analyzer');
|
|
991
991
|
detection = analyzer.detectProjectType(projectRoot);
|
|
992
|
-
} catch (
|
|
992
|
+
} catch (_err) {
|
|
993
993
|
// Fallback: use basic projectType from installer's own detection
|
|
994
994
|
detection = {
|
|
995
995
|
projectType: config.projectType || 'unknown',
|
|
@@ -1030,7 +1030,7 @@ async function init(args) {
|
|
|
1030
1030
|
// Non-fatal — profile can be generated later via /wogi-test
|
|
1031
1031
|
}
|
|
1032
1032
|
}
|
|
1033
|
-
} catch (
|
|
1033
|
+
} catch (_err) {
|
|
1034
1034
|
// Non-fatal — flow-verification-profile may not exist yet during initial install
|
|
1035
1035
|
}
|
|
1036
1036
|
|
|
@@ -1083,7 +1083,7 @@ function updateManifestAfterInit(cliDir) {
|
|
|
1083
1083
|
if (!manifest || !Array.isArray(manifest.files)) {
|
|
1084
1084
|
manifest = { version: 1, files: [], directories: ['.workflow'] };
|
|
1085
1085
|
}
|
|
1086
|
-
} catch (
|
|
1086
|
+
} catch (_err) {
|
|
1087
1087
|
// No manifest yet — create a fresh one
|
|
1088
1088
|
manifest = { version: 1, files: [], directories: ['.workflow'] };
|
|
1089
1089
|
}
|
|
@@ -1129,7 +1129,7 @@ function walkDirForManifest(dir, baseDir, fileSet) {
|
|
|
1129
1129
|
fileSet.add(path.relative(baseDir, fullPath));
|
|
1130
1130
|
}
|
|
1131
1131
|
}
|
|
1132
|
-
} catch (
|
|
1132
|
+
} catch (_err) {
|
|
1133
1133
|
// Non-critical — skip unreadable dirs
|
|
1134
1134
|
}
|
|
1135
1135
|
}
|
package/lib/release-channel.js
CHANGED
|
@@ -128,7 +128,7 @@ async function getLatestVersion(channel) {
|
|
|
128
128
|
// Get version for the channel's npm tag
|
|
129
129
|
const distTags = pkg['dist-tags'] || {};
|
|
130
130
|
return distTags[channelConfig.npmTag] || distTags.latest || pkg.version;
|
|
131
|
-
} catch (
|
|
131
|
+
} catch (_err) {
|
|
132
132
|
return null;
|
|
133
133
|
}
|
|
134
134
|
}
|
package/lib/skill-registry.js
CHANGED
|
@@ -154,7 +154,7 @@ async function fetchSkillIndex(projectRoot) {
|
|
|
154
154
|
throw new Error('Invalid index data');
|
|
155
155
|
}
|
|
156
156
|
return parsed;
|
|
157
|
-
} catch (
|
|
157
|
+
} catch (_err) {
|
|
158
158
|
// Return mock index for development/offline
|
|
159
159
|
return {
|
|
160
160
|
version: '1.0',
|
|
@@ -201,7 +201,7 @@ async function fetchSkillManifest(skillName, projectRoot) {
|
|
|
201
201
|
throw new Error('Invalid manifest data');
|
|
202
202
|
}
|
|
203
203
|
return parsed;
|
|
204
|
-
} catch (
|
|
204
|
+
} catch (_err) {
|
|
205
205
|
throw new Error(`Skill '${skillName}' not found in registry`);
|
|
206
206
|
}
|
|
207
207
|
}
|
|
@@ -213,7 +213,7 @@ async function fetchSkillManifest(skillName, projectRoot) {
|
|
|
213
213
|
* @param {string} projectRoot - Project root directory
|
|
214
214
|
* @returns {Promise<Object>} Downloaded files
|
|
215
215
|
*/
|
|
216
|
-
async function downloadSkillFiles(skillName, manifest,
|
|
216
|
+
async function downloadSkillFiles(skillName, manifest, _projectRoot) {
|
|
217
217
|
const files = {};
|
|
218
218
|
const baseUrl = `${REGISTRY_CONFIG.baseUrl}/${REGISTRY_CONFIG.branch}/skills/${skillName}`;
|
|
219
219
|
|
package/lib/workspace-events.js
CHANGED
|
@@ -46,7 +46,7 @@ const EVENT_TYPES = [
|
|
|
46
46
|
|
|
47
47
|
const EVENTS_FILE = 'events.json';
|
|
48
48
|
const MAX_EVENTS = 500; // Keep last 500 events
|
|
49
|
-
const
|
|
49
|
+
const _EVENT_ID_PATTERN = /^evt-[a-f0-9]{8}$/;
|
|
50
50
|
|
|
51
51
|
// ============================================================
|
|
52
52
|
// Event Creation
|
package/lib/workspace-gates.js
CHANGED
|
@@ -470,7 +470,7 @@ function broadcastPostChange(workspaceRoot, fromRepo, context, options = {}) {
|
|
|
470
470
|
* @param {Object} taskMeta
|
|
471
471
|
* @returns {{ passed: boolean, message: string, severity: string }}
|
|
472
472
|
*/
|
|
473
|
-
function gateDeploymentReadiness(workspaceRoot,
|
|
473
|
+
function gateDeploymentReadiness(workspaceRoot, _context, taskMeta) {
|
|
474
474
|
const { execFileSync } = require('node:child_process');
|
|
475
475
|
|
|
476
476
|
try {
|
|
@@ -668,7 +668,7 @@ function gatePeerNotification(workspaceRoot, context, taskMeta) {
|
|
|
668
668
|
* Gate: cascadeVerification
|
|
669
669
|
* For library repos, verify all consumers were notified.
|
|
670
670
|
*/
|
|
671
|
-
function gateCascadeVerification(workspaceRoot, context,
|
|
671
|
+
function gateCascadeVerification(workspaceRoot, context, _taskMeta) {
|
|
672
672
|
const gate = WORKSPACE_GATES.find(g => g.name === 'cascadeVerification');
|
|
673
673
|
|
|
674
674
|
if (!context.currentMember || context.currentMember.role !== 'library') {
|
|
@@ -694,7 +694,7 @@ function analyzeReviewForCrossRepoImpact(workspaceRoot, manifest, changedFiles,
|
|
|
694
694
|
result.endpointChanges = changedApiFiles;
|
|
695
695
|
|
|
696
696
|
// Check if contract was also updated
|
|
697
|
-
const
|
|
697
|
+
const _contractsDir = path.join(workspaceRoot, '.workspace', 'contracts');
|
|
698
698
|
const contractFiles = changedFiles.filter(f => f.includes('.workspace/contracts'));
|
|
699
699
|
|
|
700
700
|
if (contractFiles.length === 0 && changedApiFiles.length > 0) {
|
package/lib/workspace-routing.js
CHANGED
|
@@ -344,7 +344,7 @@ function generateParallelInvestigation(workspaceRoot, bugDescription, manifest)
|
|
|
344
344
|
const investigators = [];
|
|
345
345
|
|
|
346
346
|
for (const [name, member] of Object.entries(manifest.members)) {
|
|
347
|
-
const
|
|
347
|
+
const _repoPath = path.resolve(workspaceRoot, member.path);
|
|
348
348
|
|
|
349
349
|
investigators.push({
|
|
350
350
|
repoName: name,
|
package/lib/workspace.js
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
const fs = require('node:fs');
|
|
19
19
|
const path = require('node:path');
|
|
20
|
+
const { safeJsonParse } = require('../scripts/flow-io');
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* wf-f747f993 — resolve the claude-spawning command for workspace sessions.
|
|
@@ -682,7 +683,7 @@ ${Object.entries(config.channels?.members || {}).map(([name, ch]) => `- **${name
|
|
|
682
683
|
|
|
683
684
|
**Check if workers are running:**
|
|
684
685
|
\`\`\`bash
|
|
685
|
-
${Object.entries(config.channels?.members || {}).map(([
|
|
686
|
+
${Object.entries(config.channels?.members || {}).map(([_name, ch]) => `curl -s http://localhost:${ch.port}/health`).join('\n')}
|
|
686
687
|
\`\`\`
|
|
687
688
|
|
|
688
689
|
If a worker is down, tell the user: "Start the ${'{'}repo{'}'} worker: \`cd ${'{'}repo{'}'}/ && flow workspace start\`"
|
|
@@ -705,7 +706,7 @@ If a worker is down, tell the user: "Start the ${'{'}repo{'}'} worker: \`cd ${'{
|
|
|
705
706
|
**Bug investigation — dispatch to all workers:**
|
|
706
707
|
\`\`\`bash
|
|
707
708
|
# Send investigation request to all workers in parallel
|
|
708
|
-
${Object.entries(config.channels?.members || {}).map(([
|
|
709
|
+
${Object.entries(config.channels?.members || {}).map(([_name, ch]) =>
|
|
709
710
|
`curl -s -X POST http://localhost:${ch.port} -d "Investigate: <BUG_DESCRIPTION>. Check recent changes, error logs, relevant code. Report back via workspace message."`
|
|
710
711
|
).join('\n')}
|
|
711
712
|
\`\`\`
|
|
@@ -1110,7 +1111,7 @@ function generateMemberMcpConfigs(workspaceRoot, config) {
|
|
|
1110
1111
|
let existingConfig = {};
|
|
1111
1112
|
try {
|
|
1112
1113
|
if (fs.existsSync(mcpJsonPath)) {
|
|
1113
|
-
existingConfig =
|
|
1114
|
+
existingConfig = safeJsonParse(mcpJsonPath, {});
|
|
1114
1115
|
}
|
|
1115
1116
|
} catch (_err) {
|
|
1116
1117
|
// Ignore malformed existing config
|
|
@@ -1292,7 +1293,7 @@ For everything else — just do the work and report results.
|
|
|
1292
1293
|
let existingManagerMcp = {};
|
|
1293
1294
|
try {
|
|
1294
1295
|
if (fs.existsSync(managerMcpPath)) {
|
|
1295
|
-
existingManagerMcp =
|
|
1296
|
+
existingManagerMcp = safeJsonParse(managerMcpPath, {});
|
|
1296
1297
|
}
|
|
1297
1298
|
} catch (_err) { /* ignore */ }
|
|
1298
1299
|
|
|
@@ -1315,7 +1316,7 @@ For everything else — just do the work and report results.
|
|
|
1315
1316
|
* Initialize a Wogi Workspace
|
|
1316
1317
|
* @param {string[]} args — CLI arguments
|
|
1317
1318
|
*/
|
|
1318
|
-
async function initWorkspace(
|
|
1319
|
+
async function initWorkspace(_args) {
|
|
1319
1320
|
let workspaceRoot = process.cwd();
|
|
1320
1321
|
|
|
1321
1322
|
// Walk up to find existing workspace root (same as startWorkerSession)
|
|
@@ -1332,11 +1333,10 @@ async function initWorkspace(args) {
|
|
|
1332
1333
|
// If we're inside an existing workspace (found in parent or CWD)
|
|
1333
1334
|
if (existingWorkspaceRoot) {
|
|
1334
1335
|
// Check if channels need to be enabled (upgrade path)
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
console.error(`Error reading workspace config: ${err.message}`);
|
|
1336
|
+
const _workspaceConfigPath = path.join(existingWorkspaceRoot, WORKSPACE_CONFIG_FILE);
|
|
1337
|
+
const existingConfig = safeJsonParse(_workspaceConfigPath, null);
|
|
1338
|
+
if (!existingConfig) {
|
|
1339
|
+
console.error(`Error reading workspace config at ${_workspaceConfigPath}`);
|
|
1340
1340
|
process.exit(1);
|
|
1341
1341
|
}
|
|
1342
1342
|
|
|
@@ -1373,7 +1373,7 @@ async function initWorkspace(args) {
|
|
|
1373
1373
|
const manifestPath = path.join(existingWorkspaceRoot, WORKSPACE_DIR, 'state', 'workspace-manifest.json');
|
|
1374
1374
|
try {
|
|
1375
1375
|
if (fs.existsSync(manifestPath)) {
|
|
1376
|
-
const manifest =
|
|
1376
|
+
const manifest = safeJsonParse(manifestPath, {});
|
|
1377
1377
|
const claudeMd = generateWorkspaceClaudeMd(existingConfig, manifest);
|
|
1378
1378
|
fs.writeFileSync(path.join(existingWorkspaceRoot, 'CLAUDE.md'), claudeMd);
|
|
1379
1379
|
console.log(' ✓ CLAUDE.md (regenerated with channel dispatch instructions)');
|
|
@@ -1614,11 +1614,10 @@ function startWorkerSession(cwd) {
|
|
|
1614
1614
|
}
|
|
1615
1615
|
|
|
1616
1616
|
// Read workspace config
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
console.error(`Error reading workspace config: ${err.message}`);
|
|
1617
|
+
const _cfgPath = path.join(workspaceRoot, WORKSPACE_CONFIG_FILE);
|
|
1618
|
+
const config = safeJsonParse(_cfgPath, null);
|
|
1619
|
+
if (!config) {
|
|
1620
|
+
console.error(`Error reading workspace config at ${_cfgPath}`);
|
|
1622
1621
|
process.exit(1);
|
|
1623
1622
|
}
|
|
1624
1623
|
|
|
@@ -1697,7 +1696,7 @@ function startWorkerSession(cwd) {
|
|
|
1697
1696
|
let mcpConfigValid = false;
|
|
1698
1697
|
try {
|
|
1699
1698
|
if (fs.existsSync(mcpJsonPath)) {
|
|
1700
|
-
const mcpConfig =
|
|
1699
|
+
const mcpConfig = safeJsonParse(mcpJsonPath, {});
|
|
1701
1700
|
mcpConfigValid = !!mcpConfig?.mcpServers?.['wogi-workspace-channel'];
|
|
1702
1701
|
}
|
|
1703
1702
|
} catch (_err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wogiflow",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.22.0",
|
|
4
4
|
"description": "AI-powered development workflow management system with multi-model support",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"flow": "./scripts/flow",
|
|
13
|
-
"test": "NODE_ENV=test node --test tests/auto-compact-prompt.test.js tests/flow-paths.test.js tests/flow-io.test.js tests/flow-config-loader.test.js tests/flow-damage-control.test.js tests/flow-output.test.js tests/flow-constants.test.js tests/flow-session-state.test.js tests/flow-hooks-integration.test.js tests/flow-utils.test.js tests/flow-security.test.js tests/flow-memory-db.test.js tests/flow-durable-session.test.js tests/flow-skill-matcher.test.js tests/flow-bridge.test.js tests/flow-proactive-compact.test.js tests/flow-cascade-completion.test.js tests/flow-capture-gate.test.js tests/flow-correction-detector-hybrid.test.js tests/flow-promote.test.js tests/flow-archive-runs.test.js tests/flow-memory.test.js tests/flow-hooks-pre-tool-helpers.test.js tests/flow-hooks-bugfix-scope-gate.test.js tests/flow-hooks-routing-gate.test.js tests/flow-hooks-phase-read-gate.test.js tests/flow-hooks-commit-log-gate.test.js tests/flow-hooks-deploy-gate.test.js tests/flow-hooks-todowrite-gate.test.js tests/flow-hooks-git-safety-gate.test.js tests/flow-hooks-scope-mutation-gate.test.js tests/flow-hooks-strike-gate.test.js tests/flow-hooks-component-check.test.js tests/flow-hooks-scope-gate.test.js tests/flow-hooks-implementation-gate.test.js tests/flow-hooks-research-gate.test.js tests/flow-hooks-loop-check.test.js tests/flow-hooks-manager-boundary-gate.test.js tests/flow-hooks-phase-gate.test.js tests/flow-hooks-pre-tool-orchestrator.test.js tests/flow-hooks-observation-capture.test.js tests/flow-hooks-task-gate.test.js tests/flow-durable-session-suspension.test.js tests/flow-health-mcp-scopes.test.js tests/flow-lean-config.test.js tests/flow-workspace-autopickup.test.js tests/flow-worker-boundary-gate.test.js && NODE_ENV=test node tests/run-quality-gates.test.js",
|
|
13
|
+
"test": "NODE_ENV=test node --test tests/auto-compact-prompt.test.js tests/flow-paths.test.js tests/flow-io.test.js tests/flow-config-loader.test.js tests/flow-damage-control.test.js tests/flow-output.test.js tests/flow-constants.test.js tests/flow-session-state.test.js tests/flow-hooks-integration.test.js tests/flow-utils.test.js tests/flow-security.test.js tests/flow-memory-db.test.js tests/flow-durable-session.test.js tests/flow-skill-matcher.test.js tests/flow-bridge.test.js tests/flow-proactive-compact.test.js tests/flow-cascade-completion.test.js tests/flow-capture-gate.test.js tests/flow-correction-detector-hybrid.test.js tests/flow-promote.test.js tests/flow-archive-runs.test.js tests/flow-memory.test.js tests/flow-hooks-pre-tool-helpers.test.js tests/flow-hooks-bugfix-scope-gate.test.js tests/flow-hooks-routing-gate.test.js tests/flow-hooks-phase-read-gate.test.js tests/flow-hooks-commit-log-gate.test.js tests/flow-hooks-deploy-gate.test.js tests/flow-hooks-todowrite-gate.test.js tests/flow-hooks-git-safety-gate.test.js tests/flow-hooks-scope-mutation-gate.test.js tests/flow-hooks-strike-gate.test.js tests/flow-hooks-component-check.test.js tests/flow-hooks-scope-gate.test.js tests/flow-hooks-implementation-gate.test.js tests/flow-hooks-research-gate.test.js tests/flow-hooks-loop-check.test.js tests/flow-hooks-manager-boundary-gate.test.js tests/flow-hooks-phase-gate.test.js tests/flow-hooks-pre-tool-orchestrator.test.js tests/flow-hooks-observation-capture.test.js tests/flow-hooks-task-gate.test.js tests/flow-durable-session-suspension.test.js tests/flow-health-mcp-scopes.test.js tests/flow-lean-config.test.js tests/flow-workspace-autopickup.test.js tests/flow-worker-boundary-gate.test.js tests/flow-worker-question-classifier.test.js tests/flow-completion-truth-gate-contradictions.test.js tests/flow-structure-sensor.test.js && NODE_ENV=test node tests/run-quality-gates.test.js",
|
|
14
14
|
"test:syntax": "find scripts/ lib/ -name '*.js' -not -path '*/node_modules/*' -exec node --check {} +",
|
|
15
15
|
"lint": "eslint scripts/ lib/ tests/",
|
|
16
16
|
"lint:ci": "eslint scripts/ lib/ tests/ --max-warnings 0",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
const fs = require('node:fs');
|
|
31
31
|
const path = require('node:path');
|
|
32
|
-
const { PATHS
|
|
32
|
+
const { PATHS } = require('./flow-utils');
|
|
33
33
|
|
|
34
34
|
class BaseWorkflowStep {
|
|
35
35
|
/**
|
|
@@ -77,7 +77,7 @@ class BaseWorkflowStep {
|
|
|
77
77
|
* @param {object} options - Remaining options (stepConfig, mode, taskType, etc.)
|
|
78
78
|
* @returns {Promise<{passed: boolean, message: string, details?: any}>}
|
|
79
79
|
*/
|
|
80
|
-
async execute(
|
|
80
|
+
async execute(_files, options) {
|
|
81
81
|
throw new Error(`${this.name}: execute() must be overridden`);
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
const fs = require('node:fs');
|
|
16
16
|
const path = require('node:path');
|
|
17
17
|
const { execFileSync } = require('node:child_process');
|
|
18
|
-
const {
|
|
18
|
+
const { colors, PATHS, getTodayDate } = require('./flow-utils');
|
|
19
19
|
const { error: errorMsg } = require('./flow-output');
|
|
20
20
|
const { readJson } = require('./flow-io');
|
|
21
21
|
const { storeSingleLearning, getAdapterPath } = require('./flow-model-adapter');
|
|
@@ -24,7 +24,7 @@ const {
|
|
|
24
24
|
detectCategory,
|
|
25
25
|
shouldEscalate: checkShouldEscalate
|
|
26
26
|
} = require('./flow-failure-categories');
|
|
27
|
-
const { validateRepoFormat, safeGitCommand
|
|
27
|
+
const { validateRepoFormat, safeGitCommand } = require('./flow-security');
|
|
28
28
|
|
|
29
29
|
const LEARNING_LOG_PATH = path.join(PATHS.state, 'adaptive-learning.json');
|
|
30
30
|
const STRATEGY_STATS_PATH = path.join(PATHS.state, 'strategy-effectiveness.json');
|
|
@@ -66,7 +66,7 @@ const ERROR_CATEGORIES = {
|
|
|
66
66
|
* @param {object} context - Task context
|
|
67
67
|
* @returns {object} Failure analysis
|
|
68
68
|
*/
|
|
69
|
-
function analyzeFailure(error, output,
|
|
69
|
+
function analyzeFailure(error, output, _context = {}) {
|
|
70
70
|
const errorStr = String(error);
|
|
71
71
|
const outputStr = String(output || '');
|
|
72
72
|
|
|
@@ -393,7 +393,7 @@ function generateGuidanceFromFailures(category, details) {
|
|
|
393
393
|
switch (category) {
|
|
394
394
|
case 'IMPORT_ERROR': {
|
|
395
395
|
const modules = details.map(d => d.moduleName).filter(Boolean);
|
|
396
|
-
const
|
|
396
|
+
const _exports = details.map(d => d.exportName).filter(Boolean);
|
|
397
397
|
return {
|
|
398
398
|
do: 'Copy import paths exactly from the "Available Imports" section',
|
|
399
399
|
dont: modules.length > 0
|
|
@@ -530,7 +530,7 @@ function getBestStrategy(modelName, category) {
|
|
|
530
530
|
/**
|
|
531
531
|
* Check if a similar learning already exists
|
|
532
532
|
*/
|
|
533
|
-
function isDuplicateLearning(modelName, category,
|
|
533
|
+
function isDuplicateLearning(modelName, category, _details) {
|
|
534
534
|
const adapterPath = getAdapterPath(modelName);
|
|
535
535
|
if (!fs.existsSync(adapterPath)) return false;
|
|
536
536
|
|
|
@@ -800,7 +800,7 @@ function checkGitHubCLI() {
|
|
|
800
800
|
try {
|
|
801
801
|
execFileSync('gh', ['auth', 'status'], { stdio: 'pipe' });
|
|
802
802
|
return { available: true };
|
|
803
|
-
} catch (
|
|
803
|
+
} catch (_err) {
|
|
804
804
|
return { available: false, error: 'gh CLI not authenticated. Run: gh auth login' };
|
|
805
805
|
}
|
|
806
806
|
}
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
|
|
16
16
|
const fs = require('node:fs');
|
|
17
17
|
const path = require('node:path');
|
|
18
|
-
const {
|
|
18
|
+
const { color, success, warn, error, safeJsonParse, PATHS } = require('./flow-utils');
|
|
19
19
|
const {
|
|
20
20
|
findSimilarItems,
|
|
21
21
|
generateAIDecisionPrompt,
|
|
22
|
-
generateContextBlock,
|
|
22
|
+
generateContextBlock: _generateContextBlock,
|
|
23
23
|
getMatchConfig
|
|
24
24
|
} = require('./flow-semantic-match');
|
|
25
25
|
const { BaseScanner, PROJECT_ROOT } = require('./flow-scanner-base');
|
|
@@ -42,7 +42,7 @@ const path = require('node:path');
|
|
|
42
42
|
const { PATHS } = require('./flow-paths');
|
|
43
43
|
const { fileExists, ensureDir, readFile } = require('./flow-io');
|
|
44
44
|
const { getConfig } = require('./flow-config-loader');
|
|
45
|
-
const { color,
|
|
45
|
+
const { color, warn, error } = require('./flow-output');
|
|
46
46
|
|
|
47
47
|
const gateTelemetry = require('./flow-gate-telemetry');
|
|
48
48
|
|
package/scripts/flow-ask.js
CHANGED
|
@@ -159,7 +159,7 @@ function detectAssumptions(params) {
|
|
|
159
159
|
/**
|
|
160
160
|
* Detect technical assumptions (framework, patterns, etc.)
|
|
161
161
|
*/
|
|
162
|
-
function detectTechnicalAssumptions(title, description,
|
|
162
|
+
function detectTechnicalAssumptions(title, description, _context) {
|
|
163
163
|
const assumptions = [];
|
|
164
164
|
const text = `${title} ${description}`.toLowerCase();
|
|
165
165
|
|
|
@@ -33,7 +33,7 @@ const { execFileSync, execSync } = require('node:child_process');
|
|
|
33
33
|
const fs = require('node:fs');
|
|
34
34
|
const path = require('node:path');
|
|
35
35
|
|
|
36
|
-
const { PATHS,
|
|
36
|
+
const { PATHS, safeJsonParse } = require('./flow-utils');
|
|
37
37
|
|
|
38
38
|
// ============================================================
|
|
39
39
|
// Score Cap Thresholds
|
|
@@ -90,15 +90,25 @@ function runProjectScript(scriptName, timeout = 60000) {
|
|
|
90
90
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
91
91
|
env: { ...process.env, FORCE_COLOR: '0', NO_COLOR: '1' }
|
|
92
92
|
});
|
|
93
|
-
return { exists: true, passed: true, output: output
|
|
93
|
+
return { exists: true, passed: true, output: truncateOutput(output), errorCount: 0, rawOutput: output };
|
|
94
94
|
} catch (err) {
|
|
95
95
|
const output = (err.stdout || '') + (err.stderr || '');
|
|
96
|
-
// Count error lines
|
|
97
96
|
const errorCount = (output.match(/error TS\d+|Error:|ERROR/gi) || []).length;
|
|
98
|
-
return { exists: true, passed: false, output: output
|
|
97
|
+
return { exists: true, passed: false, output: truncateOutput(output), errorCount, rawOutput: output };
|
|
99
98
|
}
|
|
100
99
|
}
|
|
101
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Truncate output while preserving head AND tail so that end-of-output
|
|
103
|
+
* summary lines (e.g. "N problems (X errors, Y warnings)") remain parseable.
|
|
104
|
+
*/
|
|
105
|
+
function truncateOutput(output) {
|
|
106
|
+
if (!output || output.length <= 5000) return output;
|
|
107
|
+
const head = output.substring(0, 3500);
|
|
108
|
+
const tail = output.substring(output.length - 1500);
|
|
109
|
+
return `${head}\n\n... [truncated ${output.length - 5000} chars] ...\n\n${tail}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
102
112
|
/**
|
|
103
113
|
* Gate: Build check — does the project compile?
|
|
104
114
|
*/
|
|
@@ -161,16 +171,22 @@ function checkTypecheck() {
|
|
|
161
171
|
function checkLint() {
|
|
162
172
|
const result = runProjectScript('lint', 60000);
|
|
163
173
|
|
|
164
|
-
// Parse error/warning counts
|
|
174
|
+
// Parse error/warning counts from the RAW (untruncated) output so the
|
|
175
|
+
// end-of-output ESLint summary line is never missed. Bug fixed 2026-04-16:
|
|
176
|
+
// previously used result.output which was truncated to 5000 chars, causing
|
|
177
|
+
// runs with many warnings to silently report "0 warnings".
|
|
165
178
|
let errorCount = 0;
|
|
166
179
|
let warningCount = 0;
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
180
|
+
const parseSource = result.rawOutput || result.output || '';
|
|
181
|
+
// ESLint format: "N problems (X errors, Y warnings)"
|
|
182
|
+
const match = parseSource.match(/(\d+) problems?\s*\((\d+) errors?,\s*(\d+) warnings?\)/);
|
|
183
|
+
if (match) {
|
|
184
|
+
errorCount = parseInt(match[2], 10);
|
|
185
|
+
warningCount = parseInt(match[3], 10);
|
|
186
|
+
} else {
|
|
187
|
+
// Fallback: count individual warning/error lines (still accurate if summary missing).
|
|
188
|
+
warningCount = (parseSource.match(/^\s*\d+:\d+\s+warning/gm) || []).length;
|
|
189
|
+
errorCount = (parseSource.match(/^\s*\d+:\d+\s+error/gm) || []).length;
|
|
174
190
|
}
|
|
175
191
|
|
|
176
192
|
let scoreCap = 100;
|
|
@@ -312,9 +328,19 @@ function checkScriptCompleteness() {
|
|
|
312
328
|
*/
|
|
313
329
|
function countEslintDisables() {
|
|
314
330
|
try {
|
|
331
|
+
// Exclude node_modules, dist, build, coverage, and .workflow runtime data.
|
|
332
|
+
// Bug fixed 2026-04-16: previously walked the entire repo and counted
|
|
333
|
+
// eslint-disable in dependencies, inflating project-health reports.
|
|
315
334
|
const output = execFileSync('grep', [
|
|
316
335
|
'-r', 'eslint-disable',
|
|
317
336
|
'--include=*.ts', '--include=*.tsx', '--include=*.js', '--include=*.jsx',
|
|
337
|
+
'--exclude-dir=node_modules',
|
|
338
|
+
'--exclude-dir=dist',
|
|
339
|
+
'--exclude-dir=build',
|
|
340
|
+
'--exclude-dir=coverage',
|
|
341
|
+
'--exclude-dir=.next',
|
|
342
|
+
'--exclude-dir=.workflow',
|
|
343
|
+
'--exclude-dir=.git',
|
|
318
344
|
'-c', '.'
|
|
319
345
|
], { cwd: PATHS.root, encoding: 'utf-8', timeout: 15000, stdio: ['pipe', 'pipe', 'pipe'] }).toString();
|
|
320
346
|
const lines = output.trim().split('\n').filter(Boolean);
|
package/scripts/flow-audit.js
CHANGED
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
const { execFileSync } = require('node:child_process');
|
|
19
|
-
const
|
|
19
|
+
const _fs = require('node:fs');
|
|
20
20
|
const path = require('node:path');
|
|
21
21
|
const {
|
|
22
22
|
PATHS,
|
|
23
23
|
getConfig,
|
|
24
|
-
color,
|
|
24
|
+
color: _color,
|
|
25
25
|
safeJsonParse,
|
|
26
26
|
safeJsonParseString,
|
|
27
27
|
escapeRegex
|
|
@@ -55,10 +55,10 @@ function getProjectFiles(extraExcludes = []) {
|
|
|
55
55
|
const config = getConfig();
|
|
56
56
|
// escapeRegex imported from flow-utils.js
|
|
57
57
|
const configExcludes = (config.audit?.exclude || []).map(p => {
|
|
58
|
-
try { return new RegExp(`^${escapeRegex(p)}/`); } catch (
|
|
58
|
+
try { return new RegExp(`^${escapeRegex(p)}/`); } catch (_err) { return null; }
|
|
59
59
|
}).filter(Boolean);
|
|
60
60
|
const allExcludes = [...DEFAULT_EXCLUDE, ...configExcludes, ...extraExcludes.map(p => {
|
|
61
|
-
try { return new RegExp(p); } catch (
|
|
61
|
+
try { return new RegExp(p); } catch (_err) { return null; }
|
|
62
62
|
}).filter(Boolean)];
|
|
63
63
|
|
|
64
64
|
return output.trim().split('\n').filter(f =>
|
|
@@ -23,13 +23,13 @@ const fs = require('node:fs');
|
|
|
23
23
|
const path = require('node:path');
|
|
24
24
|
const { execSync, spawnSync } = require('node:child_process');
|
|
25
25
|
const {
|
|
26
|
-
getProjectRoot,
|
|
26
|
+
getProjectRoot: _getProjectRoot,
|
|
27
27
|
getConfig,
|
|
28
28
|
PATHS,
|
|
29
29
|
colors,
|
|
30
30
|
isAstGrepAvailable,
|
|
31
31
|
astGrepSearch,
|
|
32
|
-
AST_PATTERNS,
|
|
32
|
+
AST_PATTERNS: _AST_PATTERNS,
|
|
33
33
|
findReactComponents,
|
|
34
34
|
findCustomHooks,
|
|
35
35
|
findTypeDefinitions,
|
|
@@ -902,7 +902,7 @@ async function getLegacyContext(description, options = {}, config = null) {
|
|
|
902
902
|
|
|
903
903
|
const autoConf = config.taskContext?.auto || config.context?.auto;
|
|
904
904
|
const maxFiles = options.maxFiles || autoConf?.maxFilesToLoad || 10;
|
|
905
|
-
const
|
|
905
|
+
const _showFiles = options.showFiles ?? autoConf?.showLoadedFiles ?? true;
|
|
906
906
|
|
|
907
907
|
// Extract keywords
|
|
908
908
|
const keywords = extractKeywords(description);
|