Skip to content

Commit 071a41f

Browse files
feat: v0.14.0 — dynamic pipeline by default + broad language packs
Dynamic pipeline (composer) is now default-on, with deterministic language-specialist selection, critical-phase enforcement, and a safe generic fallback for any unknown language. - New web/rust/java/cpp language packs + shell worker/tester agents; language detection and QA gate now cover Go, Python, JS/TS, Rust, Java, C/C++, HTML, and shell. - Workspace-aware QA gate: a stale active_pack no longer forces pytest onto non-Python workspaces; virtualenv/cache dirs are skipped during detection. - Static-web entrypoint guarantee + same-file task collapse (no more "pile of .js files" or "7 tasks editing one file" grind). - Go single-file (no go.mod) gofmt smoke, go vet -short fix, tester passed:true-in-prose tolerance. - Live event severity levels + Studio EventLog severity UI + dynamic-pipeline Settings toggle + LiveView badge. - Bump version to 0.14.0 + changelog + docs.
1 parent 37f1526 commit 071a41f

66 files changed

Lines changed: 2882 additions & 160 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎AGENTS.md‎

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ Slots are user-inserted agent calls around phase anchors:
292292

293293
---
294294

295-
## 5. Built-in Specialists (15 total)
295+
## 5. Built-in Specialists (16 total)
296296

297297
Defined in `pkg/agents/prompts.go` + `pkg/agents/factory.go`:
298298

@@ -314,9 +314,38 @@ Defined in `pkg/agents/prompts.go` + `pkg/agents/factory.go`:
314314
| `placeholder` | Fill placeholders / flag gaps | Yes | 14 |
315315
| `escalate` | Escalate arbitrator | No | 1 |
316316
| `memory` | Distill MEMORY.md | No | 2 |
317+
| `composer` | Assemble a task-specific dynamic pipeline | No | 3 |
317318

318319
Custom agents can override any built-in by placing same-id YAML in `.slmcode/agents/`.
319320

321+
### 5.1 Dynamic Pipeline Composition (`composer`)
322+
323+
The **composer** specialist turns the static pipeline into a per-task pipeline.
324+
When `dynamic_pipeline` is enabled, the composer runs right after context/explore
325+
and emits a structured `Composition` that the engine applies before plan/split:
326+
327+
- **Phases** — which of the 16 phases run for this task (disabled phases become
328+
`when: never`, `enabled: false`; `init`/`skills`/`done` stay structural).
329+
- **Team** — which specialist is bound to each phase (coding roles have tools,
330+
planning roles don't), plus per-role skills.
331+
- **Execute loop** — `default_role`, `reviewer`, `corrector`, `max_waves`.
332+
- **Slots** — extra insertable specialists around phase anchors.
333+
334+
The composed pipeline is saved to `.slmcode/pipeline.dynamic.yaml` (inspection
335+
only — `pipeline.yaml` is never touched) and reported live via the `compose`
336+
phase. A weak/unparsable composition is non-fatal: the run falls back to the
337+
static pipeline.
338+
339+
Enable via config, CLI, or Studio schema:
340+
341+
```bash
342+
slmcode config set dynamic_pipeline true
343+
slmcode run --dynamic "add JWT auth"
344+
```
345+
346+
Model lives in `pkg/composer` (`Composition`, `Parse`, `Apply`); the composer
347+
prompt is `PromptComposer` in `pkg/agents/prompts.go`.
348+
320349
---
321350

322351
## 6. How Stacks Work
@@ -563,6 +592,7 @@ The `/files` page shows a full recursive directory tree. Features:
563592

564593
| Version | Key Changes |
565594
|---------|------------|
595+
| 0.14.0 | **Dynamic pipeline composition** — new `composer` specialist assembles a task-specific pipeline (phases, team, tools, skills, execute loop, slots) via `dynamic_pipeline` config / `--dynamic` CLI / Studio schema; composed pipeline saved to `.slmcode/pipeline.dynamic.yaml`; `pkg/composer` (`Composition`/`Parse`/`Apply`); non-fatal fallback to static pipeline on weak/unparsable composition |
566596
| 0.13.0 | Block CRUD API + Studio GUI editing (blocks/pipelines/agents/skills), agent blocks as runtime roles, default_role honored, phase gating + archived phases, language-pinned prompts (no pytest in Go runs), pipeline validation hardening, blocks new/edit/delete CLI, HTTP tests for block API, live user feedback (GUI + TUI `/feedback`, injected into next agent call), skills↔agents cross-linking in Studio, update-available notifications (TUI banner, `update --check`, `version`, `GET /api/update`, Studio banner) |
567597
| 0.12.2 | e2e test fixes for Vite bundle output, CI builds Studio UI before Go, Homebrew formula sync, docs refresh |
568598
| 0.12.1 | Vite/React/TypeScript Studio UI (`web/` + `make ui-react`), `fast_model` dual-model routing, smarter QA gate, improved tester |

‎Makefile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MODULE := github.com/UnicoLab/slmcode
22
BIN := slmcode
3-
VERSION ?= 0.13.1
3+
VERSION ?= 0.14.0
44
PREFIX ?= $(HOME)/.local
55
GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
66
BUILD_TIME := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)

