Skip to content

feat: feature-flag + image system; promote bundle to stable (#121)#122

Merged
fedorovvvv merged 1 commit into
developfrom
feature/issue-121-feature-flag-images
May 9, 2026
Merged

feat: feature-flag + image system; promote bundle to stable (#121)#122
fedorovvvv merged 1 commit into
developfrom
feature/issue-121-feature-flag-images

Conversation

@fedorovvvv
Copy link
Copy Markdown
Collaborator

Summary

  • Promote bundle to stable: legacy SvelteKit + node_modules/ shape is removed from the published tarball; the esbuild bundle (≈1.8 MB, capped at 3 MB) is now the universal artifact form for every image.
  • Feature-flag + image registry: config/images.json + config/features.json describe what images ship and what flags each one carries. v1 ships stable (default) and nightly, both with zero flags — framework only. Lifecycle policy: a flag's expiresInaddedIn + 3 minor; build fails fast when a flag is past expiry.
  • --image <name> CLI on init and update. Default stable. Sticky in forgeplan-web.json. --experimental kept as deprecated alias for --image nightly for one minor release; removed in 0.3.0.

Why

Two pressures merged: PRD-014 / RFC-013's dist-experimental/ bundle has been opt-in long enough to graduate, and a single --experimental boolean can't scale to three or four parallel tracks. PRD-030 asks for a registry, not more booleans, with a forcing function so experimental flags can't accrete indefinitely.

Forgeplan

  • PRD-030 — feature-flag + image system; promote experimental bundle to stable default (active)
  • RFC-026 — image manifest and build-pipeline (active)
  • ADR-005 — image as build artifact, not runtime config (active)
  • EVID-035 — smoke + lifecycle-validator evidence (active, evidence_type: test, CL3, supports)
  • All scored, R_eff > 0.

Test plan

  • npm run build — emits dist/ (image=stable, 1.79M) and dist-nightly/ (image=nightly, 1.79M), both ≤3 MB, both with per-image forgeplan-web-build.json.
  • npm run smoke — exercises both images end-to-end (init + start + /api/health + /api/list + GET / returning 200), asserts no node_modules/ in scaffold, image fields match, gitignore idempotent.
  • --experimental deprecation alias prints stderr warning and writes image: "nightly" to both config files.
  • Lifecycle validator regression — synthetic flag with expiresIn ≤ currentVersion exits non-zero with descriptive error; same for lifetime > 3 minor.
  • CI matrix (ubuntu/macos/windows × Node 20.19/22) — pending PR run.

Breaking changes (npm tarball internals only)

  • dist-experimental/ is renamed to dist-nightly/ in package.json#files. Users running npx @forgeplan/web init see no difference; only consumers that pinned the directory name in scripts must switch.
  • Legacy build pipeline functions (installRuntimeDeps, emitDistPackageJson, copyToDist) removed from scripts/build.mjs.

Out of scope

  • Per-image runtime gating logic (v1 ships empty flag lists).
  • Telemetry on which image users pick.
  • A third image (e.g. lts).

Refs: PRD-030, RFC-026, ADR-005
Closes: #121

🤖 Generated with Claude Code

#121)

Replaces the single --experimental boolean with a config-driven multi-image
pipeline. Two images for v1: stable (default) and nightly, both shipping
with empty feature lists — framework only. The legacy SvelteKit-with-
node_modules/ shape is removed; the esbuild bundle (PRD-014 / RFC-013) is
now the universal artifact form for every image.

- config/images.json + config/features.json: source of truth for image →
  flags mapping and per-flag lifecycle metadata (addedIn / expiresIn /
  rollout).
- scripts/build.mjs: bundles once via esbuild, copies to dist/ (stable)
  and dist-<name>/ (others), each with its own forgeplan-web-build.json
  carrying { image, features }. Build-time validator fails fast when any
  flag is past expiresIn or has lifetime > 3 minor versions.
- bin/lib/images.mjs: image-name → directory mapping, allow-list-safe
  (node:* + relative siblings only — rule 23 unchanged).
- bin/commands/init.mjs + update.mjs: --image <name> flag (default
  stable). Persisted in forgeplan-web.json. --experimental kept as
  deprecated alias for --image nightly with stderr warning; removed in
  0.3.0.
- scripts/smoke.mjs: extended to exercise both images end-to-end; asserts
  no node_modules/ in scaffold, image fields match, idempotent gitignore.
- README + CHANGELOG + rules 21/23 + CLAUDE.md updated.

Forgeplan: PRD-030 / RFC-026 / ADR-005 / EVID-035 (active, R_eff > 0).

Refs: PRD-030, RFC-026, ADR-005
Closes: #121

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@fedorovvvv fedorovvvv merged commit 354dee4 into develop May 9, 2026
3 checks passed
@fedorovvvv fedorovvvv deleted the feature/issue-121-feature-flag-images branch May 9, 2026 10:59
fedorovvvv added a commit that referenced this pull request May 9, 2026
Tactical follow-up to #121 (PR #122) — agent context files and the
Russian README still described the legacy `dist/` + `dist-experimental/`
shape. Bring them in line with what `develop` actually ships:

- README.ru.md: new "Образы (images)" section mirroring README.md;
  package summary in "Что получаешь" notes the per-image bundle.
- docs/agents/domain.md: replace "legacy dist/" + "opt-in
  dist-experimental/" entries with image / feature-flag definitions;
  document `--experimental` as deprecated alias.
- docs/agents/paths.md: top-level table swaps `dist-experimental/` for
  `dist-nightly/` + `config/`; tarball inventory now reads from
  `config/images.json`.

No code changes — `bin/`, `scripts/`, `template/` untouched, smoke
unchanged. Tactical depth per rule 11 (doc copy-edit, no public
behaviour change), so no new Forgeplan artifact required; references
the existing PRD-030 / RFC-026 / ADR-005 chain.

Refs: PRD-030, RFC-026, ADR-005, #121

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fedorovvvv added a commit that referenced this pull request May 9, 2026
…up) (#124)

## Summary

Tactical follow-up to #121 (PR #122). Three doc files still described
the
legacy `dist/` + `dist-experimental/` shape — bring them in line with
what `develop` actually ships post-PR-#122.

- `README.ru.md` — new "Образы (images): `stable` (по умолчанию) и
`nightly`" section mirroring `README.md`; updated "Что получаешь" line
to mention the per-image bundle.
- `docs/agents/domain.md` — replace **legacy `dist/`** + **opt-in
`dist-experimental/`** entries with **Image** + **Feature flag**
definitions, and document `--experimental` as a deprecated alias.
- `docs/agents/paths.md` — top-level table swaps `dist-experimental/`
for `dist-nightly/` + `config/`; tarball inventory now references
`config/images.json` for the canonical image list.

## Why

`docs/agents/*.md` are auto-loaded by the `fpl-skills` skill set. Stale
terms there mean every future agent invocation starts with an inaccurate
mental model of the package shape — exactly the kind of drift rule 11
(Forgeplan as single source of truth) is meant to prevent. PRD-030
already activated; this PR closes the doc gap without re-opening the
artifact discipline.

## Scope

No code changes — `bin/`, `scripts/`, `template/` untouched. Smoke
status from PR #122 still applies. Tactical depth per rule 11 (docs
without behaviour change), so no new Forgeplan artifact required.

## Test plan

- [x] `grep -rn 'dist-experimental\|--experimental' docs/` shows only
the `--experimental` *deprecated alias* mention in `domain.md`.
- [x] `git diff --stat` is bounded to the three doc files.
- [x] No code paths touched → smoke unaffected.
- [ ] CI: docs-only PRs still trigger the smoke matrix; expected green
since no source changed.

Refs: PRD-030, RFC-026, ADR-005, #121

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant