Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1b963bf
Update shared AI CLI base layer
May 23, 2026
fcbf318
Add devBench spec workflow tooling
May 23, 2026
99f8bda
Add Sonar devBench helpers
May 23, 2026
7a72b38
Refresh dev bench inventory
May 23, 2026
21cdc35
Address workbench cleanup review feedback
May 23, 2026
373a7e8
Address devcontainer review feedback
May 23, 2026
437a5b1
Add Graphite CLI to devBench base
May 23, 2026
d7c8457
Add container-safe Sonar CLI env helper
May 24, 2026
d52f633
Group Sonar MCP containers under dev-benches
May 24, 2026
0fa888d
chore: support in-repo Speckit worktree roots
May 24, 2026
b62366d
feat: add Speckit dashboard pane to yolo
May 25, 2026
9ddf3c4
feat: persist cta dashboard tooling in devBench
May 26, 2026
e021998
fix: make cta dashboard clicks locale-safe
May 28, 2026
9657ed1
Add no-cache cascade rebuild support
May 29, 2026
648f8a4
Address PR review findings
May 29, 2026
8f4ab4a
Address Speckit review follow-ups
May 29, 2026
a33a22f
Address late PR review findings
May 29, 2026
493f8d6
Address remaining PR review issues
May 29, 2026
bd360d6
Resolve remaining PR review feedback
May 30, 2026
5c25003
Resolve final PR review threads
May 30, 2026
bf481ca
Address PR review hardening issues
May 31, 2026
77a06ea
Fix latest Copilot review findings
May 31, 2026
c9e27af
Align per-repo ct fallback defaults
May 31, 2026
6785fa7
Address latest reviewer findings
May 31, 2026
d27d3e3
Address follow-up reviewer findings
May 31, 2026
5c2d064
fix(speckit-dashboard): use dependency-aware blocked markers
May 31, 2026
95ee771
Address launcher reviewer follow-ups
May 31, 2026
6613d3e
Address provider priority reviewer findings
May 31, 2026
1324168
Address Speckit bootstrap reviewer findings
May 31, 2026
9c4d587
Address swarm review feedback
Jun 1, 2026
d432219
Install Claude review workflows during setup
Jun 1, 2026
3298e9d
Document async clarify workflow protocol
Jun 1, 2026
a9d124c
Enhance Speckit dashboard workflow tracking
Jun 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ devBenches/flutterBench/
devBenches/frappeBench/
devBenches/javaBench/
devBenches/dotNetBench/
devBenches/pythonBench/
devBenches/pyBench/
devBenches/phpBench/

# Installation tracking (local only)
.installed-benches.json
Expand All @@ -17,11 +18,23 @@ config/version-manifest.json

# Common ignores
.DS_Store
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 *[MEDIUM] .gitignore adds pycache/claude rules but still has no .env / .backup / secret patterns

This PR touches .gitignore (adding pycache/, .py[cod], .claude/dashboard.md, .claude/speckit-history.md) but does not add any ignore rule for environment/secret files even though the same PR introduces a SonarQube workflow that reads tokens from ~/.config/sonarqube/sonar.env (see devBenches/base-image/files/sonarqube/sonar-env) and leaves a tracked bench-config.json.backup. With no '.env', '.env', 'sonar.env', '*.backup', or 'secrets' pattern, a developer who drops a sonar.env or a *.backup containing a SONAR_TOKEN into the tree will have it committed silently. Since the PR is already editing this file and adding a token-consuming feature, the env/secret ignores belong here.

Suggested fix: Add patterns such as '.env', '.env', 'sonar.env', '.backup', '*.bak', and 'secrets/' to .gitignore in this same change.

__pycache__/
*.py[cod]
*.log
*.tmp
node_modules/

# Secret and machine-local environment files. Keep template examples tracked.
.env
.env.*
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] The added env-ignore block (lines 26-29: .env, .env.*, *.env, sonar.env) has two real problems, plus one correction to the original finding.

1. Redundancy. *.env (line 28) subsumes .env (line 26), sonar.env (line 29), and the pre-existing config/registry.env (line 16), so those three lines are dead. Verified:

$ git check-ignore -v -- .env sonar.env config/registry.env
.gitignore:28:*.env	.env
.gitignore:29:sonar.env	sonar.env   # (28 also matches)
.gitignore:28:*.env	config/registry.env

