[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6N9PXHJXE1MEHCTCPZCENPE":3,"skill-same:01M6N9PXHJXE1MEHCTCPZCENPE":59},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":33,"linkOnly":34,"markdownContent":35,"markdownBody":36,"frontMatter":37,"refName":38,"commitSha":39,"skillDirectory":40,"forksCount":41,"repositoryHtmlUrl":42,"repositoryHomepageUrl":6,"ownerHtmlUrl":43,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":44,"install":45,"resources":58},"01M6N9PXHJXE1MEHCTCPZCENPE","bubbles-release-train-model",null,"How to operate the trunk + release-train + per-train-flag-bundle model. Use when cutting\u002Fpromoting\u002Frolling-back\u002Fretiring a release train, when declaring a feature flag, or when designing a feature spec that targets a specific train.","pkirsanov\u002Fsmackerel","pkirsanov","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F138962?v=4","01M6N8NAPD2KXMVC17X6GJ0WZ5","01M6N8NATQ9SAZ00H9D61R0TPV",1,"MIT","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-release-train-model\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],"release","model","train","train model","bubbles release train model","spec","how","use","back","feature","bundle","how to","targets","operate","feature spec","2026-11-10 10:12:30",false,"---\ndescription: How to operate the trunk + release-train + per-train-flag-bundle model. Use when cutting\u002Fpromoting\u002Frolling-back\u002Fretiring a release train, when declaring a feature flag, or when designing a feature spec that targets a specific train.\n---\n\n# Release-Train Model\n\n## Mental Model\n\n**Trunk = `main`.** Always green. Every commit produces a signed immutable build (G074).\n\n**Release train = a named, long-lived ship-line.** Operator-chosen string id (`mvp`, `v1.0`, `2026-q3`, `hardening`, anything). Each train has:\n\n| Field | Values | Meaning |\n|---|---|---|\n| `phase` | `active` \u002F `maintained` \u002F `frozen` \u002F `retired` | Lifecycle stage |\n| `target_slot` | `prod` \u002F `staging` \u002F `none` | Where promotes can land |\n| `flags_bundle` | path to YAML | Per-train feature-flag default set |\n| `retention` | string (e.g. `7d-daily,4w-weekly,12m-monthly`) | Backup retention for this train |\n| `pii` | `none` \u002F `pseudonymized` \u002F `encrypted-only` | Backup PII classification (G120) |\n\n**Feature flag = the switch that gates trunk code per-train.** A spec declares `flagsIntroduced: [\u003Cflag>]` in `state.json`. The flag is default-ON in the spec's `releaseTrain`, default-OFF in every other train (G111).\n\n## The Five Operations (owned by `bubbles.train`)\n\n| Operation | Verb | What happens | Status ceiling |\n|---|---|---|---|\n| **Cut** | `release cut \u003Ctrain>` | Tag trunk at SHA; CI builds signed candidate (digests + per-train bundle). NO deploy. | `train_cut` |\n| **Promote** | `release promote \u003Ctrain> \u003Cslot>` | Pointer-swap knb manifest to candidate digests+bundle. Requires soak evidence + backup freshness (G112) + restore-drill currency (G113). | `train_promoted` |\n| **Rollback** | `release rollback \u003Ctrain>` | Pointer-swap to previous manifest commit. Pure git history op. Never rebuilds. | `train_rolled_back` |\n| **Retire** | `release retire \u003Ctrain>` | Transitions phase to `retired`. Requires all train's flags cleaned up. | `train_retired` |\n| **Flag audit** | `release flag-audit` | Lists flags whose owning train graduated > 1 cycle. Packets cleanup work. | (audit-only) |\n\n## Train Phase Lifecycle\n\n```\nactive ──────► maintained ──────► frozen ──────► retired\n   ▲                │                  │              │\n   │ (cuts+promotes)│ (cuts only,      │ (no cuts,    │ (read-only)\n   │                │  no promotes)    │  flags must  │\n   │                │                  │  be cleaned) │\n   └────────────────┴──────────────────┴──────────────┘\n                  reverse transitions allowed\n                  via release-train-cut mode\n```\n\n## Feature Flag Discipline (G111 — NON-NEGOTIABLE)\n\nFor every spec with `state.json` containing:\n\n```json\n{\n  \"releaseTrain\": \"mvp\",\n  \"flagsIntroduced\": [\"new_payment_flow\", \"fast_checkout\"]\n}\n```\n\n`release-train-guard.sh` verifies:\n\n1. `config\u002Ffeature-flags.mvp.yaml` exists.\n2. In `mvp` bundle: `flags.new_payment_flow: true` is allowed (default ON for owning train).\n3. In `config\u002Ffeature-flags.v1.yaml`, `config\u002Ffeature-flags.experimental.yaml`, etc.: `flags.new_payment_flow: false` REQUIRED. Default-ON on a non-owning train is a BLOCKING violation.\n\n## What Lives Where\n\n| File | Owner | Read access |\n|---|---|---|\n| `config\u002Frelease-trains.yaml` | `bubbles.train` | all |\n| `config\u002Ffeature-flags.\u003Ctrain>.yaml` | `bubbles.train` | `implement`, `upkeep` |\n| `state.json` `releaseTrain` field | `bubbles.train` | all |\n| `state.json` `flagsIntroduced` field | `bubbles.train` | all |\n| `docs\u002FRelease_Trains.md` train roadmap | `bubbles.train` | `docs` (sync only) |\n| knb `\u003Cproduct>\u002F\u003Ctarget>\u002Fmanifest.yaml` | `bubbles.devops` (via packet from `bubbles.train`) | `upkeep`, `audit`, `validate` |\n\n## Cross-Domain Cooperative Reads (B2 boundary)\n\n`bubbles.train` **MAY** read `\u002Fsrv\u002Fbackups\u002Fupkeep-ledger.jsonl` (owned by `bubbles.upkeep`) to gate `promote` on:\n- Last backup within cadence (G112)\n- Last restore-drill within cadence (G113)\n\n`bubbles.train` **NEVER** writes to upkeep ledger. Failure routing goes through packet to `bubbles.upkeep`.\n\n## Common Mistakes\n\n| ❌ Wrong | ✅ Right |\n|---|---|\n| Branching `release\u002Fv1` from `main` and merging selectively | Trunk-based: tag SHA + per-train flag bundle |\n| Hardcoding `mvp`\u002F`v1`\u002F`v2` as train names | Operator-chosen strings; framework agnostic |\n| Adding a new spec without declaring `releaseTrain` | Spec template's `## Release Train` section is REQUIRED |\n| Defaulting a new flag ON in every bundle \"to test in v1 too\" | Default-ON ONLY in owning train; OFF in all others |\n| Rebuilding during `rollback` | Pointer-swap only; rebuild forbidden by mode constraint |\n| Promoting without restore-drill within cadence | G113 blocks; run `upkeep restore-test` first |\n\n## See Also\n\n- Skill: `bubbles-config-bundle-per-train` (bundle authoring contract)\n- Skill: `bubbles-flag-lifecycle` (naming, default-off, retirement triggers)\n- Instructions: `bubbles-release-trains.instructions.md`\n- Agent: `bubbles.train` (Detroit Velvet Smooth)\n- Gates: G110, G111, G081 (Build-Once Deploy-Many Integrity)\n","# Release-Train Model\n\n## Mental Model\n\n**Trunk = `main`.** Always green. Every commit produces a signed immutable build (G074).\n\n**Release train = a named, long-lived ship-line.** Operator-chosen string id (`mvp`, `v1.0`, `2026-q3`, `hardening`, anything). Each train has:\n\n| Field | Values | Meaning |\n|---|---|---|\n| `phase` | `active` \u002F `maintained` \u002F `frozen` \u002F `retired` | Lifecycle stage |\n| `target_slot` | `prod` \u002F `staging` \u002F `none` | Where promotes can land |\n| `flags_bundle` | path to YAML | Per-train feature-flag default set |\n| `retention` | string (e.g. `7d-daily,4w-weekly,12m-monthly`) | Backup retention for this train |\n| `pii` | `none` \u002F `pseudonymized` \u002F `encrypted-only` | Backup PII classification (G120) |\n\n**Feature flag = the switch that gates trunk code per-train.** A spec declares `flagsIntroduced: [\u003Cflag>]` in `state.json`. The flag is default-ON in the spec's `releaseTrain`, default-OFF in every other train (G111).\n\n## The Five Operations (owned by `bubbles.train`)\n\n| Operation | Verb | What happens | Status ceiling |\n|---|---|---|---|\n| **Cut** | `release cut \u003Ctrain>` | Tag trunk at SHA; CI builds signed candidate (digests + per-train bundle). NO deploy. | `train_cut` |\n| **Promote** | `release promote \u003Ctrain> \u003Cslot>` | Pointer-swap knb manifest to candidate digests+bundle. Requires soak evidence + backup freshness (G112) + restore-drill currency (G113). | `train_promoted` |\n| **Rollback** | `release rollback \u003Ctrain>` | Pointer-swap to previous manifest commit. Pure git history op. Never rebuilds. | `train_rolled_back` |\n| **Retire** | `release retire \u003Ctrain>` | Transitions phase to `retired`. Requires all train's flags cleaned up. | `train_retired` |\n| **Flag audit** | `release flag-audit` | Lists flags whose owning train graduated > 1 cycle. Packets cleanup work. | (audit-only) |\n\n## Train Phase Lifecycle\n\n```\nactive ──────► maintained ──────► frozen ──────► retired\n   ▲                │                  │              │\n   │ (cuts+promotes)│ (cuts only,      │ (no cuts,    │ (read-only)\n   │                │  no promotes)    │  flags must  │\n   │                │                  │  be cleaned) │\n   └────────────────┴──────────────────┴──────────────┘\n                  reverse transitions allowed\n                  via release-train-cut mode\n```\n\n## Feature Flag Discipline (G111 — NON-NEGOTIABLE)\n\nFor every spec with `state.json` containing:\n\n```json\n{\n  \"releaseTrain\": \"mvp\",\n  \"flagsIntroduced\": [\"new_payment_flow\", \"fast_checkout\"]\n}\n```\n\n`release-train-guard.sh` verifies:\n\n1. `config\u002Ffeature-flags.mvp.yaml` exists.\n2. In `mvp` bundle: `flags.new_payment_flow: true` is allowed (default ON for owning train).\n3. In `config\u002Ffeature-flags.v1.yaml`, `config\u002Ffeature-flags.experimental.yaml`, etc.: `flags.new_payment_flow: false` REQUIRED. Default-ON on a non-owning train is a BLOCKING violation.\n\n## What Lives Where\n\n| File | Owner | Read access |\n|---|---|---|\n| `config\u002Frelease-trains.yaml` | `bubbles.train` | all |\n| `config\u002Ffeature-flags.\u003Ctrain>.yaml` | `bubbles.train` | `implement`, `upkeep` |\n| `state.json` `releaseTrain` field | `bubbles.train` | all |\n| `state.json` `flagsIntroduced` field | `bubbles.train` | all |\n| `docs\u002FRelease_Trains.md` train roadmap | `bubbles.train` | `docs` (sync only) |\n| knb `\u003Cproduct>\u002F\u003Ctarget>\u002Fmanifest.yaml` | `bubbles.devops` (via packet from `bubbles.train`) | `upkeep`, `audit`, `validate` |\n\n## Cross-Domain Cooperative Reads (B2 boundary)\n\n`bubbles.train` **MAY** read `\u002Fsrv\u002Fbackups\u002Fupkeep-ledger.jsonl` (owned by `bubbles.upkeep`) to gate `promote` on:\n- Last backup within cadence (G112)\n- Last restore-drill within cadence (G113)\n\n`bubbles.train` **NEVER** writes to upkeep ledger. Failure routing goes through packet to `bubbles.upkeep`.\n\n## Common Mistakes\n\n| ❌ Wrong | ✅ Right |\n|---|---|\n| Branching `release\u002Fv1` from `main` and merging selectively | Trunk-based: tag SHA + per-train flag bundle |\n| Hardcoding `mvp`\u002F`v1`\u002F`v2` as train names | Operator-chosen strings; framework agnostic |\n| Adding a new spec without declaring `releaseTrain` | Spec template's `## Release Train` section is REQUIRED |\n| Defaulting a new flag ON in every bundle \"to test in v1 too\" | Default-ON ONLY in owning train; OFF in all others |\n| Rebuilding during `rollback` | Pointer-swap only; rebuild forbidden by mode constraint |\n| Promoting without restore-drill within cadence | G113 blocks; run `upkeep restore-test` first |\n\n## See Also\n\n- Skill: `bubbles-config-bundle-per-train` (bundle authoring contract)\n- Skill: `bubbles-flag-lifecycle` (naming, default-off, retirement triggers)\n- Instructions: `bubbles-release-trains.instructions.md`\n- Agent: `bubbles.train` (Detroit Velvet Smooth)\n- Gates: G110, G111, G081 (Build-Once Deploy-Many Integrity)\n",{"description":7},"main","ed893cc338281a0bb9bb9ecf3415716cb242bb3f",".github\u002Fskills\u002Fbubbles-release-train-model",0,"https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel","https:\u002F\u002Fgithub.com\u002Fpkirsanov","2026-11-07 02:54:37",{"source":8,"skillName":5,"commands":46,"prompt":56,"zipAvailable":57},[47,50,53],{"tool":48,"command":49},"npx","npx skills add pkirsanov\u002Fsmackerel --skill bubbles-release-train-model",{"tool":51,"command":52},"bunx","bunx skills add pkirsanov\u002Fsmackerel --skill bubbles-release-train-model",{"tool":54,"command":55},"pnpm","pnpm dlx skills add pkirsanov\u002Fsmackerel --skill bubbles-release-train-model","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-release-train-model\u002FSKILL.md",true,[],[60,91,119,147,168,195],{"skillNo":61,"name":62,"nameZh":6,"description":63,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":71,"publishedAt":33},"01M6N9V5TBHQT20V5SCCJ1VRBC","smackerel-trace-capture","Wire Smackerel's concrete validate-plane stack into the framework trace-driven defect-discovery method. Use when running live-category tests (integration\u002Fe2e\u002Fe2e-ui\u002Fstress) against the ephemeral test stack; capturing SLO or trace evidence; hunting latency\u002Ferror\u002Fperf bugs from spans; querying the test-stack Jaeger or Prometheus; or touching `.specify\u002Fruntime\u002Fobservability`. Concrete smackerel endpoints + the exact `capture-slo.sh` command; do NOT duplicate `bubbles-observability-adapter` — this only adds the wiring.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fsmackerel-trace-capture\u002FSKILL.md",[66],{"categoryNo":67,"categoryName":68,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[72,73,74,75,76,77,78,79,80,25,81,82,83,84,85,86,87,88,89,90],"trace","capture","smackerel trace capture","perf","observability","prometheus","specify","e2e","discovery","slo","only","evidence","do","latency","runtime","tests","adapter","error","bugs",{"skillNo":92,"name":93,"nameZh":6,"description":94,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":100,"publishedAt":33},"01M6N9TZDEV26RZ7W34HEFPQE9","smackerel-no-defaults","Enforce Smackerel's NO-DEFAULTS \u002F fail-loud SST policy. Use when editing config, Docker Compose, deploy adapters, docs, instructions, skills, env handling, host bind addresses, or any runtime value that could be hidden by fallback syntax.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fsmackerel-no-defaults\u002FSKILL.md",[97],{"categoryNo":98,"categoryName":99,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000011","运维与部署",[101,102,103,104,105,106,107,108,109,25,110,111,86,112,113,114,115,116,117,118],"smackerel no defaults","docker","policy","config","deploy","docker compose","syntax","editing","instructions","compose","enforce","bind","env","host","Adapters","sst","addresses","value",{"skillNo":120,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":123,"categories":124,"keywords":128,"publishedAt":33},"01M6N9TJRS5PF83JH2W4614D4W","bubbles-workflow-mode-resolution","Resolve a Bubbles workflow mode against `bubbles\u002Fworkflows.yaml`, including template inheritance, status ceilings, gate wiring, and decision policy. Use when picking a mode for a request, when a guard reports a mode-related failure, or when extending workflows.yaml with a new mode or template. Covers natural-language intent routing and the workflow registry consistency rules.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-workflow-mode-resolution\u002FSKILL.md",[125],{"categoryNo":126,"categoryName":127,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000023","Skill与智能体开发",[129,130,131,132,103,133,134,135,136,137,138,25,139,140,141,142,143,144,145,146],"workflow","resolution","mode","bubbles workflow mode resolution","workflows","routing","guard","template","decision","Rules","reports","intent","inheritance","with","consistency","natural-language","for","wiring",{"skillNo":148,"name":149,"nameZh":6,"description":150,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":151,"categories":152,"keywords":154,"publishedAt":33},"01M6N9TC98D6DJR0D64SSN0SN3","bubbles-workflow-execution-loops","Run per-round synchronous workflow execution loops correctly. Use when orchestrating a multi-round workflow, dispatching specialist subagents, handling round-based remediation, or interpreting a workflow mode's execution policy. Covers authorized direct execution, dispatch-and-wait, batch-then-summarize prohibition, and mapped-mode execution.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-workflow-execution-loops\u002FSKILL.md",[153],{"categoryNo":126,"categoryName":127,"taxonomyType":69,"taxonomyTypeDesc":70},[129,155,156,157,158,103,159,160,161,162,163,25,164,165,166,167,131],"execution","loops","bubbles workflow execution loops","summarize","run","batch","remediation","direct","subagents","dispatch","wait","multi","multi-round",{"skillNo":169,"name":170,"nameZh":6,"description":171,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":172,"categories":173,"keywords":178,"publishedAt":33},"01M6N9SYXQNJDQ1T1YT81JH2BG","bubbles-vscode-agent-constraints","Design agents that fit the VS Code Copilot Chat runtime instead of fighting it. Use when authoring or editing any `*.agent.md`; when adding `tools:`, `agents:`, `handoffs:`, `model:`, `user-invocable:`, or `disable-model-invocation:` frontmatter; when designing an orchestrator that dispatches specialists; when a design implies agent-calls-agent-calls-agent chaining; when a subagent dispatch silently no-ops or an agent cannot be selected in the dropdown; or when writing a governance rule about delegation that the runtime cannot actually enforce. Prevents multi-level-subagent designs, prose-only dispatch laws, and frontmatter\u002Fbody contradictions.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-vscode-agent-constraints\u002FSKILL.md",[174,177],{"categoryNo":175,"categoryName":176,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":126,"categoryName":127,"taxonomyType":69,"taxonomyTypeDesc":70},[179,180,181,182,183,184,185,186,187,188,19,189,108,190,82,86,191,192,193,194],"vscode","constraints","bubbles vscode agent constraints","design","writing","copilot","code","delegation","Tools","subagent","chaining","orchestrator","authoring","fit","subagent dispatch","frontmatter",{"skillNo":196,"name":197,"nameZh":6,"description":198,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":199,"categories":200,"keywords":201,"publishedAt":33},"01M6N9SD78SK12PRT9KBRZ6TB3","bubbles-upkeep-cadence","How to schedule, dispatch, and record recurring operational upkeep tasks (backup, restore-drill, BCDR-drill, patch-cycle, secret-rotation, flag-cleanup, compliance-sweep). Use when authoring or modifying `config\u002Fupkeep-calendar.yaml`, when investigating a missed task, when reading the upkeep ledger, or when adding a new task type.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-upkeep-cadence\u002FSKILL.md",[],[202,203,204,205,206,207,208,209,25,210,211,212,213,214,215,216,217,29,218,219],"cadence","bubbles upkeep cadence","tasks","cleanup","backup","sweep","schedule","recurring","patch","restore","task","cycle","record","missed","type","drill","new task","rotation"]