Skip to content

Commit d75d3ab

Browse files
committed
fix: harden sandbox flow and sync release bookkeeping
1 parent 3a46471 commit d75d3ab

12 files changed

Lines changed: 182 additions & 20 deletions

.devcontainer/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ It intentionally supports the existing contributor workflow:
77
- `npm run dev`
88
- `npm test`
99
- `npm run test:e2e`
10-
- `npm run playground`
10+
- `npm run sandbox`
1111

1212
Why it exists:
1313

@@ -19,6 +19,6 @@ Why it exists:
1919
It is **not** the main reader quickstart. Blog readers should start with:
2020

2121
- `npm run demo`
22-
- `npm run playground`
22+
- `npm run sandbox`
2323

2424
Those paths are documented in [README.md](../README.md) and [docs/GETTING_STARTED.md](../docs/GETTING_STARTED.md).

CHANGELOG.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,31 @@
22

33
All notable changes to git-cms are documented in this file.
44

5+
## [Unreleased]
6+
7+
## [1.2.0] — 2026-03-21
8+
9+
### Added
10+
11+
- **Reader-safe sandbox workflow:** Added a seeded long-lived `playground` container workflow with `sandbox` aliases, `GIT_CMS_REPO=/data/repo`, deterministic bootstrap, and host-side smoke coverage.
12+
- **Review lanes:** Added speculative editorial review lanes backed by `git-warp` working sets, including `CmsService` support, HTTP endpoints, admin UI controls, and E2E/integration tests.
13+
- **Blog and media support:** Added a public companion walkthrough (`docs/GIT_CMS_COMPANION.md`), reproducible browser/VHS media capture pipeline, and a contributor devcontainer.
14+
15+
### Changed
16+
17+
- **CLI repo root selection:** `bin/git-cms.js` now honors `GIT_CMS_REPO` before `process.cwd()`.
18+
- **Public onboarding:** README, quick reference, testing guide, ADR, and getting-started docs now distinguish `demo`, `sandbox`, and contributor `dev` modes explicitly.
19+
- **Dependencies:** Upgraded to `@git-stunts/git-cas` 5.3.2, `@git-stunts/git-warp` 14.8.0, `@git-stunts/vault` 1.0.1, `@playwright/test` 1.58.2, and `vitest` 4.1.0, with npm/pnpm overrides for patched transitives.
20+
21+
### Fixed
22+
23+
- **Published draft behavior:** Published articles can now accept newer draft commits while the published ref stays pinned until the next explicit publish.
24+
- **Publish semantics:** `publishArticle()` now only moves the published ref to the current draft tip; supplied `sha` values act as stale-write guards instead of arbitrary publish targets.
25+
- **Sandbox/bootstrap robustness:** Playground bootstrap now repairs incomplete seeded state instead of silently accepting any partial namespace.
26+
- **Warning noise:** Suppressed the `DEP0169` `url.parse()` warning from transitive dependencies and removed the `NO_COLOR`/`FORCE_COLOR` startup warning in wrapped entrypoints.
27+
- **Upload path handling:** Server upload path now uses the sanitized basename consistently when writing the temporary file and invoking asset storage.
28+
- **Version-restore UX/docs alignment:** Companion and reader docs now describe restore accurately: history is always visible, but published articles must be unpublished before restore.
29+
530
## [1.1.5] — 2026-02-14
631

732
### Fixed
@@ -143,7 +168,9 @@ All notable changes to git-cms are documented in this file.
143168
- Admin UI: `selectVersion` guards against out-of-order async responses (prevents stale preview flash from rapid clicks)
144169
- **(P2) walkLimit divergence:** Extracted `HISTORY_WALK_LIMIT` as a shared exported constant used by both `_validateAncestry` and the server's history limit clamp
145170

146-
[Unreleased]: https://github.com/flyingrobots/git-cms/compare/main...git-stunts
171+
[Unreleased]: https://github.com/flyingrobots/git-cms/compare/v1.2.0...main
172+
[1.2.0]: https://github.com/flyingrobots/git-cms/compare/v1.1.5...v1.2.0
173+
[1.1.5]: https://github.com/flyingrobots/git-cms/compare/v1.1.4...v1.1.5
147174
[1.1.4]: https://github.com/flyingrobots/git-cms/compare/v1.1.3...v1.1.4
148175
[1.1.3]: https://github.com/flyingrobots/git-cms/compare/v1.1.2...v1.1.3
149176
[1.1.2]: https://github.com/flyingrobots/git-cms/compare/v1.1.1...v1.1.2

QUICK_REFERENCE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Git CMS Quick Reference
22

3-
> Validated against v1.1.5 on 2026-03-15.
3+
> Validated against v1.2.0 on 2026-03-21.
44
55
One-page cheat sheet for Git CMS commands, API endpoints, and concepts.
66

docs/GETTING_STARTED.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Getting Started with Git CMS
22

3-
> Validated against v1.1.5 on 2026-03-15.
3+
> Validated against v1.2.0 on 2026-03-21.
44
55
This guide is optimized for people arriving from the blog post. If you just want to see the stunt, use the reader-safe paths first.
66

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "git-cms",
3-
"version": "1.1.5",
3+
"version": "1.2.0",
44
"description": "A Git-native, database-free CMS: article bodies in commit messages, publish by moving refs.",
55
"homepage": "https://flyingrobots.dev/git-stunts/git-cms",
66
"type": "module",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/index.html

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,7 @@ <h1>Git CMS</h1>
626626
selectedVersion: null,
627627
reviewLanes: [],
628628
activeReviewLane: null,
629+
reviewLaneRequestId: 0,
629630
};
630631

