Skip to content

Commit 70984e4

Browse files
docs: correct the README's four load-bearing false claims (#302)
Merge PR #302
1 parent e36aa0d commit 70984e4

1 file changed

Lines changed: 82 additions & 82 deletions

File tree

‎README.md‎

Lines changed: 82 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22

33
> Automate your entire software development lifecycle — from task to merged PR — using Claude AI.
44
5-
[![Version](https://img.shields.io/badge/Version-1.20.3-blue)](CHANGELOG.md)
5+
[![Version](https://img.shields.io/badge/Version-2.1.0-blue)](CHANGELOG.md)
66
[![Python](https://img.shields.io/badge/Python-3.10%2B-green)](https://python.org)
7-
[![PyPI](https://img.shields.io/badge/PyPI-claude--workflow--engine-orange)](https://pypi.org/project/claude-workflow-engine/)
87
[![CI](https://github.com/techdeveloper-org/claude-workflow-engine/actions/workflows/ci.yml/badge.svg)](https://github.com/techdeveloper-org/claude-workflow-engine/actions/workflows/ci.yml)
98
[![License](https://img.shields.io/badge/License-MIT-yellow)](LICENSE)
109
[![Tests](https://img.shields.io/badge/Tests-102%20files%20·%205%20integration-brightgreen)](tests/)
@@ -23,13 +22,13 @@ Most AI coding tools generate code and stop there. This engine does what a full
2322
| **Core Generation** | | | | |
2423
| Code generation | Yes | Yes | Yes | Yes |
2524
| Unit test generation (Python/Java/TS/Kotlin) | Yes | — | Partial | — |
26-
| Documentation update (Step 13) | Yes | — | — | — |
25+
| Documentation update (Step 7) | Yes | — | — | — |
2726
| **Planning & Analysis** | | | | |
2827
| Task analysis + complexity scoring [1-25] | Yes | — | — | Partial |
2928
| Call graph impact analysis (pre-change) | Yes | — | — | — |
3029
| Breaking change detection (graph diff) | Yes | — | — | — |
3130
| Multi-language call graph (Python/Java/TS/Kotlin) | Yes | — | — | — |
32-
| Template fast-path (bypass Step 0, ~0s planning) | Yes | — | — | — |
31+
| Template fast-path (skips Step 1 planning, ~0s) | Yes | — | — | — |
3332
| **GitHub / Jira SDLC** | | | | |
3433
| GitHub issue creation | Yes | — | — | — |
3534
| Dual issue tracking (GitHub + Jira) | Yes | — | — | — |
@@ -71,11 +70,9 @@ Most AI coding tools generate code and stop there. This engine does what a full
7170

7271
### Install
7372

74-
```bash
75-
# From PyPI (recommended)
76-
pip install claude-workflow-engine
73+
Not published to PyPI. Install from source:
7774

78-
# From source
75+
```bash
7976
git clone https://github.com/techdeveloper-org/claude-workflow-engine
8077
cd claude-workflow-engine
8178
pip install -r requirements.txt
@@ -85,19 +82,45 @@ cp .env.example .env
8582

8683
### Run
8784

85+
Since v2.0.0 the pipeline does **not** start on its own. It runs only when a caller
86+
explicitly declares which of six commands it stands in for, and it refuses otherwise.
87+
There is no environment variable that disables this and no opt-out flag — the reasoning
88+
is in `scripts/pipeline_invocation.py`.
89+
90+
**The supported route is the plugin.** Its commands declare the invocation for you:
91+
92+
```
93+
/claude-workflow-engine:plan Steps 0-1 — analyse and decompose, change nothing
94+
/claude-workflow-engine:implement Steps 2-4 — issue, branch, code
95+
/claude-workflow-engine:review Steps 5-6 — PR, automated review, close the issue
96+
/claude-workflow-engine:document Step 7 — docs and diagrams
97+
/claude-workflow-engine:release Step 8 — telemetry and summary
98+
/claude-workflow-engine:run-pipeline Steps 0-8 — all of it, in order
99+
```
100+
101+
MCP-backed capabilities stay unreachable until you run
102+
`/claude-workflow-engine:register-mcp` once.
103+
104+
**Direct CLI** — for a container entry point or a manual run, declare the command
105+
yourself with `--invoked-by=`:
106+
88107
```bash
89-
# Hook Mode (default) — runs analysis + creates GitHub issue + branch
90-
python scripts/3-level-flow.py --message "Fix the login timeout bug"
108+
# Hook Mode (default) — analysis, GitHub issue, branch
109+
python scripts/3-level-flow.py --invoked-by=implement --message "Fix the login timeout bug"
91110

92-
# Full Mode — runs all 8 active steps end-to-end (implements + PR + closes issue)
93-
CLAUDE_HOOK_MODE=0 python scripts/3-level-flow.py --message "Fix the login timeout bug"
111+
# Full Mode — all 9 active steps end-to-end (implements + PR + closes issue)
112+
CLAUDE_HOOK_MODE=0 python scripts/3-level-flow.py --invoked-by=run-pipeline \
113+
--message "Fix the login timeout bug"
94114

95-
# Template Fast-Path — skip Step 0 planning entirely
96-
python scripts/3-level-flow.py \
115+
# Template Fast-Path — Step 0 detects the template and skips Step 1 planning
116+
python scripts/3-level-flow.py --invoked-by=run-pipeline \
97117
--message "Add document Q&A feature" \
98118
--orchestration-template=orchestration_template.example.json
99119
```
100120

121+
Omitting `--invoked-by=` prints `[REFUSED]` and exits 0 without running anything. A
122+
misspelled command name exits 2, so a typo costs an error rather than a silent no-op.
123+
101124
### What happens when you run it
102125

103126
```mermaid
@@ -318,78 +341,55 @@ Pre-fill a JSON orchestration template once, and every subsequent run skips Step
318341
python scripts/3-level-flow.py \
319342
--message "add document Q&A feature" \
320343
--orchestration-template=orchestration_template.example.json
321-
# Planning time: ~0s (template loaded, Step 0 bypassed)
344+
# Planning time: ~0s (Step 0 detects the template and skips Step 1)
322345
```
323346

324347
See `orchestration_template.example.json` for the full field reference.
325348

326349
---
327350

328-
## Hook System
329-
330-
> Interactive version of this section + the pipeline diagram above: [Pipeline & Hook Architecture](https://claude.ai/code/artifact/6045b61f-00e5-411d-a2a6-d62b267ba29c)
351+
## Hooks — what happened to them
331352

332-
Claude Code exposes 9 hook events. This project registers **4 of them** in `~/.claude/settings.json`. The table below was produced by tracing every registered entry point down to which internal policy modules actually execute, not by reading the prose docs — `docs/policies/hook-system-policy.md` has drifted from the real wiring (see Findings below).
353+
**v2.0.0 deleted the enforcement hooks.** `PreToolUse`, `PostToolUse` and
354+
`UserPromptSubmit` are no longer registered in the user-scope `settings.json`; the
355+
`hooks` object holds exactly `Stop` and `Notification`, and those two were proved
356+
unchanged by comparing canonical-JSON digests rather than merely checking they were
357+
still present.
333358

334-
### Registration Status
359+
If you are looking for the previous version of this section — a nine-row registration
360+
table, a per-policy breakdown and four findings about dead abstractions — it described
361+
that deleted architecture and has been removed rather than corrected. `git log` has it.
335362

336-
| Event | Registered | Entry Point | Wired Policies |
337-
|---|:---:|---|---|
338-
| `UserPromptSubmit` | Yes | `scripts/3-level-flow.py` | Runs the full 3-level pipeline; also the only entry point driving `src/mcp/session_hooks.py` |
339-
| `PreToolUse` | Yes | `hooks/pre-tool-enforcer.py` → `pre_tool_enforcer/core.py` | 12 / 13 loaded policies wired (1 dead — see Findings) |
340-
| `PostToolUse` | Yes | `hooks/post-tool-tracker.py` → `post_tool_tracker/core.py` | 6 / 6 wired |
341-
| `Stop` | Yes | `hooks/stop-notifier.py` → `stop_notifier/core.py` | `voice.py` + `post_impl.py` fully wired |
342-
| `SessionStart` | **No** | — | — |
343-
| `SessionEnd` | **No** | — | — |
344-
| `SubagentStop` | **No** | — | — |
345-
| `PreCompact` | **No** | — | — |
346-
| `Notification` | **No** | — | — |
363+
### What replaced them
347364

348-
```mermaid
349-
flowchart TD
350-
subgraph REG["Registered — settings.json"]
351-
direction TB
352-
UPS["UserPromptSubmit\n→ scripts/3-level-flow.py"]
353-
PRE["PreToolUse\n→ hooks/pre-tool-enforcer.py"]
354-
POST["PostToolUse\n→ hooks/post-tool-tracker.py"]
355-
STOP["Stop\n→ hooks/stop-notifier.py"]
356-
end
357-
358-
UPS --> PIPE["Full 3-level LangGraph pipeline\n+ session_hooks.py bridge"]
359-
PRE --> PREP["pre_tool_enforcer/core.py\n12/13 policies wired · 1 dead\nPolicyRegistry loaded, never used"]
360-
POST --> POSTP["post_tool_tracker/core.py\n6/6 policies wired"]
361-
STOP --> STOPP["stop_notifier/core.py\nvoice.py + post_impl.py wired\n+ session save/archive/prune\n(SessionEnd-shaped work)"]
362-
363-
subgraph MISS["Never registered — no entry, no orphaned code"]
364-
direction LR
365-
SS["SessionStart"] ~~~ SE["SessionEnd"] ~~~ SA["SubagentStop"] ~~~ PC["PreCompact"] ~~~ NT["Notification"]
366-
end
367-
368-
style REG fill:#dcfce7,stroke:#16a34a
369-
style MISS fill:#fee2e2,stroke:#dc2626
370-
style PREP fill:#fef3c7,stroke:#d97706
371-
```
372-
373-
### PreToolUse — full policy breakdown
365+
| Was | Is now |
366+
|---|---|
367+
| `UserPromptSubmit` started the pipeline on every prompt | Nothing starts it implicitly. A caller declares one of six commands (see [Run](#run)) or it refuses |
368+
| `PreToolUse` blocked unsafe pushes | An MCP-side push gate, plus ADR-020's three-layer control: prevention on the path the plugin owns, detection on the manual-edit path that has no interception point |
369+
| `PostToolUse` tracked progress | MCP tools, called explicitly |
374370

375-
`pre_tool_enforcer/core.py` loads all 13 files under `hooks/pre_tool_enforcer/policies/`:
371+
The ordering mattered: the replacement push gate was registered and proved reachable by
372+
completing a real `tools/call` **before** `PreToolUse` was deleted. Removing the hook
373+
while its replacement existed only in the repository would have left a machine with no
374+
push gate at all.
376375

377-
| Policy | Status |
378-
|---|---|
379-
| `checkpoint.py`, `task_breakdown.py`, `skill_selection.py`, `context_read.py`, `level1_sync.py`, `python_unicode.py`, `bash_commands.py`, `grep_opt.py`, `read_opt.py`, `agent_persona.py` | Wired — blocking (`_BLOCKING_POLICIES`, core.py:470-481) |
380-
| `skill_context.py`, `failure_kb.py` | Wired — non-blocking hints (core.py:543-549, 562-568) |
381-
| `write_edit.py` | **Loaded, never called** — see Findings #2 |
376+
### The code is still here, and is not wired
382377

383-
### PostToolUse — full policy breakdown
378+
`hooks/` still contains `pre_tool_enforcer/`, `post_tool_tracker/` and `stop_notifier/`.
379+
None of it is registered. Treat it as reference material, not as behaviour you are
380+
getting — nothing in the plugin or in `scripts/3-level-flow.py` reaches it.
384381

385-
All 6 files under `hooks/post_tool_tracker/policies/` are loaded and invoked: `uncommitted_push.py`, `post_merge_update.py`, `task_tracking.py`, `phase_complexity.py`, `task_breakdown_clear.py`, `skill_selection_clear.py`.
382+
### The plugin ships zero hooks, deliberately
386383

387-
### Findings
384+
Plugin hooks merge into a flat, session-wide pipeline with no per-plugin label, so a
385+
user cannot disable one plugin's hook without disabling everyone's. Shipping one would
386+
give you less control than you have now. This is ADR-010, and a CI job
387+
(`Plugin conformance (ADR-010 / ADR-019 CRITICAL)`) fails the build if a `hooks/`
388+
directory or a `hooks.json` ever appears under the plugin root.
388389

389-
1. **`PolicyRegistry` is a dead abstraction.** `hooks/pre_tool_enforcer/registry.py` defines a `PolicyRegistry` class meant to register and run policies generically. `core.py:182` imports it, but nothing in the repo ever instantiates it — `core.py` hand-builds its own `_BLOCKING_POLICIES` list instead. Either wire real policies through it or delete it.
390-
2. **`write_edit.py` never executes.** Loaded and wrapped at `core.py:216` / `367-369`, but no call site in `main()` reaches it — and its own body is a stub that always returns `False`. A second, non-stub-looking copy also sits unused directly in the `pre-tool-enforcer.py` shim (lines 204-222), likewise never called. Two dead implementations of the same check.
391-
3. **No dedicated `SessionEnd` hook.** `stop_notifier/core.py` runs session archiving, pruning, and preference tracking on every `Stop` event — work a real `SessionEnd` hook would own instead. Since `Stop` fires on every response (not just session close), this logic runs far more often than necessary.
392-
4. **`docs/policies/hook-system-policy.md` no longer matches the implementation.** It describes a `script-chain-executor.py` dispatcher and a `hook-downloader.py` sync-from-repo model — neither file exists in the repo anymore. Its example `settings.json` snippets point at `~/.claude/scripts/...py`, while the real registration points directly into this repo's `hooks/...py`. Its policy counts ("8" PreToolUse checks, "6" PostToolUse functions) use a different taxonomy than the actual files and only coincidentally match on PostToolUse.
390+
The consequence is worth stating plainly: **nothing is enforced in a session where you
391+
do not invoke a command.** That is the intended trade-off of the hook-free design, not
392+
a regression.
393393

394394
---
395395

@@ -538,7 +538,7 @@ All options are set via environment variables. Copy `.env.example` and fill in:
538538
| Variable | Default | Description |
539539
|---|---|---|
540540
| `ENABLE_JIRA` | `0` | Dual GitHub+Jira issue tracking |
541-
| `ENABLE_JENKINS` | `0` | Jenkins build validation in Step 11 |
541+
| `ENABLE_JENKINS` | `0` | Jenkins build validation in Step 5 |
542542
| `ENABLE_SONARQUBE` | `0` | SonarQube scan after implementation |
543543
| `ENABLE_FIGMA` | `0` | Figma design-to-code pipeline |
544544
| `ENABLE_CI` | `false` | GitHub Actions CI pipeline |
@@ -570,18 +570,18 @@ All integrations follow the same create → update → close lifecycle pattern w
570570
```
571571
Step 8: CREATE Jira issue created, cross-linked to GitHub Issue
572572
Step 9: BRANCH Branch named from Jira key (feature/proj-123)
573-
Step 10: UPDATE Transition → "In Progress", add start comment
574-
Step 11: LINK PR linked in Jira, transition → "In Review"
575-
Step 12: CLOSE Transition → "Done", add implementation summary
573+
Step 4: UPDATE Transition → "In Progress", add start comment
574+
Step 5: LINK PR linked in Jira, transition → "In Review"
575+
Step 6: CLOSE Transition → "Done", add implementation summary
576576
```
577577

578578
### Figma (`ENABLE_FIGMA=1`)
579579

580580
```
581-
Step 0: EXTRACT Components + design tokens extracted into orchestration prompt
582-
Step 10: COMMENT "Implementation started" with component list
583-
Step 11: REVIEW Design fidelity checklist in code review
584-
Step 12: COMMENT "Implementation complete" with PR link
581+
Step 1: EXTRACT Components + design tokens extracted into orchestration prompt
582+
Step 4: COMMENT "Implementation started" with component list
583+
Step 5: REVIEW Design fidelity checklist in code review
584+
Step 6: COMMENT "Implementation complete" with PR link
585585
```
586586

587587
---
@@ -674,7 +674,7 @@ Numbers from the project's internal version history. All measurements taken on a
674674
| v1.13.0 | 9 | ~2 (subprocess) | ~30s | Removed Steps 1, 3, 4, 5, 6, 7 |
675675
| v1.14.0 | 8 | 2 (subprocess) | ~15s | Step 0 = template fill + orchestrator (claude CLI) |
676676
| v1.16.0 | 8 | 2 (subprocess) | ~15s | Level 2 purged — standards read from policies/ directly |
677-
| **current** | **8** | **2** | **~15s** | Template fast-path: **~0s** (Step 0 bypassed entirely) |
677+
| **current** | **9** | **2** | **~15s** | Template fast-path: **~0s** (Step 1 skipped entirely) |
678678

679679
**Planning overhead reduced by 80%** (75s → 15s) across 4 versions without any loss of output quality.
680680

@@ -687,7 +687,7 @@ Numbers from the project's internal version history. All measurements taken on a
687687
| AST navigation | Skip irrelevant functions/classes in large files | 40-60% |
688688
| Smart read | Read only the slice the agent needs (not whole file) | 20-40% |
689689
| Context dedup | Deduplicate repeated state / schema definitions | 10-20% |
690-
| **Combined** | Applied across all 8 active steps | **60-85%** |
690+
| **Combined** | Applied across all 9 active steps | **60-85%** |
691691

692692
### Call Graph Intelligence
693693

@@ -696,7 +696,7 @@ The AST-based call graph (578 classes, 3,985 methods across Python, Java, TypeSc
696696
| Capability | Without Call Graph | With Call Graph |
697697
|------------|:-----------------:|:---------------:|
698698
| Impact scope before change | Manual review | Automatic: `hot_nodes`, `danger_zones`, `affected_methods` |
699-
| Breaking change detection | File diff only | Method-level graph diff (before/after Step 10) |
699+
| Breaking change detection | File diff only | Method-level graph diff (before/after Step 4) |
700700
| Complexity scoring | Heuristic (1-10) | `combined_complexity_score` [1-25] = heuristic × 0.3 + graph × 0.7 |
701701
| Multi-language support | Python only | Python (AST) + Java, TypeScript, Kotlin (regex) |
702702

@@ -842,4 +842,4 @@ Key rules:
842842

843843
---
844844

845-
**Version:** 2.1.0 | **Last Updated:** 2026-08-07
845+
**Version:** 2.1.0 | **Last Updated:** 2026-08-08

0 commit comments

Comments
 (0)