Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 32 additions & 0 deletions .github/workflows/sdd-gates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,38 @@ jobs:
grep -q '<!-- SDD_LANGUAGE_POLICY_START -->' openspec/project.md
grep -q '<!-- SDD_LANGUAGE_POLICY_END -->' openspec/project.md

# C2 upgrade smoke test. install.sh had a greenfield gate and a consumer gate;
# upgrade.sh had neither, which is why a `realpath` call that aborts on any
# destination whose parent does not exist yet survived in it long after the same
# defect was fixed in install.sh. Regressing one directory is enough to reproduce
# the real case: every pre-1.15.0 install lacks openspec/changes/_template/specs/.
- name: Upgrade smoke test (blocking)
timeout-minutes: 4
run: |
set -euo pipefail
VER=$(grep -E '^version:' sdd-kit/MANIFEST.yaml | head -1 | sed 's/.*"\(.*\)".*/\1/')
U="${{ runner.temp }}/upgrade"
rm -rf "$U"; mkdir -p "$U"
cp -R sdd-kit "$U/"
cd "$U"
git init -q .
git -c user.email=ci@example.com -c user.name=CI commit -q --allow-empty -m "initial commit"
git checkout -q -b work # --apply refuses the default branch without --force
bash sdd-kit/install.sh --profile APP --chat-lang en --docs-lang en --code-lang en >/dev/null

# Regress to the pre-1.15.0 shape: this directory is what --apply must recreate.
rm -rf openspec/changes/_template/specs

bash sdd-kit/upgrade.sh --from 1.0.0 --to "$VER" --profile APP --dry-run >/dev/null
RPT="openspec/changes/upgrade-sdd-v${VER}/UPGRADE_REPORT.md"
sed 's/- \[ \] Upgrade approved/- [x] Upgrade approved/' "$RPT" > "$RPT.tmp"
mv "$RPT.tmp" "$RPT"
bash sdd-kit/upgrade.sh --from 1.0.0 --to "$VER" --profile APP --apply

# Exit code alone is not enough — assert the path that used to abort.
test -f openspec/changes/_template/specs/example-capability/spec.md
echo "OK: upgrade recreated a destination whose parent did not exist"

# D4 — report-only: verify.sh orquestra verify-infra.sh, que marca FAIL
# para CLIs de conhecimento (GitNexus/Graphify) ausentes no runner e muta
# openspec/infra.md. O resultado é reportado sem bloquear o merge; a
Expand Down
15 changes: 0 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,21 +141,6 @@ We **compose** OpenSpec; we don't replace it.
| [`sdd-kit/README.md`](./sdd-kit/README.md) | EN | Kit scenarios & commands |
| [`doc/avaliacoes/2026-07-26-sdd-discovery-positioning.md`](./doc/avaliacoes/2026-07-26-sdd-discovery-positioning.md) | EN | Market / SEO / backlog decisions |

## [MANUAL ACTION REQUIRED] — GitHub rename, About & topics

Settings are not in git. After merge, the operator should:

1. **Rename repo** (Settings → General → Repository name): `gitnexus-graphify-openspec` → **`byebyevibe`**
2. Update local remotes: `git remote set-url origin git@github.com:pvilarim/byebyevibe.git` (or HTTPS)
3. Set **About** and **Topics** (below)
4. Optional **Homepage**: `https://pedrocodeart.netlify.app/`

**About:**

> ByeByeVibe — Spec-Driven Development (SDD) install kit from vibe coding to shippable AI engineering. Control plane (OpenSpec + graphs + gates) for Cursor & Claude Code. Not a Next.js starter.

**Topics:** `vibe-coding` · `spec-driven-development` · `context-engineering` · `agentic-coding` · `claude-code` · `cursor`

## Maintainer

