CoAgent8 - Source API
    Preparing search index...

    P0: Git Workflow, Versioning & Release Process (02-git-workflow.md)

    Priority Level: P0 (Critical System Invariant) Direct pushes and force pushes to develop or to a release line (X.Y.x) are strictly forbidden. This rule is the single source for branching, commits, pull requests, versioning, releases and issue handling. Other documents reference it.

    The process follows widely used conventions: Semantic Versioning 2.0.0, Conventional Commits 1.0.0, Keep a Changelog 1.1.0 and the develop plus release-line model of PrestaShop (owner decision 2026-10-10): a permanent integration branch, one branch per maintained X.Y line, releases as tags on those branches, and squash-merged pull requests.

    Every commit on develop and on a line is a squash commit that GitHub created from one pull request: <PR title> (#N), signed by GitHub and therefore shown as Verified. Nothing reaches these branches any other way. Every change - features, fixes, releases, backports - travels as its own pushed branch and PR.

    Action Agent Owner
    Topic branch, commits, local checks, changelog regeneration Yes Yes
    Push a topic branch, open or update a PR Only after the owner's explicit go-ahead in the session Yes
    Independent review (03-author-reviewer) Yes (Reviewer role) Yes
    Merge a PR, create a release line, push a tag Never Yes
    Publish a GitHub Release, approve the npm environment, publish or deprecate on npm, publish on the VS Code Marketplace, change repository settings Never Yes

    An agent prepares release PRs, release notes and evidence (section 5) and stops. It never states or implies that a push, merge, tag or publication happened unless it observed it.


    Branch Purpose Created from Merges into Lifetime
    develop Default branch. Integration of the next version; betas are tagged here - - Permanent
    X.Y.x (for example 1.0.x) Release line of version X.Y: its release candidates (for 1.0 the previews after feature freeze, such as 0.8.0 and 0.9.0), the final X.Y.0 and patches X.Y.Z develop at feature freeze (the release commit of the first release candidate) - (receives backports) Until the line's end of support
    Topic branch One change develop (a backport branch: the line) Its source branch Until merged
    • There is no main branch (owner decision 2026-10-10). The repository's front page is develop; released states are tags and GitHub Releases.
    • Release stages are tags, never branches, named vX.Y.Z after the version (section 4): betas v0.6.0 -> v0.7.0 (on develop) -> release candidates v0.8.0 -> v0.9.0 -> v1.0.0 -> v1.0.1 (on 1.0.x). How many betas and release candidates there are follows the roadmap's release acceptance; each preview takes the next minor. A tag freezes the exact state of a stage forever.
    • The first release is v0.6.0 (prepared as 1.0.0-beta.2), the first squash commit of that work on develop. The npm name placeholder 1.0.0-beta.1 holds the place of 0.5.0: the owner withdraws it from npm, and it has no tag, GitHub Release or changelog entry (owner decision 2026-10-11, REPO-003).
    • Feature freeze creates the line: the owner branches X.Y.x from develop at the release commit of its first release candidate (for 1.0: the first preview tagged on 1.0.x). From then on develop carries the next version's features and X.Y.x takes only release-blocking fixes and, after X.Y.0, patch fixes.
    • Fixes for a line land on develop first. A fix that a maintained line also needs is then backported: a branch backport/<N>-<desc> from the line with git cherry-pick -x <develop-sha>, and a PR into the line titled like the original with the suffix (backport #N), squash-merged. Only a fix that does not apply to develop (code already gone there) targets the line directly.
    • No merge commits. develop and the lines have linear history of squash commits only. A line is never merged into develop; the changelog of each branch is generated on that branch (section 6).
    • Branch names never equal tag names: lines are X.Y.x, tags are vX.Y.Z....

    Format: <type>/<short-kebab-description>, optionally with the issue number: fix/123-windows-teardown-identity, feat/session-mode-none, docs/release-process.

    Prefix Use
    feat/ New user-visible capability
    fix/ Bug fix
    perf/ Performance improvement without behavior change
    refactor/ Internal restructuring without behavior change
    docs/ Documentation and contributor rules only
    test/ Tests only
    build/, ci/ Build system, packaging or CI workflow
    chore/ Maintenance that fits no other type (dependency bumps, tooling)
    release/ A release PR (section 5): release/v0.7.0
    backport/ A cherry-pick of a merged develop fix into a line (above)

    Keep a topic branch focused on one concern. Rebase it onto its target to pick up changes (git rebase origin/develop). The author may force-push their own topic branch with --force-with-lease before merge; never force-push a branch someone else is working on.


    Every commit that lands on develop or a line - in practice, every squash-merge commit - must follow Conventional Commits 1.0.0:

    <type>(<scope>)!: <subject>
    
    <body>
    
    <footers>
    
    • type (lowercase): feat, fix, perf, refactor, docs, test, build, ci, chore, revert. feat and fix appear in release notes; feat implies a minor version bump after 1.0.0, fix a patch bump.
    • scope (optional, lowercase): the owning module or area, for example process, history, sessions, redaction, routing, adapters, server, setup, vscode, rules, release, deps.
    • ! before the colon, together with a BREAKING CHANGE: footer, marks an incompatible change to the MCP tool contract, configuration, stored data or CLI.
    • subject: imperative mood ("add", not "added"), no trailing period, at most 72 characters including type and scope, English (see 06-language-and-style).
    • body (required unless trivial): wrapped at 72 characters; explain why the change is needed and what behavior changes, not a file list.
    • footers (one per line):
      • Fixes #123 / Refs #123 - linked GitHub issue;
      • Refs: AUD-P0-1 - audit finding or roadmap item;
      • BREAKING CHANGE: <description and migration>;
    • No AI attribution (forbidden): commits, pull requests, changelogs and release notes never credit an AI tool as author or co-author. Do not add a Co-Authored-By trailer for an AI (Claude, Codex, Gemini, Antigravity or any other), a "Generated with" line or a similar note. AI tools are tools paid for by the owner, who is the sole author and copyright holder. The Reviewer rejects a commit or PR that contains AI attribution.

    Examples:

    fix(process)!: identify Windows descendants by PID and creation time
    
    The CIM sweep matched processes by ParentProcessId alone, so a reused PID
    could select unrelated user processes. Tree selection now runs in a pure
    function that rejects children created before their parent.
    
    BREAKING CHANGE: terminateProcessTree no longer accepts extraPids.
    Fixes #42
    Refs: AUD-P0-1
    
    docs(rules): define release lines, tags and PR process
    

    Commits on topic branches disappear in the squash, but their headers must still be valid Conventional Commits: the changelog regeneration that runs before every push (section 6) rejects any other subject. The pull request title and description become the final commit, so they must meet this section.


    • Target develop; a backport targets its line (section 1). A release PR targets the branch that will carry the tag (section 5). Push the branch only after the owner's go-ahead (section 0); GitHub needs it to open the PR.
    • Title: a valid Conventional Commit header (section 2). It becomes the squash-merge subject and the changelog entry. Preview that entry with the changelog check (section 6) before opening the PR and whenever the title changes.
    • Open as draft while work or verification is incomplete.
    • One concern per PR. Prefer under ~400 changed lines excluding generated files and lockfiles; split larger work into reviewable steps.
    • Description (English) with these sections:
      1. Summary - what changes and why.
      2. Links - Fixes #... / Refs #..., roadmap item and audit finding IDs.
      3. Changes - notable behavior, contract or migration effects, and the pending changelog entry from the title preview (section 6).
      4. Verification - the commands run, platform and Node version, and each result as PASS, FAIL or NOT_RUN with a reason, selected per 04-quality-gate. Never report an unexecuted check as PASS.
      5. Risk and rollback - what could break and how to revert.
      6. Checklist - docs, runtime contract and roadmap status updated where behavior changed; CHANGELOG.md regenerated, never edited by hand (section 6); the title preview passed; no secrets, local paths or personal data in the diff.
    • Required before merge:
      • all required CI checks green on the PR's latest commit;
      • an independent review by the Reviewer per 03-author-reviewer, on the latest commit, with no unresolved P1/P2 finding;
      • all review conversations resolved;
      • the branch up to date with its target.
    • The Author never approves their own PR. When GitHub approvals require a second account that does not exist, record the Reviewer's verdict in the PR instead.
    • Address findings with new commits; do not rewrite history during review unless the Reviewer agrees.
    • Merge method: Squash and Merge, then delete the topic branch:
      gh pr merge <number> --squash --delete-branch
      
      Before confirming, edit the squash message so that it complies with section 2 (keep footers such as Fixes #... and BREAKING CHANGE:; remove any AI attribution). There is no other merge method: the rulesets allow only squash.

    • Versions follow SemVer 2.0.0 without pre-release identifiers (owner decision 2026-10-11, REPO-003). The npm package, the VS Code extension and the Git tag carry the same numeric X.Y.Z, with no mapping between them. VS Code accepts only a numeric extension version and offers Restart Extensions after an update only when that number changes; the Marketplace refuses a repeated version. scripts/build-vscode.cjs refuses any other version.
    • A preview is every version below 1.0.0. Each preview, beta or release candidate, raises the minor: 0.5.0 is skipped (the withdrawn npm name placeholder 1.0.0-beta.1 held it), then 0.6.0 (the first release, prepared as 1.0.0-beta.2), 0.7.0, 0.8.0, 0.9.0; further previews would continue with 0.10.0. A release of a preview that only fixes it raises the patch instead (owner decision 2026-10-11): 0.6.1, 0.6.2; it ships as a preview like its minor. The final release is 1.0.0. A preview is a VS Code pre-release, a GitHub pre-release and npm next; isPreview in scripts/build-vscode.cjs and the release workflows apply this rule. How a version after 1.0.0 is previewed is an owner decision before the first such preview.
    • Beta: feature-incomplete or not fully hardened; distributed to invited testers as a preview. Release candidate: scope frozen on the line; only release-blocking fixes. The roadmap's release acceptance defines each stage's entry gate.
    • The version is changed only in a release PR (section 5), consistently in package.json, package-lock.json, plugin.json, extensions/vscode/package.json and CHANGELOG.md. Runtime constants read it from package.json.
    • A build from an untagged commit is a development build and is never distributed, even though it carries the last version string.
    • Published versions are immutable. A correction is always a new version number; a tag is never moved, deleted or reused (the tag rulesets enforce it).
    npm dist-tag Holds Install
    next The newest preview (a version below 1.0.0) npm install coagent8@next
    latest The newest final release npm install coagent8
    • A preview is never published to latest. npm always keeps a latest tag, so while only previews exist it can point at one; the README install instructions use @next until 1.0.0.
    • The beta dist-tag is retired; the owner removes it when publishing 0.6.0 (npm dist-tag rm coagent8 beta).

    Every release follows the same five phases. The owner performs every action marked (owner); an agent may prepare everything else.

    1. Gate: the stage's entry gate in the roadmap is satisfied on the target branch with green CI. Betas target develop; release candidates, X.Y.0 and patches target X.Y.x (for the first release candidate, the owner creates X.Y.x from develop first).
    2. Branch release/vX.Y.Z from the target. One commit chore(release): vX.Y.Z that only:
      • sets the version (section 4) where it differs;
      • regenerates CHANGELOG.md with npm run changelog -- --tag vX.Y.Z, which writes the commits since the previous tag under the new version heading with the release date (section 6).
    3. Run the full local gate (04-quality-gate) on that commit and record platform, Node, commit, tree and artifact digests.
    4. Open the PR titled chore(release): vX.Y.Z; attach the local gate evidence and the release notes preview (npm run release-notes -- --tag vX.Y.Z). The independent review binds to that commit (03-author-reviewer).
    1. Squash-merge the release PR after green CI and review. Verify CI on the resulting commit of the target branch.
    2. Tag that exact commit with an annotated tag and push only the tag:
      git fetch origin
      git tag -a vX.Y.Z <verified-sha> -m "CoAgent8 vX.Y.Z"
      git push origin vX.Y.Z
    1. The tag push starts .github/workflows/release.yml. It checks that the tag is a numeric vX.Y.Z and annotated, that package.json carries the same version and that the tagged commit is on develop or an X.Y.x line; runs the full gate on Ubuntu with Node 24; packs and smoke-tests the exact npm tarball, packages the VSIX, writes SHA256SUMS, signs build provenance for the tarball and the VSIX (GitHub artifact attestations), generates the release notes with git-cliff and creates a draft GitHub Release (marked pre-release for a version below 1.0.0) with these assets. It never publishes to npm and never publishes the draft.
    1. Download the assets from the draft release (gh release download vX.Y.Z) and verify them: sha256sum --check --ignore-missing SHA256SUMS and gh attestation verify <file> --repo oktawianwybieralski/coagent8 for the tarball and the VSIX. Install both in clean profiles and run the stage's native acceptance (roadmap). Add known issues and security notes to the draft notes. Local gate digests can differ from CI builds (different machine, archive timestamps); SHA256SUMS and the attestation are authoritative.
    1. Publish the draft GitHub Release (keep "pre-release" for previews). Publishing starts .github/workflows/docs.yml, which validates the TSDoc comments, generates the TypeDoc site (source API plus the project documents: README, Architecture, Roadmap, Handoff, Changelog, Git workflow) and deploys it to GitHub Pages. Pages always shows the latest published release; versioned documentation per line is planned with the first X.Y.x line (REPO-002).
    2. Publish the verified tarball, not a rebuild. With npm trusted publishing enabled (section 8), publishing the release starts .github/workflows/npm-publish.yml: after the owner approves the npm environment, it downloads the release's tarball, checks it against SHA256SUMS and the provenance of release.yml, and runs npm publish --provenance to next (a version below 1.0.0) or latest (1.0.0 and later); the GitHub pre-release flag must agree with the version. A failed job is re-run; npm never accepts the same version twice. Until it is enabled, and for 0.6.0, the owner publishes the downloaded, verified tarball by hand:
      npm publish ./coagent8-0.N.0.tgz --tag next    # preview
      npm publish ./coagent8-X.Y.Z.tgz # 1.0.0 and later: latest
      Publish the verified VSIX from the release to the VS Code Marketplace under the publisher okidev, as a pre-release for a preview:
      npx @vscode/vsce publish --pre-release --packagePath ./coagent8-mcp-0.N.0.vsix   # preview
      npx @vscode/vsce publish --packagePath ./coagent8-mcp-X.Y.Z.vsix # 1.0.0 and later
    3. Announce the release to testers with the GitHub Release link.

    Any content change after Phase A's gate restarts it with a new commit; a pushed tag is never moved. A failed release workflow is fixed by a new release number when the tag was already pushed.

    • The final X.Y.0 follows the same phases on X.Y.x, with the additional readiness gate: the roadmap's RC stage accepted with no open P0/P1 issue; six CI jobs and the full local gate on a clean checkout; soak verification of the exact artifact (concurrent sessions, process cancellation, EOF teardown, lock contention, restart recovery, history pagination, bounded cache/memory); and an independent review of the complete release diff against the previous release tag, bound to base, candidate, tree and artifact hashes, with COVERAGE: COMPLETE, VERDICT: READY and no unresolved P1/P2 finding.
    • A line is supported until the owner announces its end; its branch then stays read-only (no deletion; the ruleset forbids it).

    • CHANGELOG.md at the repository root is generated from the Conventional Commits history by git-cliff (cliff.toml, npm run changelog). It follows Keep a Changelog 1.1.0 with one section per released version, newest first.
    • Nobody edits it by hand; the Reviewer rejects a manual edit. It is regenerated before every push (below) and, with --tag, in each release PR (section 5).
    • Each entry starts with its commit, linked to GitHub; the (#N) suffix of a squash subject becomes a link to the PR. On a topic branch the entries are the branch commits. After the squash merge they are replaced by the PR title (one entry per PR) at the next regeneration on the target branch.
    • Each branch generates its own file: on develop the versions tagged on develop (betas), on a line the versions tagged on that line. Before the first line exists (the first release candidate), the owner decides how develop lists the line's releases; until then every release is tagged on develop.
    • The detailed entries of 0.6.0 (prepared as 1.0.0-beta.2) come from the 293 local commits that were squash-merged as one PR (REPO-002). They are generated on that PR branch after its last change and before the merge, never written by hand, and kept as a fixed section, the oldest entry at the end of the file (cliff.toml footer, which names the command); generation after it starts at tag v0.6.0.
    • Groups: Breaking (! or BREAKING CHANGE), Added (feat), Changed (perf, refactor), Removed (revert), Fixed (fix). docs, chore, test, ci, build and style are omitted. A breaking commit is listed under Breaking only, not again under its type.
    • A subject that is not a Conventional Commit (for example GitHub's default Revert "..." title) fails the generation (require_conventional) instead of silently losing its entry.
    • GitHub release notes are generated by npm run release-notes (cliff.release-notes.toml) in the layout of the PrestaShop release pages.
      • Entries are grouped by area (commit scope; "General" without one), then by type.
      • Each entry is #PR: description (by @author).
      • Breaking changes come first and are not repeated under their area. Contributors and a "Full Changelog" compare link follow the entries.
      • Known issues, security notes and artifact digests are added by hand; they do not derive from commits.
    • Keep each PR to one user-visible change so that its entry is precise.

    The agent does this itself, without being asked.

    1. Before every git push (any branch), after the last change is committed:
      • Run npm run changelog. It fails when any commit since v0.6.0 is not a Conventional Commit. A failure blocks the push: reword the offending commit; never push past it.
      • If CHANGELOG.md changed, commit it alone as chore(changelog): regenerate. chore is omitted from the changelog, so this commit does not make the file stale. Do not amend it into an earlier commit: that changes the SHA that the file links.
      • Confirm that no entry is duplicated, misgrouped or missing, then push.
      • A file generated before the last commit is stale. A generated file cannot list the commit that contains it, which is why the file gets its own commit.
    2. Before gh pr create and before every PR title change, run npm run changelog:check -- --with-commit "<PR title>". It writes no file.
      • The title appears as a pending entry. It must sit in the right group and describe the change for users.
      • A non-zero exit means the title is not a Conventional Commit. (git-cliff 2.14.2 reports this case with a panic, exit code 101.)
      • A breaking change needs ! in the title or a BREAKING CHANGE: footer in the squash message. A ! on a branch commit alone is lost in the squash.
      • Copy the pending entry into the PR description (section 3).
    3. Merge conflict in CHANGELOG.md (for example after rebasing on develop): never resolve it by hand. Take either side, run npm run changelog and commit the result as in step 1.
    4. Report the results in the PR Verification section as PASS or FAIL.

    • Bugs are reported as GitHub issues. Testers should include the output of the issue tool (a sanitized, prefilled report) and of doctor, the OS, Node version, CoAgent8 version and backend CLI versions.
    • Triage labels:
      • type: bug, enhancement, question, docs;
      • severity for bugs: P0 (safety, data loss, tool unusable), P1 (incorrect result or contract violation), P2 (robustness or degraded behavior), P3 (cosmetic);
      • found-in:v0.6.0 (the version where the bug was observed);
      • status: needs-repro, confirmed, wontfix, duplicate.
    • P0 and P1 issues block the next stage tag. Every closed bug references the PR that fixed it (Fixes #... in the PR).
    • Never paste credentials, configuration files or private code into issues; maintainers redact any that appear.

    The owner maintains three branch and tag rulesets with no bypass actors except the tag-creation rule:

    Ruleset Targets Rules
    develop refs/heads/develop PR required; squash only; linear history; required checks below, up to date; conversation resolution; signed commits; no deletion; no force push
    release lines refs/heads/*.*.x PR required; squash only; linear history; required checks below, up to date; conversation resolution; signed commits; no deletion; no force push
    release tags refs/tags/v* No update, deletion or force push (immutable); creation restricted to maintainers
    • Required checks are the six CI jobs, exactly as ci.yml names them: Test on {ubuntu-latest, macos-latest, windows-latest} (Node {24.x, 26.x}). When the CI matrix changes, the ruleset changes in the same PR's follow-up; a required check that no job reports blocks every merge.
    • develop is the default branch. GitHub signs every squash commit it creates (the "Verified" badge), which satisfies the signed-commit rule; a locally made, unsigned commit can never reach a protected branch.
    • GitHub Pages: source "GitHub Actions"; the github-pages environment allows deployments from tags v* (a release event runs on the tag) and from develop (manual runs). Site: https://oktawianwybieralski.github.io/coagent8/.
    • npm trusted publishing (after 0.6.0, REPO-002g): on npmjs.com the package coagent8 trusts publisher repository oktawianwybieralski/coagent8, workflow npm-publish.yml, environment npm; the GitHub environment npm requires the owner's review and allows tags v*; the repository variable NPM_TRUSTED_PUBLISHING is true. The package then disallows token publishing. Without the variable the publish job is skipped.
    • No protection, required check or review gate may be disabled or bypassed outside the recovery procedure below.

    • History rewrites are strictly an emergency incident recovery mechanism, never routine cleanup.
    • An owner-authorized recovery must identify:
      • The exact affected refs and expected old object IDs.
      • The consolidated replacement tree SHA.
      • Complete local validation evidence.
      • An offline backup bundle (git bundle create coagent8-backup.bundle --all).
    • The recovery must use explicit atomic force-with-lease:
      git push --atomic --force-with-lease=refs/heads/<branch>:<old_sha> --force-with-lease=refs/tags/<tag>:<old_tag_obj> origin <new_sha>:refs/heads/<branch> refs/tags/<tag>:refs/tags/<tag>
      
    • Immediately verify that discarded commit SHAs are absent from the branch lineage (git merge-base --is-ancestor <bad_sha> origin/<branch> returns exit code 1).
    • Restore branch protections and revoke temporary bypass permissions immediately following recovery.