Workspace config
Change one config section (overrides / provider / language / repos) on an already-bootstrapped workspace, without re-running the full /init-workspace interview. USER-ENTRY — invoke only when the user explicitly runs /workspace-config; never autonomously, never from a subagent (guard-enforced).From its SKILL.md
npx -y skills add MostAshraf/ai-sdlc-harness --skill workspace-configAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 15 stars15 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.1 KB, as published. Nobody here has run it
workspace-config
Every command below is ${CLAUDE_PLUGIN_ROOT}/bin/harness <verb> … — run it
yourself via Bash. Never ask the user to type a harness command; the user
only answers the questions below.
Not this skill's job: registering a brand-new repo (that's /add-repo —
discovery, duplicate-name/path refusal, permission-allowlist refresh; this
skill only changes an already-registered repo's path/name/test_cmd), and
first-time setup (/init-workspace's interview).
0 · Confirm the workspace is actually bootstrapped
Resolve the plugin root if not already set (native Qwen first run —
each Bash call is a fresh subprocess, so the probe prints the path for
textual substitution). Same resolution logic as /init-workspace step 0:
R="${CLAUDE_PLUGIN_ROOT:-}"; [ -z "$R" ] && {
for p in "$HOME/.qwen/extensions/ai-sdlc-harness/bin/harness" \
"$HOME/.qwen/extensions/ai-sdlc-harness/.qwen-extension-install.json"; do
[ -e "$p" ] && { case "$p" in *install.json)
R=$(python3 -c "import json,sys;print(json.load(open(sys.argv[1])).get('source',''))" "$p");;
*) R=$(cd "$(dirname "$p")/.." && pwd);; esac
[ -x "$R/bin/harness" ] && break; }; done; }
[ -x "$R/bin/harness" ] || { echo "ERROR: set CLAUDE_PLUGIN_ROOT to the dir with bin/harness" >&2; exit 1; }
echo "PLUGIN_ROOT=$R"
Use the printed path in place of ${CLAUDE_PLUGIN_ROOT} below.
Read .claude/context/overrides.yaml. Missing, or no bootstrap_completed
key: /init-workspace never finished — stop and send the user there.
Proceeding anyway reports "the change is live," and the user only learns
otherwise later, at a confusing bootstrap incomplete refusal the next
time /dev-workflow runs.
1 · Ask which section, and what's changing
overrides— any top-level key inconfig/defaults/*.yamlother thanprovider/repos/language(status_mapping,subagent_models,quick_mode,naming+change_types,review_rounds,stall,repo_mapstaleness N,review_policy,security.scan_cmd/severity_order, …). Most single-setting changes land here.provider— work-item/git provider + specifics (stories_dir,github_repo,github_project+github_project_owner(+github_project_repo, which keeps board ids bare issue numbers),ado_org,ado_project, …).language— per-repotest_cmd/coverage_cmd/quarantine, underlanguage.repos.<name>(not the whole-workspacetest_paths/test_closure). Quarantine drops a known-failing spec unrelated to any run from every test + coverage command (reason+sincerequired,init-verifygates the shape, each run flags the exclusions):{"language": {"repos": {"fe": {"test_cmd": "npx vitest run", "quarantine": {"exclude_template": "--exclude {test}", "tests": [{"test": "t/a.spec.ts", "reason": "fails on main", "since": "2026-07-22"}]}}}}}—languageis a full REPLACE (§2): re-send every repo's existing keys.repos— repointing or renaming an existing entry's path. A path may be a checkout root or a subtree of one (<checkout>/frontend) — that's how a monorepo's logical repos are registered, one entry per root.
2 · Read the current section before writing it
overrides deep-merges — a call only needs the keys actually changing:
init-section --section overrides --json '{"quick_mode": {"loc_max": 50}}'.
If the init-section result carries a notice key, relay its text to the
user verbatim.
Exception: a list-valued key (review_policy is the only shipped one)
still replaces wholesale — dicts recurse, list items don't — so resend the
whole list, including entries you're not changing, or one silently vanishes.
provider/language/repos are full-replace: the write IS the whole
file. Read .claude/context/<section>.yaml first (Read tool, never a Bash
one-liner), splice in the change, resend the complete set — a partial
payload, or a forgotten self-nesting ({"repos": {...}} — overrides is
the one flat, non-nested exception), silently drops every entry you didn't
restate. For repos/language this is NOT caught by init-verify if it
zeroes the whole map (step 4 covers what verify does check).
Known gap: overrides only adds/updates keys, never unsets — removing
one needs a direct edit to overrides.yaml; say so rather than improvising.
3 · Confirm a test_cmd change by running it, and mind two risks
Confirm any test_cmd change by actually running it in that repo — same
rule /add-repo//init-workspace follow, never accept it unconfirmed. Run
it at the registered path, which may be a subtree of a checkout: test
commands run with the registered path as their cwd, so a command
confirmed from the enclosing checkout root proves nothing about that logical
repo. Repointing an entry between a checkout root and a subtree of it is a
legal repos write (init-verify accepts either), but it moves the command's
cwd — re-confirm that repo's test_cmd in the same pass.
Known risks: (1) init-section --section repos has none of /add-repo's
collision checks — a duplicate name (case-insensitive: collides on-disk on
a case-insensitive filesystem) or a path under two names (misattributes
test_cmd/scan_cmd) writes cleanly; check the full map yourself before
sending it. Renaming also orphans language.repos.<old-name>,
security.scan_cmd.<old-name>, and .claude/context/repo-map/<old-name>/
— carry them to the new name or tell the user to. (2) Avoid repointing a
path or changing a test_cmd while a /dev-workflow run has in-flight
tasks against that repo — resolution is by exact registered path, so a
run mid-flight can start failing with a confusing "no test command" error.
4 · Re-verify if the section could affect verify or permissions
init-verify covers provider, repos (≥1 registered, each path inside a
git work tree — a checkout root or any subtree of one, which is how a
monorepo's logical repos register), and language (test_cmd runnability)
— not overrides. A repo:<name> detail reading <path> (subtree of <checkout>) is a pass stating where the git tree actually is, not a
failure.
provideronly: re-runinit-verify, fix any failure.repos(a path) orlanguage(atest_cmdbinary): re-runinit-verify, theninit-finalizetoo — that's what refreshes the permission allowlist (Readon the repo path,Bashon thetest_cmdbinary) to the new value; skip it and the OLD path/binary stays allow-listed while the new one doesn't, so a background/mode:autorun hits an unprompted permission stall the first time it touches the changed repo.overridesonly: no re-verify/re-finalize needed.
5 · Tell the user what changed
State the section, the exact keys written, and (if re-verified/re-finalized) the result.