---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---
10 KiB
description: Ship CIAgent phase or milestone — Full autopilot release: validate, test, merge, tag, push, release. Zero HITL
CIAgent Ship
Ship a CIAgent phase or milestone. Every ship creates a release — no exceptions.
Usage: ciagent-ship [phase_number|milestone]
Autopilot Rules
These rules are non-negotiable. The ship workflow runs in full autopilot mode:
- Zero HITL — no confirmation prompts, no approval gates, no requests for human input. The agent executes the entire release flow autonomously.
- No Shortcuts — deep validation, testing, and merge checks must all run in full. The lack of HITL is not an excuse to skip steps.
- Notification Only — status updates are informational, not requests for approval. Report outcomes, never ask permission.
- Autonomous Loop on Failure — if any step fails (tests, pipeline, merge conflicts), iterate autonomously until success. Do NOT ask the user for guidance on how to fix a failing test or pipeline.
- Branch Hierarchy Enforced —
main > milestone/vX.X-slug > phase/NN-slug. Phase merges into milestone, milestone merges into main. This is validated, not assumed.
Milestone Type and Versioning
The milestone type is determined before any development work and governs all versioning for the entire milestone.
Define semver at milestone start: establish the version and milestone type before writing code.
Determine milestone type by calling getMilestoneType() which returns "nfr" | "feature" | "major":
| Milestone Type | Condition | Phase release | Milestone release |
|---|---|---|---|
| NFR | All phases are fix/chore/docs/perf/refactor/test | Patch — v1.8.1, v1.8.2, ... |
None — final patch IS the deliverable |
| Feature | At least one phase has new features (feat) |
Patch — v1.8.1, v1.8.2, ... |
Next minor — v1.9.0 |
| Major | Breaking schema changes or complete refactor | Minor — v2.1.0, v2.2.0, ... |
Major — v3.0.0 |
Tag rules (CRITICAL):
- Milestone tags are always the NEXT version, never the base:
- Feature: patches v0.5.1–v0.5.5 → milestone tag is v0.6.0 (NOT v0.5.0)
- Major: minors v0.3.0, v0.4.0, v0.5.0 → milestone tag is v1.0.0
- NFR: no milestone tag — the final patch release IS the deliverable
- Tags must be strictly greater than all existing tags on the same major.minor line
- NEVER create a milestone tag that is semantically below existing phase tags
Step 0: Confirm Active Project
Check ci listProjects() or read .ciagent/config.json to determine if multi-project mode is active.
If .ciagent/config.json has projects[] with length > 0:
- Confirm
active_projectis correct for this ship - If not, set it with
ci setActiveProject(<slug>) - All commit messages must include
project: <slug>in---ci---block - Branch names are prefixed with
<slug>/in multi-project mode
If single-project mode: proceed with existing conventions.
Step 1: Pre-Flight Validation
git log --max-count=10
git branch -a
git tag -l
Determine what is being shipped: a single phase or an entire milestone.
Read .ciagent/ROADMAP.md to determine:
- Current milestone version (e.g.,
v0.2) - Phase number within the milestone
- Whether this is the last phase in the milestone
Read .ciagent/config.json for autonomy level.
Validation gates — all must pass before proceeding:
- Milestone type resolved —
getMilestoneType()must return"nfr" | "feature" | "major". Stop if undefined. - Branch hierarchy correct — phase branch exists and targets the correct parent (milestone branch, or main if no milestone branch exists).
- No unmerged phase branches — if shipping a milestone, all phase branches for this milestone must be merged into the milestone branch.
- Tag sequence valid — the computed tag must be strictly greater than all existing tags on the same major.minor line. Check with
git tag -l. - Autonomy confirmed —
.ciagent/config.jsonautonomy level must befull. This is the zero-HITL enforcement point.
If any validation fails: stop and report. Do NOT proceed past a failed gate.
Step 2: Run Tests
npm test
npm run typecheck
npm run build
If any fail: iterate autonomously until tests pass. Do NOT ask the user for guidance — debug and fix.
Step 3: Create PR and Quality Assurance
Open a Pull Request for the merge target:
tea pr create --base <target-branch> --head <source-branch> --title "ship: [phase-name or milestone-name]"
- For a phase ship: PR from
phase/NN-slugintomilestone/vX.Y-slug(ormainif no milestone branch). - For a milestone ship: PR from
milestone/vX.Y-slugintomain.
Auto-merge configuration:
Set the PR to auto-merge upon pipeline success:
tea pr merge <pr-number> --auto --squash
Review:
Conduct a thorough autonomous review of the PR diff. Check:
- All expected files are included
- No unintended changes slipped in
- No secrets or credentials in the diff
- All
---ci---blocks have correct metadata
Finalization:
- On pipeline success: the PR auto-merges. Proceed to Step 4.
- On pipeline failure: iterate autonomously until the pipeline passes. Do NOT merge a PR with a failing pipeline. Do NOT ask for guidance.
Strict rule: Never merge a PR with a failed pipeline. No exceptions.
Step 4: Compute Version
| What's shipping | Milestone Type | Phase release | Milestone release | Example |
|---|---|---|---|---|
| Single phase | NFR | Patch vX.Y.Z |
N/A | v0.1.3 (3rd NFR phase) |
| Single phase | Feature | Patch vX.Y.Z |
N/A | v0.2.3 (3rd feature phase) |
| Single phase | Major | Minor vX.(Y+N).0 |
N/A | v0.4.0 (2nd major phase) |
| Milestone completion | NFR | Patch (last phase) | None | v0.1.3 (no milestone tag) |
| Milestone completion | Feature | Last patch | Minor vX.(Y+1).0 |
v0.3.0 (NOT v0.2.0) |
| Milestone completion | Major | Last minor | Major v(X+1).0.0 |
v1.0.0 |
Phase number within the milestone determines the increment:
- NFR/Feature: 1st phase = .1, 2nd = .2, etc. (v0.5.1, v0.5.2)
- Major: 1st phase = next minor, 2nd = minor+1, etc. (v0.3.0, v0.4.0)
Tag validation (before creating ANY tag):
- Tag must be strictly greater than all existing tags on the same major.minor line
- Milestone completion tag must be next minor (feature) or next major (major)
- NEVER create a milestone tag that is semantically below existing phase tags (e.g., v0.5.0 when v0.5.1 already exists)
Step 5: Merge Branch
Branch hierarchy: main > milestone/vX.X-slug > phase/NN-slug
Merge validation gates
Phase → Milestone:
- VALIDATED — must target milestone branch when one exists
- REJECTED if milestone branch does not exist for this phase's milestone
Phase → Main:
- VALIDATED — only allowed when NO milestone branch exists for this phase's milestone
- REJECTED if a milestone branch exists for this milestone
Milestone → Main:
- VALIDATED — only after all phase branches are merged
- REJECTED if any phase branches for this milestone are unmerged
Phase ship
If milestone branch exists:
git checkout milestone/vX.Y-slug
git merge --squash phase/NN-slug
git commit -m "docs(P##): complete [phase-name] phase
---ci---
phase: [N]
milestone: [vX.Y]
status: complete
requirements:
covered: [REQ-01, REQ-02]
partial: []
---/ci---"
If no milestone branch exists (single-phase milestone):
git checkout main
git merge --squash phase/NN-slug
git commit -m "docs(P##): complete [phase-name] phase
---ci---
phase: [N]
milestone: [vX.Y]
status: complete
requirements:
covered: [REQ-01, REQ-02]
partial: []
---/ci---"
Milestone ship (after last phase)
Validate all phase branches are merged into the milestone branch before proceeding.
git checkout main
git merge --squash milestone/vX.Y-slug
git commit -m "docs(milestone): complete [milestone-name]
---ci---
phase: 0
milestone: [vX.Y]
status: complete
---/ci---"
Step 6: Tag and Push
git tag -a vX.Y.Z -m "vX.Y.Z: [phase-name or milestone-name]"
git push origin main --tags
Tag format by milestone type:
- NFR/Feature phase: patch format (
v0.5.1,v0.5.2) - Major phase: minor format (
v0.3.0,v0.4.0) - Feature milestone: next minor (
v0.6.0, NOTv0.5.0) - Major milestone: next major (
v1.0.0)
Step 7: Create Release and Package
Every ship creates a Gitea release. No exceptions.
Generate release notes
git log v[previous_tag]..vX.Y.Z --oneline
Create the Gitea release
curl -X POST "https://git.cloudinit.dev/api/v1/repos/continuous-intelligence/ci/releases" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"tag_name":"vX.Y.Z","name":"vX.Y.Z","body":"[release notes from git log]"}'
For milestone releases, include a summary of all phases completed and requirements covered.
Create distribution packages
Use coreci to create the necessary distribution packages:
coreci build --tag vX.Y.Z
coreci package --tag vX.Y.Z
Upload packages to the Gitea release:
coreci release upload --tag vX.Y.Z --files [built-artifacts]
Generate documentation
Include release notes in the Gitea release body with:
- Summary of changes
- Requirements covered
- Known issues (if any)
- Migration notes (for major milestones)
Step 8: Update .ci/ Files
- Update
.ciagent/REQUIREMENTS.md— mark shipped requirements as complete - Update
.ciagent/ROADMAP.md— mark shipped phase as complete
Commit the file updates.
Step 9: Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CIAgent ► SHIPPED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Phase [N]: [name]
Milestone: [vX.Y] ([nfr|feature|major])
Version: vX.Y.Z
Release: https://git.cloudinit.dev/continuous-intelligence/ci/releases/tag/vX.Y.Z
Status: complete
Tests: PASS
Typecheck: PASS
Build: PASS
Pipeline: PASS
Requirements covered: [N]
Commits: [N]
[If milestone complete:]
All phases in milestone v0.2 complete. Milestone released as vX.Y.Z.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━