wogiflow 2.34.1 → 2.34.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.workflow/templates/partials/methodology-rules.hbs +3 -1
- package/lib/workspace-channel-server.js +10 -0
- package/package.json +1 -1
- package/scripts/flow-io.js +17 -0
- package/scripts/flow-paths.js +81 -0
- package/scripts/flow-utils.js +2 -0
- package/scripts/hooks/core/long-input-enforcement.js +49 -39
- package/scripts/hooks/core/phase-gate.js +34 -5
- package/scripts/hooks/core/phase-read-gate.js +62 -10
- package/scripts/hooks/core/worker-continuation-gate.js +169 -8
- package/.claude/rules/README.md +0 -36
- package/.claude/rules/_internal/README.md +0 -64
- package/.claude/rules/_internal/document-structure.md +0 -77
- package/.claude/rules/_internal/dual-repo-management.md +0 -174
- package/.claude/rules/_internal/feature-refactoring-cleanup.md +0 -87
- package/.claude/rules/_internal/github-releases.md +0 -71
- package/.claude/rules/_internal/model-management.md +0 -35
- package/.claude/rules/_internal/self-maintenance.md +0 -87
- package/.claude/rules/_internal/worker-tool-first-turn.md +0 -82
- package/.claude/rules/alternative-execpolicy-toml-command-policy.md +0 -11
- package/.claude/rules/alternative-hand-edit-ready-json-to-register-orpha.md +0 -11
- package/.claude/rules/alternative-hook-args-exec-form.md +0 -6
- package/.claude/rules/alternative-permission-ruleset-per-phase.md +0 -11
- package/.claude/rules/alternative-short-name.md +0 -12
- package/.claude/rules/alternative-wogi-flow-as-mcp-client-oauth-manager.md +0 -11
- package/.claude/rules/architecture/component-reuse.md +0 -38
- package/.claude/rules/architecture/hook-three-layer.md +0 -68
- package/.claude/rules/code-style/naming-conventions.md +0 -107
- package/.claude/rules/dual-repo-architecture-2026-02-28.md +0 -18
- package/.claude/rules/github-release-workflow-2026-01-30.md +0 -16
- package/.claude/rules/operations/git-workflows.md +0 -92
- package/.claude/rules/operations/scratch-directory.md +0 -54
- package/.claude/skills/figma-analyzer/knowledge/learnings.md +0 -11
- package/.workflow/specs/architecture.md.template +0 -24
- package/.workflow/specs/stack.md.template +0 -33
- package/.workflow/specs/testing.md.template +0 -36
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "GitHub release workflow - prevents race conditions in npm publish"
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
globs: package.json
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# GitHub Release Workflow
|
|
8
|
-
|
|
9
|
-
**Source**: Repeated failures (10+ times) in npm publish automation
|
|
10
|
-
**Priority**: Critical - prevents wasted releases and broken npm versions
|
|
11
|
-
|
|
12
|
-
## Problem
|
|
13
|
-
|
|
14
|
-
Running `git push` followed immediately by `gh release create` causes a race condition. The release tag gets created on the remote's HEAD before the push fully propagates, pointing to an old commit.
|
|
15
|
-
|
|
16
|
-
## Pre-Release Quality Gate (MANDATORY)
|
|
17
|
-
|
|
18
|
-
Before ANY release, verify the codebase is in a releasable state:
|
|
19
|
-
|
|
20
|
-
1. **Check outstanding findings**: Read `.workflow/state/last-review.json` — if unresolved critical/high findings exist, STOP and fix them first
|
|
21
|
-
2. **Run lint** (if configured): `npm run lint`
|
|
22
|
-
3. **Run typecheck** (if configured): `npm run typecheck`
|
|
23
|
-
4. **Verify no uncommitted changes**: `git status` should be clean
|
|
24
|
-
|
|
25
|
-
The `preRelease` and `outstandingFindings` quality gates in `flow-done.js` enforce this automatically for `release` type tasks. For manual releases, check these yourself.
|
|
26
|
-
|
|
27
|
-
## Correct Procedure
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
# 0. Verify codebase is releasable (pre-release gate)
|
|
31
|
-
# (automated by flow-done.js for release-type tasks)
|
|
32
|
-
|
|
33
|
-
# 1. Push commits first
|
|
34
|
-
git push origin master
|
|
35
|
-
|
|
36
|
-
# 2. Create tag LOCALLY on the correct commit
|
|
37
|
-
git tag vX.Y.Z HEAD
|
|
38
|
-
|
|
39
|
-
# 3. Push the tag explicitly
|
|
40
|
-
git push origin vX.Y.Z
|
|
41
|
-
|
|
42
|
-
# 4. THEN create the release (it will use the existing tag)
|
|
43
|
-
gh release create vX.Y.Z --title "vX.Y.Z" --notes "..."
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Never Do This
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
# BAD - race condition, tag may point to wrong commit
|
|
50
|
-
git push origin master && gh release create vX.Y.Z ...
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Recovery Procedure
|
|
54
|
-
|
|
55
|
-
If a release fails with wrong version:
|
|
56
|
-
|
|
57
|
-
1. Delete the bad release: `gh release delete vX.Y.Z --yes`
|
|
58
|
-
2. Delete the bad remote tag: `git push origin --delete vX.Y.Z`
|
|
59
|
-
3. Delete local tag if exists: `git tag -d vX.Y.Z`
|
|
60
|
-
4. Follow the correct procedure above
|
|
61
|
-
|
|
62
|
-
## Verification
|
|
63
|
-
|
|
64
|
-
Before creating the release, verify:
|
|
65
|
-
```bash
|
|
66
|
-
git show vX.Y.Z --quiet --format="%H" # Should match HEAD
|
|
67
|
-
git show vX.Y.Z:package.json | grep version # Should show X.Y.Z
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
Last updated: 2026-01-30
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
globs: scripts/flow-model*.js
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
description: "Model management architecture - two separate systems for different purposes"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Model Management Architecture
|
|
8
|
-
|
|
9
|
-
**Context**: Phase 1 introduced model registry and stats system alongside existing model-adapter.
|
|
10
|
-
|
|
11
|
-
## Two Model Systems
|
|
12
|
-
|
|
13
|
-
### 1. flow-model-adapter.js - Prompt Adaptation
|
|
14
|
-
|
|
15
|
-
- `getCurrentModel()` returns normalized model name (string)
|
|
16
|
-
- Focus: Per-model prompt adjustments, learning, and corrections
|
|
17
|
-
- Imports: Used by flow-knowledge-router.js
|
|
18
|
-
|
|
19
|
-
### 2. flow-models.js - Registry and Stats
|
|
20
|
-
|
|
21
|
-
- `getCurrentModel()` returns `{name, info, source}` object
|
|
22
|
-
- Focus: Model listing, routing recommendations, cost tracking
|
|
23
|
-
- Standalone CLI commands: `flow models [subcommand]`
|
|
24
|
-
|
|
25
|
-
## Design Decision
|
|
26
|
-
|
|
27
|
-
**Keep them separate** because:
|
|
28
|
-
- Different return types serve different consumers
|
|
29
|
-
- Adapter system needs just the name for pattern matching
|
|
30
|
-
- Registry system needs full model metadata for display/routing
|
|
31
|
-
- Merging would create unnecessary coupling
|
|
32
|
-
|
|
33
|
-
## Future Consideration
|
|
34
|
-
|
|
35
|
-
Could extract shared model detection logic into a common utility if they drift apart, but avoid premature abstraction.
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Patterns for modifying WogiFlow itself (scripts, templates, config)"
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
globs: "scripts/**,*.workflow/**,.claude/**,templates/**,agents/**,lib/**"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# WogiFlow Self-Maintenance Patterns
|
|
8
|
-
|
|
9
|
-
When modifying WogiFlow's own code (scripts/, templates/, config, hooks), follow these patterns.
|
|
10
|
-
|
|
11
|
-
## 1. Template-First Changes
|
|
12
|
-
|
|
13
|
-
CLAUDE.md is **generated**, not hand-edited. Changes must go through the template system:
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
.workflow/templates/claude-md.hbs # Main template
|
|
17
|
-
.workflow/templates/partials/*.hbs # Partial templates
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
After editing templates, regenerate:
|
|
21
|
-
```bash
|
|
22
|
-
node scripts/flow-bridge.js sync claude-code
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
**Never edit CLAUDE.md directly** - changes will be overwritten on next sync.
|
|
26
|
-
|
|
27
|
-
## 2. Three-Layer Hook Architecture
|
|
28
|
-
|
|
29
|
-
All hooks follow: Entry → Core → Adapter
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
scripts/hooks/entry/claude-code/<name>.js # CLI-specific entry point
|
|
33
|
-
scripts/hooks/core/<name>.js # CLI-agnostic logic
|
|
34
|
-
scripts/hooks/adapters/claude-code.js # Transform results
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
When adding/modifying hooks:
|
|
38
|
-
- Logic goes in `core/` (not entry)
|
|
39
|
-
- Entry files only parse input and call core
|
|
40
|
-
- Register hook in `.claude/settings.local.json`
|
|
41
|
-
- Add config toggle in `.workflow/config.json` under `hooks.rules`
|
|
42
|
-
|
|
43
|
-
## 3. Config Changes Need Documentation
|
|
44
|
-
|
|
45
|
-
When adding config keys:
|
|
46
|
-
- Use `_comment_<keyName>` for inline documentation of non-obvious settings
|
|
47
|
-
- Update config.schema.json if it exists
|
|
48
|
-
- Ensure `lib/installer.js` handles the new key for fresh installs
|
|
49
|
-
|
|
50
|
-
## 4. State File Templates
|
|
51
|
-
|
|
52
|
-
For files in `.workflow/state/` that target projects need:
|
|
53
|
-
- Create both the file AND a `.template` version
|
|
54
|
-
- Templates go in `.workflow/state/<name>.template` (for init/onboard)
|
|
55
|
-
- Also add to `templates/` directory (for npm distribution)
|
|
56
|
-
|
|
57
|
-
## 5. Slash Commands Are Flat Files
|
|
58
|
-
|
|
59
|
-
Slash commands in `.claude/commands/` must be flat `.md` files:
|
|
60
|
-
```
|
|
61
|
-
.claude/commands/wogi-start.md ← Correct (flat file)
|
|
62
|
-
.claude/commands/wogi-start/ ← Wrong (directory)
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## 6. Two Agent Directories
|
|
66
|
-
|
|
67
|
-
| Directory | Purpose | Used By |
|
|
68
|
-
|-----------|---------|---------|
|
|
69
|
-
| `agents/` | 11 persona files | Health checks, CLI |
|
|
70
|
-
| `.workflow/agents/` | Review checklists | wogi-review |
|
|
71
|
-
|
|
72
|
-
Don't confuse them. `agents/security.md` (persona) is different from `.workflow/agents/security.md` (OWASP checklist).
|
|
73
|
-
|
|
74
|
-
## 7. Regression Prevention
|
|
75
|
-
|
|
76
|
-
When modifying flow-*.js scripts:
|
|
77
|
-
- Run `node --check scripts/<file>.js` after edits
|
|
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
|
-
- Check for circular dependencies when moving shared functions
|
|
80
|
-
|
|
81
|
-
## 8. Feature Refactoring Cleanup
|
|
82
|
-
|
|
83
|
-
When renaming/replacing a feature, follow the full checklist in `.claude/rules/architecture/feature-refactoring-cleanup.md`. Key steps:
|
|
84
|
-
- Remove old script files
|
|
85
|
-
- Update config keys
|
|
86
|
-
- Update documentation references
|
|
87
|
-
- Search all `.md` files for old name
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Worker tool-first-turn contract — workspace worker mode only (WOGI_WORKSPACE_ROOT set, WOGI_REPO_NAME !== 'manager')"
|
|
4
|
-
globs: "scripts/hooks/core/worker-tool-first-gate.js,.workflow/templates/worker-rules.md"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Worker Tool-First Turn Contract
|
|
8
|
-
|
|
9
|
-
**Applies to**: workspace worker mode (`WOGI_WORKSPACE_ROOT` set + `WOGI_REPO_NAME !== 'manager'`).
|
|
10
|
-
|
|
11
|
-
**Rule**: Every worker turn that follows a `UserPromptSubmit` (channel dispatch from the manager) MUST contain at least one tool call. In **strict mode** (default), the first assistant content block MUST be a tool call, not text.
|
|
12
|
-
|
|
13
|
-
## Three violations enforced as one rule
|
|
14
|
-
|
|
15
|
-
The Stop hook detects three distinct violations and labels all of them under the unified rule name `worker-tool-first-turn`:
|
|
16
|
-
|
|
17
|
-
| Gate | Violation | Detection |
|
|
18
|
-
|------|-----------|-----------|
|
|
19
|
-
| **G1** | `silent-halt` | Zero `tool_use` blocks across the entire turn (pure-text response). |
|
|
20
|
-
| **G4** | `text-before-tool-call` | First assistant content block is `text`, not `tool_use`. Strict mode only. |
|
|
21
|
-
| **G6** | documented contract | The named rule referenced in block messages so the worker sees one coherent contract, not three independent gates. |
|
|
22
|
-
|
|
23
|
-
## Why the contract exists
|
|
24
|
-
|
|
25
|
-
Workers communicate with the manager via tool calls:
|
|
26
|
-
- Channel dispatches (`curl` POST to the manager port)
|
|
27
|
-
- File edits (`Edit`, `Write`)
|
|
28
|
-
- Test runs (`Bash`)
|
|
29
|
-
- Structured `## Results` payloads posted back to the manager channel
|
|
30
|
-
|
|
31
|
-
A pure-text response from a worker is **invisible to the user** — the user only sees the manager terminal. Worker text disappears into the transcript with no downstream consumer. It also disqualifies the worker from the three-state end-of-turn contract (`ACTION` | `ESCALATION` | `IDLE`) documented in CLAUDE.md under "Workspace Autonomous-Mode Action-After-Completion Contract".
|
|
32
|
-
|
|
33
|
-
## Allowed turn shapes (pass)
|
|
34
|
-
|
|
35
|
-
- Pure action: `tool_use` → `tool_use` → end
|
|
36
|
-
- Action with narration after: `tool_use` → `text` → `tool_use` → end
|
|
37
|
-
- Escalation: `tool_use` (channel dispatch of `## QUESTION:`) → end
|
|
38
|
-
- Reply: `tool_use` (channel dispatch of `## Results:`) → end
|
|
39
|
-
- Idle (pre-user-message): zero assistant blocks — not gated since no dispatch happened
|
|
40
|
-
|
|
41
|
-
## Blocked turn shapes (fail)
|
|
42
|
-
|
|
43
|
-
- **G1**: `text` → end (no tool_use anywhere in turn)
|
|
44
|
-
- **G4**: `text` → `tool_use` → end (strict mode: first block must be tool_use)
|
|
45
|
-
|
|
46
|
-
## Configuration
|
|
47
|
-
|
|
48
|
-
`.workflow/config.json → workspace.toolFirstTurnGate`:
|
|
49
|
-
|
|
50
|
-
```json
|
|
51
|
-
{
|
|
52
|
-
"enabled": true,
|
|
53
|
-
"strict": true
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
- `enabled: false` — disables the gate entirely (silent-halt + text-first both allowed).
|
|
58
|
-
- `strict: false` — G1 still enforced (zero-tool-call blocked), G4 relaxed (text-first allowed as long as a tool_use eventually fires).
|
|
59
|
-
|
|
60
|
-
Default is `enabled: true, strict: true` — maximum worker discipline.
|
|
61
|
-
|
|
62
|
-
## Fail-open behavior
|
|
63
|
-
|
|
64
|
-
The gate fails open on:
|
|
65
|
-
- Missing transcript path
|
|
66
|
-
- Unreadable / malformed transcript file
|
|
67
|
-
- Config read errors
|
|
68
|
-
- Any unexpected exception
|
|
69
|
-
|
|
70
|
-
Rationale: a silent-halt false-negative is recoverable (the worker will be retried on the next manager cycle via the dispatch-tracking overdue check). A false-positive block on every turn would make the worker unusable — unrecoverable without a code deploy.
|
|
71
|
-
|
|
72
|
-
## Related gates (same epic, same integration point)
|
|
73
|
-
|
|
74
|
-
- **Existing — "Gap B" (v2.20.0)**: blocks end-of-turn when queued dispatches exist but no task is in-progress. Complements this gate — Gap B runs at the queue boundary; tool-first runs at every turn.
|
|
75
|
-
- **Existing — AI Worker Question Classifier (v2.21.0)**: Haiku classifier detects when a worker ends with a user-facing question. Complements this gate — question classifier is semantic; tool-first is structural.
|
|
76
|
-
- **Existing — Worker Boundary Gate**: blocks `AskUserQuestion` in worker mode. Complements this gate — boundary gate blocks a specific tool; tool-first requires any tool.
|
|
77
|
-
|
|
78
|
-
## Enforcement
|
|
79
|
-
|
|
80
|
-
- Core logic: `scripts/hooks/core/worker-tool-first-gate.js`
|
|
81
|
-
- Wired into: `scripts/hooks/entry/claude-code/stop.js` (after Gap B, before AI question classifier)
|
|
82
|
-
- Template updated: `.workflow/templates/worker-rules.md` carries the contract verbatim so workers see it in every system prompt.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Alternative: execpolicy-style TOML Bash allow/deny policy layer - Rejected: 2026-04-24"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Alternative: execpolicy-style TOML Bash allow/deny policy layer
|
|
7
|
-
|
|
8
|
-
**Rejected**: 2026-04-24
|
|
9
|
-
**Reason**: The spec framed WogiFlow as owner of Bash allow/deny wildcards. It isn't — `.claude/settings.local.json → permissions.{allow,deny,ask}` are enforced by Claude Code *before* any WogiFlow hook runs, and Claude Code already supports all three modes natively (see `.claude/rules/security/security-patterns.md` §6). WogiFlow's PreToolUse Bash gates (`git-safety-gate`, `deploy-gate`, `strike-gate`, `scope-mutation-gate`, `commit-log-gate`) are content-aware — not wildcard lists — so there is nothing for a TOML allowlist to "replace." Implementing the spec as written would duplicate Claude Code's native permission system with a strictly worse version (no UI integration, no session-scope memory, no settings-source hierarchy).
|
|
10
|
-
**Chose instead**: Lean on Claude Code's native `permissions.{allow,deny,ask}` for allow/deny semantics. The only genuinely-additive piece of the D2 spec — **per-phase command overlay** (AC3) — should be re-specced as a small feature that reads phase-scoped overrides from `.workflow/config.json` and augments the existing `pre-tool-orchestrator.js`, if the need resurfaces from a real incident. Don't build it speculatively.
|
|
11
|
-
**Source**: wf-ac2a8074 scope-confidence audit (user chose option A: drop the story entirely)
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Alternative: Hand-edit ready.json to register orphaned specs - Rejected: 2026-04-15"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Alternative: Hand-edit ready.json to register orphaned specs
|
|
7
|
-
|
|
8
|
-
**Rejected**: 2026-04-15
|
|
9
|
-
**Reason**: CLAUDE.md memory-hierarchy rule forbids hand-editing `.workflow/state/` files to create tasks. Doing so bypasses routing telemetry and breaks the bypass-counter signal that surfaces actual workflow gaps.
|
|
10
|
-
**Chose instead**: One-off script using `flow-utils` `getReadyData` / `saveReadyData` API. The script is self-documenting (kept in `.workflow/scratch/` for the auto-cleanup pass) and uses the same write path the runtime uses.
|
|
11
|
-
**Source**: wf-a3cc5f2a session, state-sync between progress.md and ready.json after epic-episodic-memory wave.
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
# Alternative: Migrate generated hook registrations to the `args: string[]` exec form
|
|
2
|
-
|
|
3
|
-
**Rejected**: 2026-05-12
|
|
4
|
-
**Reason**: Claude Code 2.1.139 added an `args: string[]` field for hook entries that spawns the command directly without a shell, so path placeholders never need quoting. WogiFlow's generated hook registrations (`generateConfig()` in `scripts/hooks/adapters/claude-code.js`) already emit `command: \`node "${absolutePath}"\`` — the absolute script path is double-quoted, which already handles spaces in the project path. Switching to `args` would buy only marginal robustness (paths containing a literal `"` or shell metacharacters — vanishingly rare for real project directories) while introducing a real regression: `args` is silently ignored on Claude Code < 2.1.139, and since it *replaces* `command` rather than augmenting it, a hook entry that emits only `args` would do nothing on older Claude Code — breaking task gating, validation, routing enforcement, etc. for any user not yet on 2.1.139. WogiFlow does not currently require a minimum Claude Code version that high (`postinstall.js` version-gates individual hook *events*, but the base hook set must work on much older CC). The shell-chain commands that actually have gnarly quoting (the `&&`/`2>/dev/null`/`$(...)` one-liners) live in the **permissions allow-list**, not in hook registrations, and cannot use exec form at all (no shell = no `&&`).
|
|
5
|
-
**Chose instead**: Keep `command: \`node "${path}"\``. If WogiFlow's minimum supported Claude Code version ever reaches 2.1.139, revisit — at that point `buildHookEntry()` could emit `args: ["node", scriptPath]` for the `command` transport and drop the manual quoting. Until then, the double-quoted `command` form is correct and maximally compatible.
|
|
6
|
-
**Source**: wf-cb951e91 — "Respond to Claude Code v2.1.139 changelog" (AC2).
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Alternative: Permission-ruleset-per-phase via WogiFlow hooks - Rejected: 2026-04-24"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Alternative: Permission-ruleset-per-phase via WogiFlow hooks
|
|
7
|
-
|
|
8
|
-
**Rejected**: 2026-04-24
|
|
9
|
-
**Reason**: Same root cause as wf-ac2a8074 (D2). `.claude/settings.json → permissions.{allow,deny,ask}` is Claude Code's permission system, enforced by Claude Code itself before any WogiFlow hook fires. Making it phase-aware would require Claude Code to be phase-aware — out of WogiFlow's scope. WogiFlow's PreToolUse gates are content-aware (`git-safety-gate`, `scope-mutation-gate`, etc.), not wildcard permission lists, so there's nothing to "phase-scope" at this layer either.
|
|
10
|
-
**Chose instead**: If real per-phase restrictions surface as a need from incident data, extend `pre-tool-orchestrator.js` with phase-scoped content-aware checks (e.g., "block `rm -rf` during validating phase"). Build that narrow thing from a real incident, not speculative per-phase rulesets.
|
|
11
|
-
**Source**: wf-c6c75841 scope-confidence batch audit (user chose "drop H2" as part of the 1+2+3 combination)
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Alternative: <short name> - Rejected: <YYYY-MM-DD>"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Alternative: <short name>
|
|
7
|
-
|
|
8
|
-
**Rejected**: <YYYY-MM-DD>
|
|
9
|
-
**Reason**: <why we said no — be specific>
|
|
10
|
-
**Chose instead**: <what we did instead, and where it lives>
|
|
11
|
-
**Source**: <task ID, audit, or session that produced this decision>
|
|
12
|
-
-->
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Alternative: WogiFlow-as-MCP-client OAuth manager - Rejected: 2026-04-24"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Alternative: WogiFlow-as-MCP-client OAuth manager (Cline McpHub pattern)
|
|
7
|
-
|
|
8
|
-
**Rejected**: 2026-04-24
|
|
9
|
-
**Reason**: WogiFlow is a workflow layer that runs *inside* a Claude Code session — it is not an MCP client. No `@modelcontextprotocol/sdk` dependency, no transport/stdio/server-connect code; existing `scripts/flow-mcp-*` scripts only *discover* capabilities Claude Code already exposes (`ToolSearch`, `ListMcpResourcesTool`). Cline's `McpHub` works because Cline owns the MCP client lifecycle. In our stack, Claude Code owns it — by the time a WogiFlow SessionStart hook fires, Claude Code has already loaded (or declined to load) its MCP servers, so "reconnect at session start" has no connection object to attach tokens to.
|
|
10
|
-
**Chose instead**: Rely on Claude Code 2.1+ native MCP OAuth. If a future WogiFlow-as-standalone-agent runtime hosts its own MCP clients, revisit then with a fresh spec grounded in that runtime's lifecycle.
|
|
11
|
-
**Source**: wf-8e97ac77 scope-confidence audit (user chose option C: drop the story entirely)
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
globs: src/components/**/*
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
description: "Component reuse policy - always check app-map.md before creating components"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Component Reuse Policy
|
|
8
|
-
|
|
9
|
-
**Rule**: Always check `app-map.md` before creating any component.
|
|
10
|
-
|
|
11
|
-
## Priority Order
|
|
12
|
-
|
|
13
|
-
1. **Use existing** - Check if component already exists in app-map
|
|
14
|
-
2. **Add variant** - Extend existing component with a new variant
|
|
15
|
-
3. **Extend** - Create a wrapper/HOC around existing component
|
|
16
|
-
4. **Create new** - Only as last resort
|
|
17
|
-
|
|
18
|
-
## Before Creating Components
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
# Check app-map first
|
|
22
|
-
cat .workflow/state/app-map.md | grep -i "button"
|
|
23
|
-
|
|
24
|
-
# Or search codebase
|
|
25
|
-
grep -r "Button" src/components/
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Variant vs New Component
|
|
29
|
-
|
|
30
|
-
Prefer variants when:
|
|
31
|
-
- Same base functionality, different appearance
|
|
32
|
-
- Same HTML structure, different styling
|
|
33
|
-
- Same component, different size/color/state
|
|
34
|
-
|
|
35
|
-
Create new component when:
|
|
36
|
-
- Fundamentally different functionality
|
|
37
|
-
- Different DOM structure
|
|
38
|
-
- Different state management
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Three-layer hook architecture: Entry → Core → Adapter. Applies to all hooks under scripts/hooks/."
|
|
4
|
-
globs: scripts/hooks/**/*.js
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Hook Three-Layer Architecture
|
|
8
|
-
|
|
9
|
-
**Rule**: Every WogiFlow hook follows a strict three-layer separation: Entry → Core → Adapter. Entry files parse CLI-harness input and dispatch to core. Core files contain all business logic and are CLI-agnostic. Adapter files translate core results into the target CLI's expected output format.
|
|
10
|
-
|
|
11
|
-
## Layer contract
|
|
12
|
-
|
|
13
|
-
| Layer | Location | Responsibility | Dependencies allowed |
|
|
14
|
-
|-------|----------|----------------|---------------------|
|
|
15
|
-
| **Entry** | `scripts/hooks/entry/<cli-name>/<hook>.js` | Parse stdin JSON, delegate to core, pass result to adapter, write adapter output. Minimal logic. | `core/`, `adapters/` |
|
|
16
|
-
| **Core** | `scripts/hooks/core/<hook>.js` | All business logic: gate decisions, state reads/writes, classifications, enforcement. CLI-agnostic. | `scripts/flow-*.js`, `lib/`, each other |
|
|
17
|
-
| **Adapter** | `scripts/hooks/adapters/<cli-name>.js` | Transform core's uniform return shape into the CLI's expected output format (stdout JSON, exit codes, block messages). | None (pure functions) |
|
|
18
|
-
|
|
19
|
-
## What belongs in each layer
|
|
20
|
-
|
|
21
|
-
**Entry layer MUST**:
|
|
22
|
-
- Read stdin, parse JSON
|
|
23
|
-
- Call exactly one core function (the hook's entry point)
|
|
24
|
-
- Wrap the core's return with the adapter
|
|
25
|
-
- Write adapter output to stdout and exit
|
|
26
|
-
|
|
27
|
-
**Entry layer MUST NOT**:
|
|
28
|
-
- Contain business logic (gate decisions, state enforcement, classifications)
|
|
29
|
-
- Import from other `core/` modules directly (only the hook's own core)
|
|
30
|
-
- Call other CLI's adapters
|
|
31
|
-
- Contain more than ~100 LOC total
|
|
32
|
-
|
|
33
|
-
**Core layer MUST**:
|
|
34
|
-
- Own all gate logic and state mutations
|
|
35
|
-
- Export pure-ish functions (I/O allowed; network not)
|
|
36
|
-
- Be testable without any CLI harness
|
|
37
|
-
|
|
38
|
-
**Core layer MUST NOT**:
|
|
39
|
-
- Import from `entry/` or `adapters/` (those import core, not vice versa)
|
|
40
|
-
- Know about stdin JSON shapes or stdout formats
|
|
41
|
-
- Reference specific CLI tool names (Claude Code, Cursor, etc.)
|
|
42
|
-
|
|
43
|
-
**Adapter layer MUST**:
|
|
44
|
-
- Accept a uniform core-return shape as input
|
|
45
|
-
- Produce CLI-specific output (JSON shape, exit codes)
|
|
46
|
-
|
|
47
|
-
## Why this matters
|
|
48
|
-
|
|
49
|
-
Past incidents (pre-v2.26): `pre-tool-use.js` grew to 560 LOC + 84 branches with gate logic inline in the entry file. This was the origin of `arch-001` audit finding. Same pattern plagued `session-start.js` (307 LOC inline) and `stop.js` (188 LOC inline). When business logic lives in entry files:
|
|
50
|
-
- It can't be unit-tested without spawning a full process
|
|
51
|
-
- It's tied to one CLI harness; cross-CLI support requires copying
|
|
52
|
-
- New gates drift from the established enforcement pattern
|
|
53
|
-
|
|
54
|
-
The three-layer split is enforced mechanically:
|
|
55
|
-
- `flow-standards-checker.js` (standards gate) flags entry files over 120 LOC
|
|
56
|
-
- `flow-standards-checker.js` flags entry files that import from multiple `core/` modules (suggests orchestration logic inline)
|
|
57
|
-
- `flow-standards-checker.js` flags `core/` files that reference CLI-specific shapes (e.g., `input.tool_name` vs accepting `toolName` as a normalized param)
|
|
58
|
-
|
|
59
|
-
## Enforcement
|
|
60
|
-
|
|
61
|
-
Standards-gate checks (added in wf-0f2e0f16):
|
|
62
|
-
1. Entry files (`scripts/hooks/entry/**/*.js`) must be ≤ 120 LOC (allows room for imports + dispatch)
|
|
63
|
-
2. Entry files must import from at most 2 `core/` modules (single-entry-point principle)
|
|
64
|
-
3. Core files (`scripts/hooks/core/**/*.js`) must not contain strings matching known CLI-specific identifiers (`claude-code`, `cursor`, etc.) in comments or code
|
|
65
|
-
|
|
66
|
-
Gate runs during `/wogi-review` and per-commit via the standards lane of `/wogi-done`.
|
|
67
|
-
|
|
68
|
-
**Exemption**: If a legitimate reason requires breaking a rule (e.g., a hook that genuinely needs to fan out to 3 core modules), document it in the entry file header and add the file to `config.standardsCheck.hookThreeLayer.exemptions`.
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: true
|
|
3
|
-
description: "Naming conventions for files and code variants"
|
|
4
|
-
globs: "**/*.{js,ts,jsx,tsx,mjs,cjs}"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Naming Conventions
|
|
8
|
-
|
|
9
|
-
## File Names
|
|
10
|
-
|
|
11
|
-
Use **kebab-case** for all file names in this project.
|
|
12
|
-
|
|
13
|
-
Examples:
|
|
14
|
-
- `flow-health.js` (correct)
|
|
15
|
-
- `flowHealth.js` (incorrect)
|
|
16
|
-
- `flow_health.js` (incorrect)
|
|
17
|
-
|
|
18
|
-
## Variant Names (UI Projects Only)
|
|
19
|
-
|
|
20
|
-
When working on projects with UI components, use consistent variant names:
|
|
21
|
-
|
|
22
|
-
| Category | Values |
|
|
23
|
-
|----------|--------|
|
|
24
|
-
| Size | `sm`, `md`, `lg`, `xl` |
|
|
25
|
-
| Intent | `primary`, `secondary`, `danger`, `success`, `warning` |
|
|
26
|
-
| State | `default`, `hover`, `active`, `disabled` |
|
|
27
|
-
|
|
28
|
-
Skip this section for backend-only or library projects (no UI components).
|
|
29
|
-
|
|
30
|
-
## Catch Block Variables
|
|
31
|
-
|
|
32
|
-
Use `err` for all catch blocks in this codebase.
|
|
33
|
-
|
|
34
|
-
**Avoid**: `e`, `error`, `ex`, `exception` - these cause confusion with loop variables.
|
|
35
|
-
|
|
36
|
-
```javascript
|
|
37
|
-
// Good
|
|
38
|
-
try {
|
|
39
|
-
doSomething();
|
|
40
|
-
} catch (err) {
|
|
41
|
-
console.error(err.message);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Bad - 'e' conflicts with common iterator variables
|
|
45
|
-
try {
|
|
46
|
-
items.map(e => e.value); // 'e' used as iterator
|
|
47
|
-
} catch (e) {
|
|
48
|
-
console.error(e.message); // Easy to confuse with iterator 'e'
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
**Reason**: Standardizing on `err` prevents mix-ups when `.map(e => ...)` is used nearby.
|
|
53
|
-
|
|
54
|
-
### Unused Catch Variables
|
|
55
|
-
|
|
56
|
-
When the catch block intentionally ignores the error, prefix with underscore: `_err`.
|
|
57
|
-
|
|
58
|
-
```javascript
|
|
59
|
-
// Good - _err signals "intentionally unused"
|
|
60
|
-
try {
|
|
61
|
-
JSON.parse(input);
|
|
62
|
-
} catch (_err) {
|
|
63
|
-
return defaultValue;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Bad - looks like a bug (unused variable without underscore)
|
|
67
|
-
try {
|
|
68
|
-
JSON.parse(input);
|
|
69
|
-
} catch (err) {
|
|
70
|
-
return defaultValue;
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
This convention is used across 100+ files in the codebase and satisfies no-unused-vars lint rules.
|
|
75
|
-
|
|
76
|
-
## Default Value Operators: `||` vs `??`
|
|
77
|
-
|
|
78
|
-
Use **nullish coalescing (`??`)** for defaults where the left operand could legitimately be `0`, `false`, or `""`.
|
|
79
|
-
|
|
80
|
-
Use **logical OR (`||`)** only when falsy values (0, false, empty string) should genuinely fall through to the default.
|
|
81
|
-
|
|
82
|
-
```javascript
|
|
83
|
-
// Use ?? — timeout=0 is valid (means "no timeout"), not "use default"
|
|
84
|
-
this.timeout = options.timeout ?? TIMEOUTS.HTTP_DEFAULT;
|
|
85
|
-
|
|
86
|
-
// Use ?? — numeric config values where 0 is meaningful
|
|
87
|
-
const retries = config.maxRetries ?? 3;
|
|
88
|
-
const threshold = config.similarityThreshold ?? 0.5;
|
|
89
|
-
|
|
90
|
-
// Use ?? — boolean config where false is the intended value
|
|
91
|
-
const strictMode = config.enforcement?.strictMode ?? false;
|
|
92
|
-
|
|
93
|
-
// Use ?? — array/object defaults guarding against null/undefined
|
|
94
|
-
const items = data.inProgress ?? [];
|
|
95
|
-
const settings = config.hybrid ?? {};
|
|
96
|
-
|
|
97
|
-
// Use || — empty string should fall through to a display default
|
|
98
|
-
const branch = status.git.branch || 'unknown';
|
|
99
|
-
|
|
100
|
-
// Use || — lookup fallback where undefined means "not found"
|
|
101
|
-
const name = cliNames[type] || type;
|
|
102
|
-
|
|
103
|
-
// Use || — join() returns "" for empty arrays, want a fallback message
|
|
104
|
-
const summary = facts.join('; ') || 'No data available';
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
**Rule of thumb**: If you are defaulting a config value, numeric parameter, boolean flag, or array/object from a potentially-null source, use `??`. If you are providing a display fallback where empty string should show a placeholder, use `||`.
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Dual-Repo Architecture (2026-02-28) - Source: User directive — formalize dual-repo management for wogi-flow + wogiflow-cloud"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Dual-Repo Architecture (2026-02-28)
|
|
7
|
-
|
|
8
|
-
**Source**: User directive — formalize dual-repo management for wogi-flow + wogiflow-cloud
|
|
9
|
-
**Rule**: Two repos, independent versions, mutual version awareness. OSS (`wogi-flow` / npm `wogiflow`) and Cloud (`wogiflow-cloud` / `@wogiflow/teams`) are separate packages with separate release cycles.
|
|
10
|
-
|
|
11
|
-
**Key constraints:**
|
|
12
|
-
1. **No teams code in the free repo** — all team logic lives in `wogiflow-cloud`. The free repo provides extension points only.
|
|
13
|
-
2. **Independent semver** — each repo versions independently. The client declares compatibility via peerDependencies (`wogiflow >= X.Y.Z`).
|
|
14
|
-
3. **Cross-repo version file** — each repo maintains `.workflow/state/partner-versions.json` recording the other's last-known version. Updated on every release.
|
|
15
|
-
4. **OSS releases first** — if cloud needs a new OSS feature/export, release OSS first, then cloud.
|
|
16
|
-
5. **Interface contract** — exported functions, hook interfaces, state file formats, and config keys used by cloud are documented in `.claude/rules/_internal/dual-repo-management.md`. Changes to these require updating the cloud client.
|
|
17
|
-
|
|
18
|
-
**Verification**: Before releasing either repo, check `partner-versions.json` and grep the other repo for consumers of changed interfaces.
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "GitHub Release Workflow (2026-01-30) - Source: Repeated failures (10+ times) in npm publish automation"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# GitHub Release Workflow (2026-01-30)
|
|
7
|
-
|
|
8
|
-
**Source**: Repeated failures (10+ times) in npm publish automation
|
|
9
|
-
**Details**: See `.claude/rules/_internal/github-releases.md` for full procedure.
|
|
10
|
-
|
|
11
|
-
**Quick reference**:
|
|
12
|
-
1. `git push origin master`
|
|
13
|
-
2. `git tag vX.Y.Z HEAD`
|
|
14
|
-
3. `git push origin vX.Y.Z`
|
|
15
|
-
4. `gh release create vX.Y.Z --title "vX.Y.Z" --notes "..."`
|
|
16
|
-
5. `npm publish`
|