v0.1.3: encoding remediation - restore 11 core files to clean UTF-8 + add check:encoding-health guard

This commit is contained in:
octopus
2026-09-16 13:13:18 +08:00
parent 445940ea63
commit 4518f41fd4
14 changed files with 437 additions and 341 deletions
+79 -79
View File
@@ -4,22 +4,22 @@ description: >
Use ONLY when ready to cut a release. The Release Manager (Worker) inspects
project state (git log, version files, build) to determine the semver bump,
generate the changelog, tag, and produce a release artifact. Works on any
project state 鈥?no pipeline artifacts required.
project state no pipeline artifacts required.
triggers:
- release
- cut release
- 鍙戠増
- 发版
- publish release
- ship release
role: Producer
---
> Core 涓珛鐗堬紙Increment 6a 鏀瑰啓锛屽師 deferHard verbatimDir锛夈€傛満鍒躲€佺粨鏋勪笌 frontmatter 淇濇寔锛涘疄渚嬫湳璇紙宸ュ叿鍚嶃€佽矾寰勩€佸伐鍗曞彿锛夋寜 `core/adapters/TERMINOLOGY.md` 缁戝畾鍒板叿浣撳疄渚嬨€?
> Core 中立版(Increment 6a 改写,原 deferHard verbatimDir)。机制、结构与 frontmatter 保持;实例术语(工具名、路径、工单号)按 `core/adapters/TERMINOLOGY.md` 绑定到具体实例。
# Release
Prepare and tag a release based on project facts 鈥?git history since the last
Prepare and tag a release based on project facts git history since the last
tag, current version, build status, and dependency health. No dependency on `.artifacts/{slug}/`
(**deprecated** 鈥?SDLC artifacts now live in the Gitea wiki at `{slug}/...`;
(**deprecated** SDLC artifacts now live in the Gitea wiki at `{slug}/...`;
see `_shared/gitea-read-patterns.md`) or any pipeline skill outputs.
**This SKILL does not deploy.** Deployment is project-specific (K8s, Docker,
@@ -32,12 +32,12 @@ The release is owned and executed by the **Release Manager** (Worker).
**Context compaction**: release is a pipeline stage boundary. The main session
compacts at this clean boundary ONLY when a capacity/projection trigger holds,
per `core/rules/compact.md` "Stage-boundary compaction" (long multi-stage
runs 鈥?DAG Epic orchestration 鈥?keep the legacy every-boundary compaction;
short runs 鈥?bugfix / DAG task 鈥?and standalone runs default to NOT
per `core/rules/compact.md` §"Stage-boundary compaction" (long multi-stage
runs DAG Epic orchestration keep the legacy every-boundary compaction;
short runs bugfix / DAG task and standalone runs default to NOT
compacting). The Release Manager itself is single-phase and
artifact-driven (version files, changelog, tag); a mid-run compaction loses
nothing 鈥?re-read the release checklist state and git log to resume.
nothing re-read the release checklist state and git log to resume.
---
@@ -50,7 +50,7 @@ Before starting the release:
---
## Phase 1 鈥?Pre-release Gate
## Phase 1 Pre-release Gate
Run each check against the live project. Stop and report failures.
@@ -65,82 +65,82 @@ Run each check against the live project. Stop and report failures.
- No new HIGH or CRITICAL CVEs block the release.
- Pre-existing HIGH/CRITICAL CVEs do NOT block but **MUST be filed as
tech-debt** before the release lands. File them in TWO TIERS (batching
rule, [org-internal #3846] 鈥?a single release audit once fanned out to 14 TDs 鈫?14 PRs 鈫?
rule, [org-internal #3846] a single release audit once fanned out to 14 TDs 14 PRs
56-84 CI runs on a saturated runner pool): Tier A below is the general
mechanical-change batching rule; Tier B and the escape hatch follow it.
<a id="phase-1-tier-a"></a>
### Tier A 鈥?閫氱敤鏈烘鍙樻洿骞跺崟瑙勫垯 / Universal mechanical-change batching rule
### Tier A — 通用机械变更并单规则 / Universal mechanical-change batching rule
Origin [org-internal #3846] (audit-batch pilot, generalized in place): the rule covers ANY
single-source fan-out of mechanical changes, not just dependency audits.
Two source types today: (a) dependency bump audits; (b) docs 鎵归噺淇
Two source types today: (a) dependency bump audits; (b) docs 批量修订
(batch docs revisions).
#### 瑙勫垯姝f枃 / Rule text
#### 规则正文 / Rule text
- **Core**: mechanical changes of ONE class fanning out from a single
source are filed as ONE batch issue + ONE batch PR 鈥?never Nissue +
NPR. The batch body keeps one row per item (per-CVE / per-doc mapping),
source are filed as ONE batch issue + ONE batch PR never N×issue +
N×PR. The batch body keeps one row per item (per-CVE / per-doc mapping),
so per-item traceability is unchanged; work the batch as a single PR.
- **(a) Dependency bump audits** (the [org-internal #3846] origin case): advisories whose
remediation is a plain version bump (lockfile-only diff, no semver-major
jump, no overrides/catalog surgery, no API or adapter fallout) are filed
together via `宸ュ崟 API锛堣 TERMINOLOGY锛塩reate` with
together via `工单 API(见 TERMINOLOGYcreate` with
`title="[{origin}] audit-batch@{version}: mechanical bumps for {N} advisories (TD-{NNN})"`
and labels `[tech_debt_label_id, severity_label_id, kind_bug_label_id]`
(severity = highest in the batch). One row per advisory 鈥?CVE/GHSA ID,
affected package + from鈫抰o version, severity (CVSS), advisory URL,
(severity = highest in the batch). One row per advisory CVE/GHSA ID,
affected package + from→to version, severity (CVSS), advisory URL,
recommended remediation, and a per-advisory Reactivation Trigger
("resolved when `npm audit` / `bun audit` reports no HIGH/CRITICAL for
this advisory") 鈥?so the release-notes `TD-NNN 鈫?#NNNN` mapping stays
this advisory") so the release-notes `TD-NNN #NNNN` mapping stays
per-advisory.
- **(b) Docs 鎵归噺淇 (batch docs revisions)**: many small same-class docs
- **(b) Docs 批量修订 (batch docs revisions)**: many small same-class docs
corrections discovered in one pass (e.g. a terminology sweep) file as ONE
issue via the same flow,
`title="[{origin}] docs-batch: {class} revisions for {N} files"`, with one
row per file (path, correction, reason); same ONE-batch-PR landing.
- **Landing**: when members live on separate branches, compose the single
batch PR via the `land-batch` skill (`core/skills/land-batch/SKILL.md`
鈥?cross-branch batch composition, topology B). For dependency-bump
cross-branch batch composition, topology B). For dependency-bump
batches pass `batch-compose --convergent bun.lock` (script
`.gitea/scripts/batch-compose.ts`): the regenerable lockfile is exempt
from path-overlap admission and lockfile-only conflicts are surgically
resolved to the running head's version.
#### 閫傜敤杈圭晫 / Applicability boundary
#### 适用边界 / Applicability boundary
- **闈?mechanical锛堝惈鍒ゆ柇鎴愬垎鐨勫彉鏇达紝涓嶅苟鍗曪級** 鈥?items requiring judgment
- **mechanical(含判断成分的变更,不并单)** items requiring judgment
(wording decisions, behavior/API changes, review-dependent edits) are
never batched; file each as its own issue.
- **璺緞閲嶅彔锛坆atch 鎴愬憳瑙︾鐩稿悓鏂囦欢 鈫?涓嶅苟鍗曪紱鍞竴璞佸厤 =
鍙啀鐢熷叡浜枃浠?`bun.lock` 缁?batch-compose `--convergent` 鏀舵暃锛?* 鈥?the sole
- **路径重叠(batch 成员触碰相同文件 → 不并单;唯一豁免 =
可再生共享文件`bun.lock` batch-compose `--convergent` 收敛)** — the sole
path-overlap exemption is the regenerable shared lockfile under
`--convergent`; every other same-file collision stays un-batched.
- **semver-major 璺冲彉 / overridescatalog 鎵嬫湳 / adapterpeer 鑱斿姩锛堚啋
Tier B 鐙珛鍗曪紝缁存寔 per-package锛?* 鈥?these stay per-package Tier B
- **semver-major 跳变 / overrides·catalog 手术 / adapter·peer 联动(→
Tier B 独立单,维持 per-package** — these stay per-package Tier B
issues. Tier B and the escape hatch (below) survive this generalization
unchanged.
#### 闄嶇骇璺緞 / Degradation path
#### 降级路径 / Degradation path
- **骞跺崟 PR CI 澶辫触 鈫?鎸夐攣鏂囦欢 hunk 鎷嗗寘鍥為€€锛坆isect锛?*: for dependency
- **并单 PR CI 失败 → 按锁文件 hunk 拆包回退(bisect**: for dependency
batches, bisect by splitting lockfile hunks per package back into
per-package PRs 鈥?the original Tier A bisect semantics carried over
verbatim (鍚岃涔夛紝娉涘寲鎺緸: every mechanical batch degrades the same way).
per-package PRs the original Tier A bisect semantics carried over
verbatim (同语义,泛化措辞: every mechanical batch degrades the same way).
- **Docs batches**: split per file back into per-file PRs.
- **land-batch composition fallback** (exit codes per
`.gitea/scripts/batch-compose.ts`): `3` path-overlap 鈫?split the batch
`.gitea/scripts/batch-compose.ts`): `3` path-overlap split the batch
along the reported pairs (or land the overlapping member 1:1) and re-run
per group; `4` merge conflict / `5` transport/git error 鈫?fall back to
per group; `4` merge conflict / `5` transport/git error fall back to
1:1 PRs for the whole batch.
- **Preflight hedge ([org-internal #3846])**: run `bun install --dry-run` before opening
a dependency-batch PR 鈥?the resolver accepting the composed version set
a dependency-batch PR the resolver accepting the composed version set
is a cheap pre-CI rejection of impossible bump combinations.
Tier B and the escape hatch (unchanged by the generalization):
- **Tier B 鈥?surgery, one issue per package**: semver-major jumps,
- **Tier B surgery, one issue per package**: semver-major jumps,
adapter/peer fallout, or overrides/catalog surgery keep the
per-package issue: `title="[{origin}] {CVE-ID/GHSA-ID} in {package} (TD-{NNN})"`
with the same labels; body requirements match the Tier A rows.
@@ -148,7 +148,7 @@ Tier B and the escape hatch (unchanged by the generalization):
issue when same-day remediation is required (urgent HIGH/CRITICAL).
De-duplicate against open `tech-debt` issues (match by
CVE/GHSA ID) before creating. Record the `TD-NNN 鈫?#NNNN` mapping in the
CVE/GHSA ID) before creating. Record the `TD-NNN #NNNN` mapping in the
release notes. See `verify` Phase 5.5 for the tech-debt promotion body
template and `_shared/gitea-write-patterns.md` Pattern 3.
@@ -157,19 +157,19 @@ template and `_shared/gitea-write-patterns.md` Pattern 3.
| Check | Status |
| ----------------- | ----------------------------------------------------- |
| Clean workspace | 鉁?/ 鉂? |
| Clean workspace | ✅/ ❌ |
| Branch | {branch name} |
| Build | 鉁?/ 鉂? |
| Typecheck + Lint | 鉁?/ 鉂? |
| Tests | 鉁?/ 鉂?(N passed, M failed) |
| Dependency audit | 鉁?/ 鈿狅笍 N known CVEs (pre-existing) / 鉂?N new CVEs |
| Build | ✅/ ❌ |
| Typecheck + Lint | ✅/ ❌ |
| Tests | ✅/ ❌(N passed, M failed) |
| Dependency audit | ✅/ ⚠️ N known CVEs (pre-existing) / N new CVEs |
```
If any gate fails except known CVEs, stop and report what failed.
---
## Phase 2 鈥?Version Bump
## Phase 2 Version Bump
Determine the new version by inspecting git history since the last tag.
@@ -193,14 +193,14 @@ Determine the new version by inspecting git history since the last tag.
| `docs:` / `chore:` | (skip) | Not user-visible |
If no conventional prefix found, infer from the subject line:
- "add", "implement", "introduce" 鈫?MINOR
- "fix", "resolve", "correct" 鈫?PATCH
- "remove", "drop", "rename" (public API) 鈫?MAJOR
- "add", "implement", "introduce" MINOR
- "fix", "resolve", "correct" PATCH
- "remove", "drop", "rename" (public API) MAJOR
5. **Compute bump**:
- If any MAJOR commit 鈫?bump MAJOR.
- Else if any MINOR commit 鈫?bump MINOR.
- Else 鈫?bump PATCH.
- If any MAJOR commit bump MAJOR.
- Else if any MINOR commit bump MINOR.
- Else bump PATCH.
```markdown
## Version Bump
@@ -210,12 +210,12 @@ Determine the new version by inspecting git history since the last tag.
**New version**: {new version}
**Type**: MAJOR / MINOR / PATCH
**Commits since last tag**: {N}
**Reason**: {justification 鈥?e.g. "2 feat + 3 fix 鈫?MINOR"}
**Reason**: {justification e.g. "2 feat + 3 fix MINOR"}
```
---
## Phase 3 鈥?Changelog
## Phase 3 Changelog
Generate the changelog from `git log <last-tag>..HEAD`:
@@ -224,10 +224,10 @@ Generate the changelog from `git log <last-tag>..HEAD`:
- Scope (if present, e.g. `feat(auth):`).
- Description (the subject line, past tense, human-readable).
2. **Group by type**:
- **Added** 鈥?`feat:` commits.
- **Changed** 鈥?modifications to existing behavior (non-breaking).
- **Fixed** 鈥?`fix:` commits.
- **Breaking** 鈥?`BREAKING CHANGE:` or `!:` commits.
- **Added** `feat:` commits.
- **Changed** modifications to existing behavior (non-breaking).
- **Fixed** `fix:` commits.
- **Breaking** `BREAKING CHANGE:` or `!:` commits.
3. **Deduplicate**: squash multiple commits for the same change into one entry
where it makes narrative sense.
4. Read the existing root `CHANGELOG.md` (if any) and prepend this release.
@@ -235,7 +235,7 @@ Generate the changelog from `git log <last-tag>..HEAD`:
Write to root `CHANGELOG.md` (prepend section).
```markdown
## [{version}] 鈥?{YYYY-MM-DD}
## [{version}] {YYYY-MM-DD}
### Added
@@ -251,24 +251,24 @@ Write to root `CHANGELOG.md` (prepend section).
### Breaking
- {breaking change} ({hash}) 鈥?see migration notes above
- {breaking change} ({hash}) see migration notes above
```
---
## Phase 4 鈥?Tag & Finalize
## Phase 4 Tag & Finalize
1. **Update version file** 鈥?write the new version to the project's version
1. **Update version file** write the new version to the project's version
manifest.
2. **Commit**: `git add` version file + changelog file, commit with message:
```
release: {version}
```
3. **Tag**: `git tag v{version}` (adjust prefix per project convention 鈥?
3. **Tag**: `git tag v{version}` (adjust prefix per project convention
check existing tags with `git tag -l`).
4. **Verify tag**: `git tag -l v{version}` confirms the tag exists.
**Do not push** 鈥?the user must explicitly request pushing to remote.
**Do not push** the user must explicitly request pushing to remote.
```markdown
## Release Artifact
@@ -282,15 +282,15 @@ Write to root `CHANGELOG.md` (prepend section).
| File | Change |
| -------------- | ------------------------- |
| {version file} | {old} 鈫?{new} |
| {version file} | {old} {new} |
| CHANGELOG.md | Prepended {version} |
```
---
## Phase 4b 鈥?Publish Release Artifacts (octopus project, manual)
## Phase 4b Publish Release Artifacts (octopus project, manual)
> Octopus-specific. Other projects: substitute your own artifact pipeline 鈥?
> Octopus-specific. Other projects: substitute your own artifact pipeline
> the goal is identical (turn the tag into downloadable assets).
The CI publish pipeline (`.gitea/workflows/publish.yml`) was **retired by
@@ -303,17 +303,17 @@ credentials in the environment.
- Clean checkout of the release commit (tag pushed or about to be pushed).
- Credentials in env:
- `GITEA_TOKEN` 鈥?PAT with `write:repository` (release create/undraft,
- `GITEA_TOKEN` PAT with `write:repository` (release create/undraft,
tag push) and `write:package` (container registry). The `CI_PAT` secret
value is the canonical token.
- `NODE_AUTH_TOKEN` 鈥?only if publishing to npm.
- `AUR_KEY` 鈥?only if pushing the AUR package.
- `NODE_AUTH_TOKEN` only if publishing to npm.
- `AUR_KEY` only if pushing the AUR package.
- Docker logged in to the Gitea container registry:
`echo "$GITEA_TOKEN" | docker login <instance-registry-host> -u <user> --password-stdin`.
### Steps
1. **Version + draft release** (idempotent 鈥?skips if already published):
1. **Version + draft release** (idempotent skips if already published):
```bash
GITEA_TOKEN=<pat> GH_REPO=Octopus/octopus bun script/version.ts
```
@@ -344,7 +344,7 @@ credentials in the environment.
-H "Content-Type: application/json" -d '{"draft": false}'
```
5. **Verify assets** 鈥?the release must carry 12 assets:
5. **Verify assets** the release must carry 12 assets:
```bash
curl -sS "<instance-base-url>/api/v1/repos/Octopus/octopus/releases/tags/v{version}" \
-H "Authorization: token $GITEA_TOKEN" | jq '.assets | length'
@@ -368,7 +368,7 @@ credentials in the environment.
---
## Phase 5 鈥?Rollback Plan
## Phase 5 Rollback Plan
Document how to undo this release:
@@ -379,7 +379,7 @@ Document how to undo this release:
2. **Data rollback** (if applicable):
- For each migration, confirm the `down` migration exists and has been tested.
- If the release changes data format without a reversible migration, mark
`鈿狅笍 IRREVERSIBLE DATA CHANGE`.
`⚠️ IRREVERSIBLE DATA CHANGE`.
```markdown
## Rollback Plan
@@ -403,7 +403,7 @@ git tag -d v{version}
---
## Phase 6 鈥?Post-release Smoke Test
## Phase 6 Post-release Smoke Test
1. Run the project's build command on the tagged commit. Must pass.
2. Run the test suite. Must pass.
@@ -411,15 +411,15 @@ git tag -d v{version}
---
## Phase 7 鈥?Report
## Phase 7 Report
```markdown
## Release Report
**Version**: {old} 鈫?{new} (MAJOR / MINOR / PATCH)
**Version**: {old} {new} (MAJOR / MINOR / PATCH)
**Tag**: v{version}
**Commits**: {N} since last tag ({feat} features, {fix} fixes)
**Typecheck**: 鉁?| Lint: 鉁?| Tests: 鉁?
**Typecheck**: | Lint: | Tests:
### Changelog
@@ -427,21 +427,21 @@ git tag -d v{version}
### Release Artifacts
- Commit: {hash} 鈥?`release: {version}`
- Commit: {hash} `release: {version}`
- Tag: v{version}
- Changelog: CHANGELOG.md updated
---
**Deploy**: {manual step 鈥?"merge to main triggers CI", etc.}
**Deploy**: {manual step "merge to main triggers CI", etc.}
**Rollback**: see Phase 5 above
**Next**: `core/skills/retrospective/SKILL.md` (optional 鈥?run on any project state)
**Next**: `core/skills/retrospective/SKILL.md` (optional run on any project state)
```
---
## References
- `core/checklists/release.md` 鈥?Release checklist
- `core/checklists/release.md` Release checklist
- Semver spec: https://semver.org
- Conventional Commits: https://www.conventionalcommits.org