631632
/* ── API Layer ── */
@@ -1254,15 +1255,21 @@ <h1>Git CMS</h1>
12541255
},
12551256

12561257
async fetchReviewLanes() {
1257-
if (!state.currentSlug) {
1258+
const slug = state.currentSlug;
1259+
if (!slug) {
1260+
state.reviewLaneRequestId += 1;
12581261
state.reviewLanes = [];
12591262
this.renderReviewLanes();
12601263
return;
12611264
}
1265+
const requestId = ++state.reviewLaneRequestId;
12621266
try {
1263-
state.reviewLanes = await api.listReviews(state.currentSlug);
1267+
const lanes = await api.listReviews(slug);
1268+
if (state.currentSlug !== slug || requestId !== state.reviewLaneRequestId) return;
1269+
state.reviewLanes = lanes;
12641270
this.renderReviewLanes();
12651271
} catch (err) {
1272+
if (state.currentSlug !== slug || requestId !== state.reviewLaneRequestId) return;
12661273
state.reviewLanes = [];
12671274
this.renderReviewLanes();
12681275
toast('Failed to load review lanes', 'error');

scripts/demo.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ echo ""
209209
echo "This is Git as a database. 🤯"
210210
echo ""
211211
echo "Next steps:"
212-
echo " • Start the seeded playground: npm run playground"
213-
echo " • Open a shell in it: npm run playground:shell"
212+
echo " • Start the seeded sandbox: npm run sandbox"
213+
echo " • Open a shell in it: npm run sandbox:shell"
214214
echo " • Read the guide: docs/GETTING_STARTED.md"
215215
echo " • Read the ADR: docs/ADR.md"
216216
echo " • Explore the code: src/lib/CmsService.js"

scripts/prepare-playground.sh

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ AUTHOR_EMAIL="${GIT_AUTHOR_EMAIL:-playground@git-cms.local}"
1010
COMMITTER_NAME="${GIT_COMMITTER_NAME:-$AUTHOR_NAME}"
1111
COMMITTER_EMAIL="${GIT_COMMITTER_EMAIL:-$AUTHOR_EMAIL}"
1212
SKIP_SEED="${GIT_CMS_SKIP_SEED:-0}"
13+
DRAFT_REF="${REF_PREFIX}/articles/hello-world"
14+
PUBLISHED_REF="${REF_PREFIX}/published/hello-world"
1315

1416
mkdir -p "$REPO_DIR"
1517

@@ -20,10 +22,40 @@ fi
2022
git -C "$REPO_DIR" config user.name "$AUTHOR_NAME"
2123
git -C "$REPO_DIR" config user.email "$AUTHOR_EMAIL"
2224

25+
seed_is_complete() {
26+
local draft_sha published_sha history_count
27+
draft_sha="$(git -C "$REPO_DIR" rev-parse -q --verify "$DRAFT_REF" 2>/dev/null || true)"
28+
published_sha="$(git -C "$REPO_DIR" rev-parse -q --verify "$PUBLISHED_REF" 2>/dev/null || true)"
29+
30+
if [ -z "$draft_sha" ] || [ -z "$published_sha" ]; then
31+
return 1
32+
fi
33+
34+
if [ "$draft_sha" = "$published_sha" ]; then
35+
return 1
36+
fi
37+
38+
history_count="$(git -C "$REPO_DIR" rev-list --count "$DRAFT_REF" 2>/dev/null || echo 0)"
39+
[ "$history_count" -ge 3 ]
40+
}
41+
42+
delete_seed_refs() {
43+
while IFS= read -r ref; do
44+
if [ -n "$ref" ]; then
45+
git -C "$REPO_DIR" update-ref -d "$ref"
46+
fi
47+
done < <(git -C "$REPO_DIR" for-each-ref "${REF_PREFIX}/" --format='%(refname)' || true)
48+
}
49+
2350
existing_refs="$(git -C "$REPO_DIR" for-each-ref "${REF_PREFIX}/" --format='%(refname)' || true)"
2451
if [ -n "$existing_refs" ]; then
25-
echo "Playground repo already contains refs under ${REF_PREFIX}; leaving existing state intact."
26-
exit 0
52+
if seed_is_complete; then
53+
echo "Playground repo already contains the expected seeded state under ${REF_PREFIX}; leaving existing state intact."
54+
exit 0
55+
fi
56+
57+
echo "Playground repo contains incomplete state under ${REF_PREFIX}; repairing seeded refs."
58+
delete_seed_refs
2759
fi
2860

2961
if [ "$SKIP_SEED" = "1" ]; then
@@ -73,7 +105,7 @@ Try these next:
73105
- inspect refs
74106
- inspect the commit message
75107
- browse history
76-
- restore an older version
108+
- unpublish, then restore an older version
77109
EOF
78110

79111
echo "Playground repo seeded under ${REF_PREFIX}."

0 commit comments

Comments
 (0)