‎cmd/slmcode/cmd_core.go‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,16 @@ func runCmd() *cobra.Command {
6565
mode, _ := cmd.Flags().GetString("mode")
6666
agent, _ := cmd.Flags().GetString("agent")
6767
pinSkills, _ := cmd.Flags().GetStringSlice("skill")
68+
dynamic, _ := cmd.Flags().GetBool("dynamic")
69+
noDynamic, _ := cmd.Flags().GetBool("no-dynamic")
6870
if mode != "" {
6971
h.Config.Mode = mode
7072
}
73+
if dynamic {
74+
h.Config.DynamicPipeline = true
75+
} else if noDynamic {
76+
h.Config.DynamicPipeline = false
77+
}
7178
if agent != "" {
7279
h.Config.Specialist = agent
7380
h.Config.Mode = config.ModeSpecialist
@@ -90,6 +97,9 @@ func runCmd() *cobra.Command {
9097
if h.Config.Mode == config.ModeSpecialist {
9198
cli.KeyVal("specialist", h.Config.Specialist)
9299
}
100+
if h.Config.DynamicPipeline {
101+
cli.KeyVal("dynamic", "composer assembles a task-specific pipeline")
102+
}
93103
cli.KeyVal("think", fmt.Sprintf("%d passes", h.Config.ThinkPasses))
94104
cli.KeyVal("parallel", fmt.Sprintf("%d", h.Config.MaxParallel))
95105
fmt.Println()
@@ -125,6 +135,8 @@ func runCmd() *cobra.Command {
125135
}
126136
cmd.Flags().String("mode", "", "full | specialist (overrides config)")
127137
cmd.Flags().String("agent", "", "run a single specialist (worker, explorer, …)")
138+
cmd.Flags().Bool("dynamic", false, "run the composer specialist to assemble a task-specific pipeline (default: on)")
139+
cmd.Flags().Bool("no-dynamic", false, "disable the dynamic pipeline (use the static pipeline)")
128140
cmd.Flags().StringSlice("skill", nil, "pin/load skill by name (repeatable); also accepts @skill:name in query")
129141
return cmd
130142
}

‎cmd/slmcode/cmd_util.go‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ func configCmd() *cobra.Command {
195195
cli.KeyVal("backend", c.Backend)
196196
cli.KeyVal("mode", c.Mode)
197197
cli.KeyVal("specialist", c.Specialist)
198+
cli.KeyVal("dynamic_pipeline", fmt.Sprintf("%v", c.DynamicPipeline))
198199
cli.KeyVal("pinned_skills", strings.Join(c.PinnedSkills, ", "))
199200
cli.KeyVal("think_passes", fmt.Sprintf("%d", c.ThinkPasses))
200201
cli.KeyVal("max_parallel", fmt.Sprintf("%d", c.MaxParallel))
@@ -243,6 +244,8 @@ func configCmd() *cobra.Command {
243244
if v != "" {
244245
c.Mode = config.ModeSpecialist
245246
}
247+
case "dynamic_pipeline", "dynamic", "composer":
248+
c.DynamicPipeline = v == "1" || strings.EqualFold(v, "true") || strings.EqualFold(v, "yes") || strings.EqualFold(v, "on")
246249
case "pinned_skills", "skills":
247250
if v == "" || v == "-" {
248251
c.PinnedSkills = nil

‎cmd/slmcode/ui/index.html‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
99
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
1010
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='6' fill='%237c3aed'/><text x='16' y='22' font-family='system-ui' font-weight='700' font-size='18' fill='white' text-anchor='middle'>SL</text></svg>" />
11-
<script type="module" crossorigin src="/assets/index-BJBYh-fV.js"></script>
12-
<link rel="stylesheet" crossorigin href="/assets/index-CHgA9IM9.css">
11+
<script type="module" crossorigin src="/assets/index-B5L19IV9.js"></script>
12+
<link rel="stylesheet" crossorigin href="/assets/index-Djv6tf4Z.css">
1313
</head>
1414
<body class="antialiased">
1515
<div id="root"></div>

‎cmd/slmcode/version.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package main
44
//
55
// go build -ldflags "-X main.Version=0.5.0 -X main.SourceRoot=/path -X main.GitCommit=abc -X main.BuildTime=…"
66
var (
7-
Version = "0.13.1"
7+
Version = "0.14.0"
88
SourceRoot = "" // absolute path to the slmcode checkout used to build this binary
99
GitCommit = "unknown"
1010
BuildTime = "unknown"

‎docs/agents.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 🧩 Agents
22

3-
Fourteen specialists. Scoped packs. No “hold the monorepo in your head” cosplay. 🎭
3+
Sixteen specialists. Scoped packs. No “hold the monorepo in your head” cosplay. 🎭
44

55
<div class="slm-banner" markdown>
66
<span class="slm-banner__emoji">🧬</span>
@@ -32,6 +32,7 @@ see <a href="providers.md">Providers</a>. Budget diplomacy is a feature.
3232
| `placeholder` | ✅ + `find_models` / `mcp_call` | status + gaps | Fill stubs / flag precise gaps 🩹 |
3333
| `escalate` | — | action JSON | HITL timeout arbitrator (retry/re-scope/…) ⚖️ |
3434
| `memory` | — | bullets | Learn 💾 |
35+
| `composer` | — | pipeline JSON | Assemble a task-specific pipeline (dynamic_pipeline) 🎯 |
3536

3637
!!! note "🧰 Coding tools"
3738
Coding agents share `ws_*` + `git_*` plus **`find_models`** (auth-gated catalog)

‎docs/architecture.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ If you stuff the whole repo into context, don’t be surprised when the model na
3131
cmd/slmcode CLI + embedded Studio (go:embed ui/)
3232
pkg/orchestrator Pipeline runner + coordinator + sessions
3333
pkg/pipeline Config-driven phases / slots / loop agents
34+
pkg/composer Dynamic pipeline composition (Composition/Parse/Apply)
3435
pkg/blocks Building block registry + bundled YAML presets
3536
pkg/loop Parallel execute → review → correct
3637
pkg/agents Specialist prompts + custom YAML factory

‎docs/blocks.md‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,52 @@ Pipeline: react | Agents: react-worker, react-tester | Quality: react
9595
- **Tester**: `npm run lint` → `tsc --noEmit` → `npm test` → `npm run build`
9696
- **QA Gate**: `npm test --silent`
9797
98+
### 🌐 Static Web (HTML/CSS/JS)
99+
100+
```
101+
Pipeline: web | Agents: web-worker, web-tester | Quality: web
102+
```
103+
104+
- **Pipeline**: Static-browser-aware with `web-tester` agent
105+
- **Worker**: Always produces a usable `index.html` entrypoint + referenced assets
106+
- **Tester**: Verifies a non-empty HTML entrypoint, resolved asset refs, `node --check` each `.js`
107+
- **QA Gate**: non-empty `.html` entrypoint exists (no pytest / npm test forced)
108+
109+
### 🦀 Rust
110+
111+
```
112+
Pipeline: rust | Agents: rust-worker, rust-tester | Quality: rust
113+
```
114+
115+
- **Worker**: cargo module-aware, smokes with `cargo build --quiet`
116+
- **Tester**: `cargo build` → `cargo test` → `cargo clippy` (optional)
117+
- **QA Gate**: `cargo test --quiet`
118+
119+
### ☕ Java
120+
121+
```
122+
Pipeline: java | Agents: java-worker, java-tester | Quality: java
123+
```
124+
125+
- **Worker**: Maven/Gradle-aware, smokes with `mvn -q -DskipTests compile`
126+
- **Tester**: `mvn -q test` (or `./gradlew test`)
127+
- **QA Gate**: `mvn -q test`
128+
129+
### ⚙️ C/C++
130+
131+
```
132+
Pipeline: cpp | Agents: cpp-worker, cpp-tester | Quality: cpp
133+
```
134+
135+
- **Worker**: CMake/Make-aware, smokes with `cmake --build build`
136+
- **Tester**: `cmake --build build` → `ctest` (when present)
137+
- **QA Gate**: `cmake --build build`
138+
139+
### 🐚 Shell (agents only)
140+
141+
`shell-worker` / `shell-tester` — for Bash/shell scripts (`bash -n` + `shellcheck`).
142+
No standalone pack; the generic pipeline selects them when the workspace is shell.
143+
98144
---
99145
100146
## CLI Commands

‎docs/changelog.md‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,37 @@
11
# Changelog
22

3+
## v0.14.0 — Dynamic Pipeline, Broad Language Support & Live Log Severity
4+
5+
### Highlights
6+
- **Dynamic pipeline is now the default** — the `composer` specialist assembles a
7+
task-specific pipeline (phases, team, tools, skills) before every run; disable via
8+
`dynamic_pipeline: false`, `slmcode run --no-dynamic`, or the Studio Settings toggle.
9+
The composer deterministically upgrades generic `worker`/`tester` to the matching
10+
language specialist, enforces that `execute` + `test` always run, and falls back to a
11+
safe generic pipeline for any unknown language.
12+
- **Six new language packs** — `web` (static HTML/CSS/JS), `rust`, `java`, `cpp`
13+
(full pipeline + quality + worker/tester), plus `shell` worker/tester agents.
14+
`DetectProjectLanguage`/`langHint`/splitter guidance now cover Go, Python, JS/TS,
15+
Rust, Java, C/C++, HTML, and shell.
16+
- **Static-web deliverables are guaranteed** — HTML/browser/game queries always get an
17+
`index.html` (or the splitter's chosen `.html`) entrypoint injected; a pile of
18+
disconnected `.js` files with no page can no longer happen.
19+
- **QA gate is workspace-aware** — a stale `active_pack` (e.g. `python` from a prior
20+
run) no longer forces pytest onto a Go/JS/HTML workspace; virtualenv/cache dirs are
21+
skipped during quality detection; a lone `.go` file without `go.mod` uses a
22+
module-free `gofmt -e` smoke, and the `go test`→`go vet` fast-path no longer emits
23+
an invalid `-short` flag.
24+
- **Live log severity** — events now carry a `level` (`info|warning|error|success|problem`);
25+
the Studio Event Log renders severity badges, colors, and a Problems filter with
26+
error/warning/success counts.
27+
- **Tester finalize is more forgiving** — an explicit `passed:true` anywhere in the
28+
finalize (not just inside the parsed JSON object) is now honored, reducing false
29+
"missing passed:true" rejections.
30+
- **Same-file task collapse** — many worker tasks editing one self-contained file are
31+
collapsed into a single worker (fixes the "7 tasks editing index.html" grind that
32+
caused review/correction loops).
33+
- **Shell whitelist** extended for cargo/mvn/gradle/ctest/gcc/clang/shellcheck.
34+
335
## v0.13.1 — 2026-08-10
436

537
- Automate Homebrew formula checksum sync in the release pipeline

0 commit comments

Comments
 (0)