2. Does not protect already-tracked secrets. This repo already tracks devBenches/cppBench/.env, devBenches/goBench/.env, and devBenches/javaBench/.env. .gitignore does not untrack committed files, so these (and any secrets in them) remain tracked. If the intent is to stop committing them, also run git rm --cached on those three paths.

3. Correction — .env.* DOES match *.env.example templates. The original finding claimed templates are "correctly NOT matched … so no template breakage occurs." That is wrong. The newly added .env.* rule (line 27) matches .env.example:

$ git check-ignore -v -- somedir/.env.example
.gitignore:27:.env.*	somedir/.env.example

There are 7 tracked *.env.example files (e.g. config/registry.env.example, devBenches/.devcontainer/.env.example). They survive only because they were committed before this rule; any new .env.example (or .env.local, .env.production, etc.) will now be silently ignored and refused by git add. If templates must stay committable, add a negation after the env rules:

!*.env.example

Suggested cleanup (collapse redundancy, keep templates committable):

Suggested change
.env.*
*.env
.env.*
!*.env.example

and separately git rm --cached devBenches/cppBench/.env devBenches/goBench/.env devBenches/javaBench/.env if those should no longer be tracked.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] New .env.* pattern ignores committed .env.example template files

The newly added pattern .env.* (line 27) matches the dot-prefixed .env.example template files this repo tracks on purpose (devBenches/.devcontainer/.env.example, devBenches/cppBench/.devcontainer/.env.example, devBenches/goBench/.devcontainer/.env.example, devBenches/devcontainer.test/.env.example, devcontainer.test/.env.example, sysBenches/devcontainer.test/.env.example).

Verified with git check-ignore:

.gitignore:27:.env.*    newBench/.devcontainer/.env.example
.gitignore:27:.env.*    sub/.env.example

Already-tracked files keep working (git skips ignore checks for tracked paths), but this is a multi-bench scaffolding repo whose purpose is creating new benches. Any new bench that adds a .env.example template will be silently un-addable — git add skips it — which is exactly the file users need committed to know what env vars to set.

Note: line 28 *.env does NOT cause this (it only matches paths ending in .env), so non-dot examples like config/registry.env.example are safe. The problem is specifically .env.* matching .env.example.

Fix: re-allow the example templates after the ignore patterns (order matters — un-ignore lines must come after the ignore):

.env
.env.*
*.env
!.env.example

(.env.example is the only name at risk here; add !*.env.example too if you ever introduce non-dot-prefixed example files.)

*.env
!.env.example
!.env.sample
!.env.template
*.backup
*.bak
*.bak.*
secrets/
*.swp
*.swo

Expand All @@ -38,4 +51,6 @@ bioBenches/gentecBench/
logs/
.codex
.codex/
.claude/dashboard.md
.claude/speckit-history.md
sysBenches/opsBench/
154 changes: 154 additions & 0 deletions PROTOCOL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Asynchronous Clarify Protocol

