refactor(P06): rename milestone type schema-breaking → major, reinforce release flow

---ci---
phase: 6
milestone: v0.10
status: execute
decisions:
  - id: D-001
    decision: Rename MilestoneType schema-breaking to major for clarity
    rationale: Major better describes the semver impact (major version bump) and aligns with standard semver terminology
    confidence: 0.95
    alternatives: [schema-breaking, breaking, major-change]
  - id: D-002
    decision: Add autopilot rules, PR+QA gates, and merge validation to ship workflow
    rationale: Release flow was documented but not enforced in the workflow. Zero-HITL rules, branch hierarchy validation, and coreci packaging steps ensure consistent releases
    confidence: 0.90
    alternatives: [keep-as-documentation-only, add-to-AGENTS.md-only]
---/ci---
This commit is contained in:
Jon Chery
2026-06-01 15:29:43 +00:00
parent e2b749d42e
commit f478088797
12 changed files with 187 additions and 68 deletions
+4 -4
View File
@@ -1002,7 +1002,7 @@ function computeShipVersion(
projectPath: string,
phaseNum: number,
config: CIAgentConfig
): { tag: string; milestoneType: "nfr" | "feature" | "schema-breaking" } {
): { tag: string; milestoneType: "nfr" | "feature" | "major" } {
const tags = execSync("git tag -l", { cwd: projectPath, encoding: "utf-8" })
.split("\n")
.map((t) => t.trim())
@@ -1029,7 +1029,7 @@ function computeShipVersion(
const milestoneType = inferMilestoneType(projectPath);
let tag: string;
if (milestoneType === "schema-breaking") {
if (milestoneType === "major") {
tag = `v${major}.${minor + phaseNum}.0`;
} else {
tag = `v${major}.${minor}.${phaseNum}`;
@@ -1038,10 +1038,10 @@ function computeShipVersion(
return { tag, milestoneType };
}
function inferMilestoneType(projectPath: string): "nfr" | "feature" | "schema-breaking" {
function inferMilestoneType(projectPath: string): "nfr" | "feature" | "major" {
try {
const log = execSync("git log --oneline -50", { cwd: projectPath, encoding: "utf-8" });
if (log.match(/\brefactor\b|\brewrite\b|\bmigrate\b|\brestructure\b/i)) return "schema-breaking";
if (log.match(/\brefactor\b|\brewrite\b|\bmigrate\b|\brestructure\b/i)) return "major";
if (log.match(/\bfeat\b/)) return "feature";
return "nfr";
} catch {
+3 -3
View File
@@ -329,7 +329,7 @@ describe("CIAgentFiles", () => {
expect(ciFiles.getMilestoneType()).toBe("feature");
});
it("returns schema-breaking when phases include refactor/rewrite/migrate", () => {
it("returns major when phases include refactor/rewrite/migrate", () => {
const ciFiles = new CIAgentFiles(dir, "schema-proj");
ciFiles.ensureProjectDir();
fs.writeFileSync(path.join(dir, ".ciagent", "config.json"), JSON.stringify({
@@ -337,13 +337,13 @@ describe("CIAgentFiles", () => {
active_project: "schema-proj",
}));
const roadmap: RoadmapMd = {
overview: "schema-breaking",
overview: "major",
phases: [
{ number: 1, name: "refactor-core", description: "Refactor core", status: "in_progress", dependsOn: [], requirements: [], successCriteria: [] },
],
};
ciFiles.writeRoadmapMd(roadmap);
expect(ciFiles.getMilestoneType()).toBe("schema-breaking");
expect(ciFiles.getMilestoneType()).toBe("major");
});
});
+1 -1
View File
@@ -486,7 +486,7 @@ export class CIAgentFiles {
}
}
if (hasSchemaBreak) return "schema-breaking";
if (hasSchemaBreak) return "major";
if (hasFeature) return "feature";
return "nfr";
}
+2 -2
View File
@@ -192,11 +192,11 @@ describe("GitBranch", () => {
expect(tag).toBe("v0.6.0");
});
it("computes next major for schema-breaking milestone", () => {
it("computes next major for major milestone", () => {
execSync(`git tag -a v0.5.1 -m "v0.5.1"`, { cwd: repoDir, stdio: "pipe" });
const gitBranch = new GitBranch(repoDir);
const tag = gitBranch.computeMilestoneTag("schema-breaking");
const tag = gitBranch.computeMilestoneTag("major");
expect(tag).toBe("v1.0.0");
});
+1 -1
View File
@@ -242,7 +242,7 @@ export class GitBranch {
}
}
if (milestoneType === "schema-breaking") {
if (milestoneType === "major") {
return `v${major + 1}.0.0`;
}
+2 -2
View File
@@ -307,7 +307,7 @@ status: execute
expect(ctx.getMilestoneType()).toBe("feature");
});
it("returns schema-breaking when refactor commits exist", () => {
it("returns major when refactor commits exist", () => {
commit(repoDir, `refactor(P01): rewrite core
---ci---
@@ -317,7 +317,7 @@ status: execute
---/ci---`);
const ctx = new GitContext(repoDir);
expect(ctx.getMilestoneType()).toBe("schema-breaking");
expect(ctx.getMilestoneType()).toBe("major");
});
});
});
+1 -1
View File
@@ -333,7 +333,7 @@ export class GitContext {
if (!commit.ci) continue;
hasAnyCiCommit = true;
if (commit.type === "feat") return "feature";
if (commit.type === "refactor" || commit.scope === "init") return "schema-breaking";
if (commit.type === "refactor" || commit.scope === "init") return "major";
}
if (!hasAnyCiCommit) return "nfr";
return "nfr";
+1 -1
View File
@@ -7,7 +7,7 @@ export type ModelProfile = "quality" | "speed" | "balanced";
export type BranchingStrategy = "phase" | "feature" | "trunk";
export type MilestoneType = "nfr" | "feature" | "schema-breaking";
export type MilestoneType = "nfr" | "feature" | "major";
export type PhaseName = "research" | "plan" | "execute" | "verify" | "complete";