feat(P06): 3-tier versioning, branch hierarchy enforcement, ARCHITECTURE-PLAN synthesis

---ci---
phase: 6
milestone: v0.5
status: complete
decisions:
  - id: D-006
    decision: Research as intermediate work product
    rationale: Conclusions update .ci/ files; full research doc intentionally not preserved
    confidence: 0.90
  - id: D-007
    decision: Branch hierarchy enforcement: main > milestone > phase
    rationale: Prevents out-of-order merges and semantically wrong tags
    confidence: 0.92
  - id: D-008
    decision: 3-tier versioning: NFR/feature/schema-breaking
    rationale: Patch per phase (NFR/feature) or minor per phase (schema-breaking); milestone gets minor (feature) or major (schema-breaking)
    confidence: 0.95
requirements:
  covered: [VER-06, BRANCH-01, BRANCH-02, ARCH-01]
---/ci---

- Synthesize ARCHITECTURE-PLAN.md into .ci/ci/ARCHITECTURE.md (expanded 51→230 lines)
- Add D-006/D-007/D-008 to .ci/ci/PROJECT.md key decisions table
- Delete ARCHITECTURE-PLAN.md after synthesis
- Rewrite ship.md with 3-tier versioning model + branch hierarchy merge flows
- Rewrite branch-strategy.md with 3-tier versioning + branch hierarchy + version validation
- Add MilestoneType to config types
- Replace isNfrMilestone() with getMilestoneType() returning nfr|feature|schema-breaking
- Add validateMergeOrder(), mergeMilestoneBranch(), computeMilestoneTag() to GitBranch
- Add computeShipVersion(), validateVersionOrder(), resolveMergeTarget() to ship command
- Remove hardcoded v0.5. from error-recovery rollback
- Create .githooks/pre-push for semver ordering + branch hierarchy validation
- Add 15 new tests (370 total, all passing)
This commit is contained in:
Jon Chery
2026-05-29 17:18:10 +00:00
parent 3d069319b5
commit ab6af144b7
14 changed files with 696 additions and 93 deletions
+6 -5
View File
@@ -81,17 +81,18 @@ export class ErrorRecovery {
this.git(`branch -D ${phaseBranch}`);
}
const tag = `v0.5.${phase}`;
const tags = this.git("tag -l").split("\n").map((t) => t.trim());
if (tags.includes(tag)) {
this.git(`tag -d ${tag}`);
const tags = this.git("tag -l").split("\n").map((t) => t.trim()).filter(Boolean);
const phaseTagPattern = new RegExp(`^v\\d+\\.\\d+\\.${phase}$`);
const matchingTag = tags.find((t) => phaseTagPattern.test(t));
if (matchingTag) {
this.git(`tag -d ${matchingTag}`);
}
return {
recovered: true,
strategy: "rollback",
attempts: 1,
message: `Rolled back phase ${phase}: ${reason}. Branch ${branchExists ? `${phaseBranch} deleted` : "not found"}. Tag ${tags.includes(tag) ? `${tag} deleted` : "not found"}.`,
message: `Rolled back phase ${phase}: ${reason}. Branch ${branchExists ? `${phaseBranch} deleted` : "not found"}. Tag ${matchingTag ? `${matchingTag} deleted` : "not found"}.`,
};
} catch (err) {
return {