A custom clarify step for [GitHub Spec Kit](https://github.com/github/spec-kit) +
Claude Code. It fans question generation out across reviewer angles, logs the questions
to a file, and finishes clarify **automatically** once they are answered — no manual
re-running.

## Why

Spec Kit's stock `/speckit.clarify` is synchronous: it asks, you answer, all in one
sitting. Real clarification has human latency — a domain expert may take a day to answer
a compliance question. This protocol decouples **question generation** (cheap, parallel,
done by AI) from **answering** (slow, human) from **application** (one edit to `spec.md`),
and uses a polling loop so the loop, not you, watches for completion.

## The four files

| File | Role |
|------|------|
| `.claude/commands/openClarify.md` | Orchestrator. Resolves the feature dir, initializes the log, triggers the generation fan-out, registers the poll loop. Never answers questions. |
| `.claude/commands/openClarify-resume.md` | Poll tick. Reads the log and branches cheaply; only the all-answered tick edits `spec.md`. Enforces the critical-class human gate. |
| `templates/clarify-log.template.md` | The log schema: two top-of-file sentinels + per-question blocks. |
| `PROTOCOL.md` | This document. |

## Data flow

```
/openClarify [feature-dir]
├─ verify spec.md exists
├─ init clarify-log.md from template (GENERATION: PENDING, CLARIFY: IN_PROGRESS)
├─ workflow: fan out reviewer angles ──┐
│ data-model ┐ │ each appends OPEN question blocks
│ edge-cases ┤ │ merge + dedupe, cap 25
│ security-compliance ┤ │ then flip GENERATION: COMPLETE
│ testability ┤ │
│ integration ┘ │
└─ register /loop 10m /openClarify-resume <dir>

... humans answer blocks in clarify-log.md over time ...

/openClarify-resume <dir> (every 10 min)
├─ log missing? → no-op
├─ CLARIFY: COMPLETE? → no-op, stop loop
├─ GENERATION != COMPLETE → no-op (sentinel guard: no early firing)
├─ any status: OPEN? → no-op (still waiting)
├─ critical answered by architect-ai? → no-op (human escalation)
└─ all answered, criticals human-signed → edit spec.md, CLARIFY: COMPLETE, stop loop
```

## The log schema

Two **sentinels** at the top of `clarify-log.md` are the entire coordination contract:

- `GENERATION: PENDING | COMPLETE` — set `COMPLETE` only when the fan-out has written
every question. Until then the poller refuses to act.
- `CLARIFY: IN_PROGRESS | COMPLETE` — set `COMPLETE` only after answers are applied to
`spec.md`.

Each question is a block:

```
## Q3
- id: q3
- status: OPEN # OPEN | ANSWERED
- class: normal # normal | critical
- agent: security-compliance # which reviewer angle raised it
- question: How long is PHI retained after account deletion?
- answer:
- answered_by: # human | architect-ai
- ts:
```

## Three design guarantees

1. **Sentinel guard against early firing.** The poller treats `GENERATION: COMPLETE` as a
precondition. A log that is mid-generation can momentarily show "zero OPEN questions"
simply because no questions have been written yet — the guard stops the poller from
misreading that as "all answered" and prematurely editing `spec.md`.

2. **Critical-class human escalation.** A `class: critical` question (clinical / regulated /
safety-impacting) answered by `architect-ai` does **not** clear. Completion blocks until
a human re-answers or confirms it. The AI can draft; only a human signature releases the
gate.

3. **Cheap read-and-branch ticks.** Nearly every poll tick just greps the sentinels and a
handful of `status:` lines, then exits. Exactly one tick — the one that sees everything
answered and all criticals human-signed — does the expensive `spec.md` edit. Polling
every 10 minutes is therefore nearly free.

## Relationship to stock `/speckit.clarify` — audit pass

This protocol **does the clarification work**, then stock `/speckit.clarify` runs **after**
as an **audit**, not as the primary clarifier.

Because `/openClarify-resume` writes answers in stock's canonical shape — a
`## Clarifications` section with `### Session YYYY-MM-DD` and `- Q: … → A: …` bullets, plus
the answer folded into the relevant spec section — a subsequent stock run sees those points
as already resolved. Stock decides what to ask by scanning **spec sections** against its
coverage taxonomy (Clear / Partial / Missing), so the folding in §3b is what actually makes
the audit quiet, not the log bullets.

**How to use the audit:** after our protocol marks `CLARIFY: COMPLETE`, run stock
`/speckit.clarify` (the `speckit-clarify` skill) a few times.

- **No new questions** → our five reviewer angles covered the spec to stock's standard. Proceed to `/speckit.plan`.
- **New questions** → a real coverage gap. Most will land in taxonomy categories our angles
don't target: **functional scope & behavior, interaction/UX flow, non-functional
(performance, scalability, reliability, observability), constraints & tradeoffs, and
terminology consistency**. Our angles cover data-model, edge-cases, security/compliance,
testability, and integration — so those five categories are the expected blind spots.

Treat stock's output as a **regression check on our generation coverage**. If a category
keeps surfacing, add a reviewer angle for it to the fan-out in `/openClarify`.

> Note: in this environment stock clarify is overridden (see `~/.claude` global config) to
> ask up to **25** questions in **block form**, written to `<FEATURE_DIR>/clarify-questions.md`
> — so the audit produces a diffable file rather than a one-at-a-time interactive loop.

```
/openClarify → (async answers) → resume applies + canonical format → CLARIFY: COMPLETE
/speckit.clarify ×N (audit)
new questions? → new clarify cycle ; else → /speckit.plan
```

## Known gaps / operational notes

- **Generation script is authored on first run.** The `workflow` keyword lets the Claude
Code runtime author the fan-out's internal script the first time `/openClarify`
runs. **Save that run as `/openClarify-generate`** so subsequent features reuse it
instead of re-authoring the fan-out each time.

- **`/loop` is session-scoped with a 3-day cap.** It only survives while the session is
alive and stops after ~3 days. For human turnaround longer than that, swap the in-session
loop for an external scheduler:

```
cron + claude -p /openClarify-resume <dir>
```

e.g. a crontab entry running `claude -p "/openClarify-resume specs/my-feature/"` every
15 minutes, which survives restarts and arbitrary human latency.

## Usage

```
# 1. start (defaults to specs/<current-branch>/)
/openClarify

# 2. humans edit clarify-log.md, filling answer / answered_by / status: ANSWERED

# 3. nothing else to do — the loop applies answers to spec.md and stops itself
```
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ Safe to run repeatedly. Installed benches show `✓ up to date` and are skipped.
## Docker Image Layers

```
Layer 0: workbench-base:latest — Ubuntu 24.04 + git, zsh, curl, AI CLIs, bun
├─ Layer 1a: dev-bench-base:latest — Python, Node.js LTS, npm, dev tools, testing tools, Playwright Chromium
Layer 0: workbench-base:latest — Ubuntu 24.04 + git, zsh, curl, shared AI CLIs, bun
├─ Layer 1a: dev-bench-base:latest — Python, Node.js LTS, npm, dev tools, OpenSpec, spec-kit, testing tools, Playwright Chromium
│ ├─ Layer 2: cpp-bench:latest — GCC, CMake, vcpkg
│ ├─ Layer 2: dotnet-bench:latest — .NET SDK 8/9
│ ├─ Layer 2: flutter-bench:latest — Flutter SDK, Dart, Android tools
│ ├─ Layer 2: frappe-bench:latest — MariaDB client, Redis, Nginx, bench CLI (Node.js 20)
│ ├─ Layer 2: java-bench:latest — OpenJDK 21, Maven, Gradle, Spring CLI
│ ├─ Layer 2: python-bench:latest — Python dev tools (thin layer on 1a)
│ ├─ Layer 2: php-bench:latest — PHP 8.3, Composer, PHPUnit, Xdebug
│ ├─ Layer 2: py-bench:latest — Python dev tools (thin layer on 1a)
│ └─ Layer 2: go-bench:latest — Go toolchain
├─ Layer 1b: sys-bench-base:latest — Kubernetes, Terraform, cloud CLIs
│ └─ Layer 2: cloud-bench:latest — Cloud admin tools
Expand Down Expand Up @@ -109,7 +110,8 @@ workBenches/
│ ├── frappeBench/ ← Frappe/ERPNext bench (opensoft/frappeBench)
│ ├── goBench/ ← Go bench (opensoft/goBench)
│ ├── javaBench/ ← Java bench (opensoft/javaBench)
│ └── pythonBench/ ← Python bench (opensoft/pythonBench)
│ ├── phpBench/ ← PHP bench (opensoft/phpBench)
│ └── pyBench/ ← Python bench (opensoft/pyBench)
├── sysBenches/
│ ├── base-image/ ← Layer 1b: sys-bench-base Dockerfile
│ ├── cloudBench/ ← Cloud admin bench (opensoft/cloudBench)
Expand Down Expand Up @@ -187,6 +189,7 @@ npm global packages install to `~/.npm-global` (no sudo required).
| frappeBench | [opensoft/frappeBench](https://github.com/opensoft/frappeBench) |
| goBench | [opensoft/goBench](https://github.com/opensoft/goBench) |
| javaBench | [opensoft/javaBench](https://github.com/opensoft/javaBench) |
| pythonBench | [opensoft/pythonBench](https://github.com/opensoft/pythonBench) |
| phpBench | [opensoft/phpBench](https://github.com/opensoft/phpBench) |
| pyBench | [opensoft/pyBench](https://github.com/opensoft/pyBench) |
| gentecBench | [opensoft/gentecBench](https://github.com/opensoft/gentecBench) |
| simBench | [opensoft/simBench](https://github.com/opensoft/simBench) |
Loading