A governed multi-agent SDLC pipeline for Claude Code and Qwen Code — a ground-up rewrite of ai-sdlc-harness.
> /plugin marketplace add MostAshraf/ai-sdlc-harness> /plugin install ai-sdlc-harness@ai-sdlc-harness
What's inside
A governed multi-agent SDLC pipeline for Claude Code and Qwen Code — a ground-up rewrite of ai-sdlc-harness. Drives a real engineering workflow — fetch → scope-confirmed plan → independent plan review → proven-red TDD → review → security → PR → comment rounds → reconcile → metrics — across one or many repos. No application code lives here: only the pipeline manifest, the Python core that enforces it, and the agents, skills, and hooks that run it.
| Command | Purpose |
|---|---|
/init-workspace | One-time setup interview: provider, repos, discovered toolchain, verification gate |
/dev-workflow <work-item-id> | Take a work item from requirements to merged PR end-to-end |
/story-workflow <command> <work-item-id> | Shape a story's quality before it's built: analyze · refine · improve · groom |
/workflow-status | Read-only dashboard: cursor, tasks, gates, flagged events, run-health verdict per run |
/workspace-config | Change one config section without re-running the interview |
/add-repo | Register one new repo into an already-bootstrapped workspace |
/migrate-workspace | Adopt a v2.x workspace: config carries over, run history stays archived in place |
/repo-map-refresh | Regenerate the auto-generated codebase map the planner grounds its plans in |
The original harness works, but almost all of its accumulated complexity compensates for one root cause: orchestration logic lived in markdown prose an LLM had to faithfully execute, with hooks bolted on to catch the cases where it didn't. The rewrite moves every mechanical rule into code that just runs, and reserves the model for judgment.
| Concern | ai-sdlc-harness (v2.x) | ai-sdlc-harness (v3.0) |
|---|---|---|
| Pipeline definition | Prose phase files the orchestrator re-derives every run; a separate hardcoded copy in guard scripts | One declared manifest (pipeline/manifest.yaml) read by both the orchestrator and the enforcement layer — no second copy to drift |
| Git operations | Raw git calls reverse-engineered after the fact by shlex-parsing hooks | Owned entry points (harness commit / merge-task / sync-branch / push …); the raw verbs are blocked outright |
| Workflow state | tracker.md, honor-system updates | HMAC-chain-sealed state.yaml + append-only ndjson evidence ledgers — tamper-evident, exit 3 on out-of-band edits |
| Human gates | The model reads your reply and acts on it | A hook captures your reply verbatim; deterministic code parses the decision — the model cannot approve on your behalf |
| TDD enforcement | Separate Tester and Developer subagents per task (token/latency tax) | One developer writes test + implementation; harness verify-red proves the failure and blob-SHA-locks the test set until completion |
| Providers | Markdown capability docs an agent must correctly read | Code modules behind one interface, each held to a shared contract test |
| Agents | 7 role files fusing permissions with procedure | 3 fixed tool-grant shapes (planner / developer / reviewer); procedure lives in shared step files |
| File-size budgets | Retrofitted after files passed 400 lines | ~100/200-line budget enforced from day one (tools/budget_check.py) |
This repo is dual-native: a native Claude Code plugin (.claude-plugin/) and a native Qwen Code extension (qwen-extension.json) in one repository. Install it under either CLI — no conversion step is needed.
/plugin marketplace add MostAshraf/ai-sdlc-harness
/plugin install ai-sdlc-harness@ai-sdlc-harness
The repeated name isn't a typo — it's plugin-name@marketplace-name, and here they match. Restart Claude Code (or /reload-plugins) so the skills and hooks load. There's a non-interactive equivalent too, if you'd rather script it:
claude plugin marketplace add MostAshraf/ai-sdlc-harness
claude plugin install ai-sdlc-harness@ai-sdlc-harness # --scope user|project|local
qwen extensions install MostAshraf/ai-sdlc-harness
For development with a live link to your working copy:
qwen extensions link /path/to/ai-sdlc-harness
Restart Qwen Code so the skills, agents, and hooks load.
Then, inside Claude Code or Qwen Code:
/init-workspace
The interview asks only what it must (provider, repos), discovers your toolchain (proposing the test command it found), and offers default for everything else. It bootstraps a plugin-owned Python venv (PEP 668-safe — no system-python changes), ends with a verification gate — every check passes or you don't proceed — and writes per-section config under .claude/context/, a permission allowlist into .claude/settings.json (no manual settings.json editing needed), and the bootstrap marker.
| Dependency | Why |
|---|---|
| Claude Code or Qwen Code | The CLI that runs this harness. Install Claude Code from claude.ai/code or Qwen Code from qwen-code. |
| Git | Branch management, per-task worktree isolation, owned commits. |
| Python 3.10+ | The entire core is Python. /init-workspace creates the plugin's own venv with PyYAML as its first step; until then the guards print a one-line notice and stand down. |
| Provider CLI, authed (optional) | gh auth login / glab auth login / az login, if using that provider (github-projects additionally needs the project OAuth scope). MCP providers need their server connected. The local-markdown provider needs nothing at all. |
Target repos must be cloned locally, clean, and on their default branch when registered — the harness does not clone them. A registered repo does not have to be a whole checkout: any subtree of one can be registered as a repo in its own right, which is how a monorepo's stacks are set up (see Multi-repo runs). No language prerequisites; toolchains are discovered.
This repo carries a qwen-extension.json at root, making it a native Qwen Code extension — no Claude-plugin conversion is needed. Install via qwen extensions install or qwen extensions link (see Install above), then run /init-workspace inside a Qwen Code session.
When /init-workspace runs under Qwen Code (detected when either QWEN_CODE, which Qwen sets for shell-tool children, or QWEN_CODE_CLI, which it sets for hook subprocesses, is present — measured on 0.22.2):
.qwen/settings.json. Qwen Code reads its allowlist from .qwen/settings.json rather than .claude/settings.json; the init step writes both so background agents run unprompted under either CLI. A workspace bootstrapped under Claude Code and later opened under Qwen Code has no .qwen/settings.json yet — re-run /workspace-config (or the permission-write step) once under Qwen Code to create it.CLAUDE_PLUGIN_ROOT is exported via the .qwen/settings.json env block (self-healing on reinstall). Native Qwen does not export this variable or substitute it in markdown, so the init step's bootstrap probe resolves the plugin root on first run and prints it for the model to substitute textually in subsequent commands (each Bash call is a fresh subprocess, so a shell export doesn't persist). The env export written at step 6 takes over from the next session. A stale value from a prior install self-heals when the stored path no longer exists on disk; a deliberate user pin pointing at a real directory is preserved..qwen/context is symlinked to ../.claude/context (relative, so a workspace move doesn't dangle it). This is an affordance for the converted-install path only: Qwen's Claude-plugin converter rewrites .claude/ → .qwen/ in installed markdown, so skills point the model at .qwen/context/… while the CLI reads .claude/context/. The symlink makes both land in the single physical tree. Under native installs, markdown keeps literal .claude/context/ paths that already match the physical tree, so the symlink is harmless when unused. The write guard additionally accepts the literal .qwen/context/ prefix as a confined root. Windows needs Developer Mode or an admin shell to create symlinks; if creation fails or a real file occupies the path, init prints a visible warning (no silent data loss).tools: list. Each agent's frontmatter carries both Claude names (Read, Write, Edit, Bash) and Qwen display names (ReadFile, WriteFile, Shell). Claude Code grants the names it recognizes and silently ignores the rest; Qwen Code does the same in reverse. The reviewer stays read-only on both platforms (no write spelling of either dialect).subagent_models overrides are honored in Claude Code sessions but cannot be applied at spawn under Qwen Code — its agent tool has no model parameter, so subagents run on the session model. The harness surfaces this at spawn time (via resolve-model) and at config time (via init-section --section overrides), relaying a notice to the user the first time it fires in each run. The advanced manual escape hatch is a project-level .qwen/agents/<name>.md shadow file with a model: line — a full copy that replaces the plugin's agent wholesale and must be manually re-synced after plugin upgrades.Folder-trust note: if you enable Qwen Code's security.folderTrust.enabled and the workspace is untrusted, Qwen drops workspace settings entirely — both the env export and the permission allowlist go inert, surfacing as permission prompts reappearing. Trust enforcement is off by default; trust the workspace (or keep it off) to keep the dual-write live.
FAQ
ai-sdlc-harness is a Claude Code plugin with 8 hand-picked skills for development work, indexed on Flowy. Install it with the command on its page. It includes add-repo, dev-workflow, init-workspace. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it