Pedro Vilarim — [LinkedIn](https://www.linkedin.com/in/pedrovilarim/) · [Portfolio](https://pedrocodeart.netlify.app/)
14 changes: 12 additions & 2 deletions doc/byebyevibe-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**GitNexus + Graphify + OpenSpec, integrated in Cursor and VS Code + Claude Code**

> **Canonical install guide (v1.15.0)** — use in any Git repository, manually or via an AI agent. Payloads in `sdd-kit/`; procedure in this document.
> **Canonical install guide (v1.15.1)** — use in any Git repository, manually or via an AI agent. Payloads in `sdd-kit/`; procedure in this document.

## How to use this document

Expand All @@ -19,7 +19,7 @@
| **SDD metrics (G4)** | `bash scripts/sdd-metrics.sh` — §2.17 (mode C; no DevLake) |

- **`AGENTS.md` pattern:** aligned with [agents.md](https://agents.md/) + TLC workshop (Context Engineering, on-demand loading).
- **Guide version:** 1.15.0 — see [Guide changelog](#guide-changelog).
- **Guide version:** 1.15.1 — see [Guide changelog](#guide-changelog).
- **Versioned payload:** `sdd-kit/MANIFEST.yaml` — see §1.6 and `sdd-kit/README.md`.
- **Does not replace** `openspec/project.md` (project constitution) or specs in `openspec/specs/`.

Expand Down Expand Up @@ -3107,6 +3107,16 @@ bash scripts/verify-task-patterns.sh # Pattern: paths exist; DOCS_SPECS withou

## Guide changelog

### 1.15.1 (2026-08-14)

**Change `fix-upgrade-realpath`** — repairs `sdd-kit/upgrade.sh`, which could not deliver the 1.15.0 payload at all. The C2 upgrade path had no gate of its own: `install.sh` gained a greenfield smoke test in 1.14.0 and a consumer smoke test in 1.15.0, while `upgrade.sh` kept a `realpath` call whose equivalent defect had already been fixed in `install.sh` one release earlier.

- **`--apply` no longer aborts on a destination whose parent does not exist** — the traversal guard used plain `realpath --no-symlinks`, which requires every leading path component to already exist. Any MANIFEST entry creating a new directory killed the run mid-apply, leaving the repository half-upgraded. This is **not** macOS-specific: it reproduces on GNU coreutils. Concretely, upgrading any pre-1.15.0 install to 1.15.0 aborted on `openspec/changes/_template/specs/`, a directory none of them have. The call now uses `-m` with the same `posixpath.normpath` fallback `install.sh` has carried since 1.14.0, probed once. `..` is still resolved and traversal is still blocked.
- **BSD/macOS realpath covered by the same change** — `--no-symlinks` is a GNU long option that macOS realpath does not accept at all, so one fix repairs both failures. This was recorded as out of scope in 1.15.0 and pulled forward, because the upgrade tool is exactly what the existing installed base needs.
- **New blocking gate: C2 upgrade smoke test** — `sdd-gates` now installs, regresses one directory to the pre-1.15.0 shape, and runs a full dry-run to approve to `--apply` cycle, asserting the exact path that used to abort. The defect survived precisely because no gate ever exercised `upgrade.sh`.

**Housekeeping** — the stale `[MANUAL ACTION REQUIRED]` block is removed from `README.md`: the repository rename it asked for was completed long ago.

### 1.15.0 (2026-08-13)

**Change `fix-consumer-install`** — repairs the consumer install path end to end. One root cause under all seven defects: **the hub validated itself.** Every hub/consumer branch was a directory-shaped guess, so a consumer holding a full copy of `sdd-kit/` read as the hub and skipped the checks written for it; and every "cannot run" state reported success instead of failing. A 1.14.0 install completed, printed `Done.`, and left the operator without a guide, without a constitution, and with a validation that could not pass.
Expand Down
8 changes: 4 additions & 4 deletions sdd-kit/MANIFEST.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
# The `gate:` field is documentary metadata only — the suggested verification
# command for manual or CI use. It MUST NOT be executed via `eval` or any
# equivalent by install.sh, upgrade.sh, or any other script.
version: "1.15.0"
guide_version: "1.15.0"
version: "1.15.1"
guide_version: "1.15.1"
min_openspec: "1.3.1"
profiles: [APP, DOCS_SPECS, HYBRID]

Expand Down Expand Up @@ -110,7 +110,7 @@ files:

- path: .github/workflows/sdd-gates.yml
source: templates/.github/workflows/sdd-gates.yml
sha256: "7326bf67327d42aed6407a93b776dd9bb0b239736b86cf4d78adc114fedc93bb"
sha256: "58f8516995c07457a51abacd1c54456afc699c62657da5638cf562858402dcc7"
merge: COPY
profiles: [APP, DOCS_SPECS, HYBRID]
gate: "test -f .github/workflows/sdd-gates.yml"
Expand Down Expand Up @@ -303,7 +303,7 @@ files:
# openspec/ specs and development history — an operator guide is neither.
- path: doc/byebyevibe-guide.md
source: templates/doc/byebyevibe-guide.md
sha256: "28a9dfa3a9cf6fcdf5b0570bd0df7163e85d917967aa7ff54c12eacfc90d1ea2"
sha256: "6044ae92297c3b4cd7ed597a19398fbb2f27b29b36ede2746885271b6f6de25a"
merge: COPY
profiles: [APP, DOCS_SPECS, HYBRID]
gate: "test -s doc/byebyevibe-guide.md && grep -q 'Guide version' doc/byebyevibe-guide.md"
Expand Down
2 changes: 1 addition & 1 deletion sdd-kit/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ByeByeVibe — sdd-kit v1.15.0
# ByeByeVibe — sdd-kit v1.15.1

**ByeByeVibe** is the public name of this project. This folder (`sdd-kit/`) is the versioned **install payload** — commands and paths stay `sdd-kit/*`.

Expand Down
32 changes: 32 additions & 0 deletions sdd-kit/templates/.github/workflows/sdd-gates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,38 @@ jobs:
grep -q '<!-- SDD_LANGUAGE_POLICY_START -->' openspec/project.md
grep -q '<!-- SDD_LANGUAGE_POLICY_END -->' openspec/project.md

# C2 upgrade smoke test. install.sh had a greenfield gate and a consumer gate;
# upgrade.sh had neither, which is why a `realpath` call that aborts on any
# destination whose parent does not exist yet survived in it long after the same
# defect was fixed in install.sh. Regressing one directory is enough to reproduce
# the real case: every pre-1.15.0 install lacks openspec/changes/_template/specs/.
- name: Upgrade smoke test (blocking)
timeout-minutes: 4
run: |
set -euo pipefail
VER=$(grep -E '^version:' sdd-kit/MANIFEST.yaml | head -1 | sed 's/.*"\(.*\)".*/\1/')
U="${{ runner.temp }}/upgrade"
rm -rf "$U"; mkdir -p "$U"
cp -R sdd-kit "$U/"
cd "$U"
git init -q .
git -c user.email=ci@example.com -c user.name=CI commit -q --allow-empty -m "initial commit"
git checkout -q -b work # --apply refuses the default branch without --force
bash sdd-kit/install.sh --profile APP --chat-lang en --docs-lang en --code-lang en >/dev/null

# Regress to the pre-1.15.0 shape: this directory is what --apply must recreate.
rm -rf openspec/changes/_template/specs

bash sdd-kit/upgrade.sh --from 1.0.0 --to "$VER" --profile APP --dry-run >/dev/null
RPT="openspec/changes/upgrade-sdd-v${VER}/UPGRADE_REPORT.md"
sed 's/- \[ \] Upgrade approved/- [x] Upgrade approved/' "$RPT" > "$RPT.tmp"
mv "$RPT.tmp" "$RPT"
bash sdd-kit/upgrade.sh --from 1.0.0 --to "$VER" --profile APP --apply

# Exit code alone is not enough — assert the path that used to abort.
test -f openspec/changes/_template/specs/example-capability/spec.md
echo "OK: upgrade recreated a destination whose parent did not exist"

# D4 — report-only: verify.sh orquestra verify-infra.sh, que marca FAIL
# para CLIs de conhecimento (GitNexus/Graphify) ausentes no runner e muta
# openspec/infra.md. O resultado é reportado sem bloquear o merge; a
Expand Down
14 changes: 12 additions & 2 deletions sdd-kit/templates/doc/byebyevibe-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**GitNexus + Graphify + OpenSpec, integrated in Cursor and VS Code + Claude Code**

> **Canonical install guide (v1.15.0)** — use in any Git repository, manually or via an AI agent. Payloads in `sdd-kit/`; procedure in this document.
> **Canonical install guide (v1.15.1)** — use in any Git repository, manually or via an AI agent. Payloads in `sdd-kit/`; procedure in this document.

## How to use this document

Expand All @@ -19,7 +19,7 @@
| **SDD metrics (G4)** | `bash scripts/sdd-metrics.sh` — §2.17 (mode C; no DevLake) |

- **`AGENTS.md` pattern:** aligned with [agents.md](https://agents.md/) + TLC workshop (Context Engineering, on-demand loading).
- **Guide version:** 1.15.0 — see [Guide changelog](#guide-changelog).
- **Guide version:** 1.15.1 — see [Guide changelog](#guide-changelog).
- **Versioned payload:** `sdd-kit/MANIFEST.yaml` — see §1.6 and `sdd-kit/README.md`.
- **Does not replace** `openspec/project.md` (project constitution) or specs in `openspec/specs/`.

Expand Down Expand Up @@ -3107,6 +3107,16 @@ bash scripts/verify-task-patterns.sh # Pattern: paths exist; DOCS_SPECS withou

## Guide changelog

### 1.15.1 (2026-08-14)

**Change `fix-upgrade-realpath`** — repairs `sdd-kit/upgrade.sh`, which could not deliver the 1.15.0 payload at all. The C2 upgrade path had no gate of its own: `install.sh` gained a greenfield smoke test in 1.14.0 and a consumer smoke test in 1.15.0, while `upgrade.sh` kept a `realpath` call whose equivalent defect had already been fixed in `install.sh` one release earlier.

- **`--apply` no longer aborts on a destination whose parent does not exist** — the traversal guard used plain `realpath --no-symlinks`, which requires every leading path component to already exist. Any MANIFEST entry creating a new directory killed the run mid-apply, leaving the repository half-upgraded. This is **not** macOS-specific: it reproduces on GNU coreutils. Concretely, upgrading any pre-1.15.0 install to 1.15.0 aborted on `openspec/changes/_template/specs/`, a directory none of them have. The call now uses `-m` with the same `posixpath.normpath` fallback `install.sh` has carried since 1.14.0, probed once. `..` is still resolved and traversal is still blocked.
- **BSD/macOS realpath covered by the same change** — `--no-symlinks` is a GNU long option that macOS realpath does not accept at all, so one fix repairs both failures. This was recorded as out of scope in 1.15.0 and pulled forward, because the upgrade tool is exactly what the existing installed base needs.
- **New blocking gate: C2 upgrade smoke test** — `sdd-gates` now installs, regresses one directory to the pre-1.15.0 shape, and runs a full dry-run to approve to `--apply` cycle, asserting the exact path that used to abort. The defect survived precisely because no gate ever exercised `upgrade.sh`.

**Housekeeping** — the stale `[MANUAL ACTION REQUIRED]` block is removed from `README.md`: the repository rename it asked for was completed long ago.

### 1.15.0 (2026-08-13)

**Change `fix-consumer-install`** — repairs the consumer install path end to end. One root cause under all seven defects: **the hub validated itself.** Every hub/consumer branch was a directory-shaped guess, so a consumer holding a full copy of `sdd-kit/` read as the hub and skipped the checks written for it; and every "cannot run" state reported success instead of failing. A 1.14.0 install completed, printed `Done.`, and left the operator without a guide, without a constitution, and with a validation that could not pass.
Expand Down
22 changes: 21 additions & 1 deletion sdd-kit/upgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ _sha256() {
echo ""
fi
}
# Probe GNU `realpath -m` once; the macOS fallback lives at the call site (design D6,
# mirroring install.sh). BSD/macOS realpath has neither -m nor --no-symlinks.
if realpath -m --no-symlinks / >/dev/null 2>&1; then
REALPATH_M=true
else
REALPATH_M=false
fi

FROM_VER=""
TO_VER=""
DRY_RUN=false
Expand Down Expand Up @@ -303,7 +311,19 @@ PY
[[ -n "$dest" ]] || continue
[[ "$merge" == "COPY" ]] || continue
[[ -f "$KIT_DIR/$src" ]] || continue
dest_path="$(realpath --no-symlinks "$REPO_ROOT/$dest")"
# -m: canonicalise a destination whose parent does not exist YET. Plain `realpath`
# requires every leading component to exist, so --apply aborted on any entry that
# creates a new directory — e.g. openspec/changes/_template/specs/ when upgrading a
# pre-1.15.0 install, which made the upgrade to 1.15.0 impossible. `--no-symlinks`
# is additionally a GNU long option that BSD/macOS realpath does not have at all,
# so the fallback covers both failures. `..` is still resolved, so the prefix check
# below keeps catching escapes. Same form as install.sh (design D6).
if $REALPATH_M; then
dest_path="$(realpath -m --no-symlinks "$REPO_ROOT/$dest")"
else
# $SDD_PYTHON unquoted by convention: "py -3" is two words
dest_path="$($SDD_PYTHON -c 'import posixpath,sys; print(posixpath.normpath(sys.argv[1]))' "$REPO_ROOT/$dest")"
fi
[[ "$dest_path" == "$REPO_ROOT"/* ]] || {
echo "ERROR: path traversal blocked: $dest" >&2
exit 1
Expand Down