Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ readiness.

| Area | Current evidence | Status and limit |
| --- | --- | --- |
| G0 public foundation | Public repository `https://github.com/daichunghy/patchgate`, Apache-2.0 license, Community Profile 100%, nine repository topics, Discussions, private vulnerability reporting, protected `main`, CI workflow, and successful public `main` CI runs | Foundation is present on public `main`; `main` requires six CI contexts and one approving review, `0.1.0-dev` remains an unpublished package, and beta.5 is the current public Action pre-release. There is no downstream usage; maintainer-bypass merges remain recorded as maintainer decisions rather than independent-review evidence |
| G0 public foundation | Public repository `https://github.com/daichunghy/patchgate`, Apache-2.0 license, Community Profile 100%, nine repository topics, Discussions, private vulnerability reporting, protected `main`, CI workflow, and successful public `main` CI runs | Foundation is present on public `main`; `main` requires six CI contexts and one approving review; the maintainer-authorized scoped npm prerelease [`@daichunghy/patchgate@0.1.0-beta.5`](https://www.npmjs.com/package/%40daichunghy%2Fpatchgate) (dist-tag `beta`) is published — the unscoped `patchgate` name belongs to a different project — and beta.5 is the current public Action pre-release. There is no downstream usage; maintainer-bypass merges remain recorded as maintainer decisions rather than independent-review evidence |
| G1 deterministic contract | TypeScript evaluator, schemas, receipt digests, recorded fixtures (including the replayable Case Lab manifest), security coverage, and deterministic tests | Locally verified; this does not prove a live GitHub integration |
| G2 local preflight | `preflight`, `validate`, `init`, `doctor`, Git-ref loading, discovery classification (including Prow `OWNERS`/`OWNERS_ALIASES` as `needs_confirmation`, discovery-only, PR #75), text/JSON parity, CLI process smoke tests, the `evaluate --output` alias with fail-closed conflicts (PR #40), and the `npm run case-lab` replay path | Local user flow is verified; three consented usability sessions and UR acceptance evidence are still open |
| G3 GitHub adapter | Recorded/mock authenticated snapshot flow, bounded requests, source and SHA binding to the exact `pull_request.head.sha` with fail-closed live-target mismatch handling (PR #59), TOCTOU re-read, redaction, branch-protection and Rulesets subset contract, 25 integration tests and the latest recorded GET-only smoke for PR #9 head `5f9ccb5` | The tested head built a schema-valid live snapshot and receipt with final status `human_review_required`; missing approval/ownership/linkage evidence remains explicit; unsupported Ruleset semantics and merge-group membership remain fail-closed |
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ broader use.

## Current status

**Status (2026-08-30):** public pre-release, 1 GitHub star, 0 forks, and no
verified external users, downstream repositories, or pilots. The npm package
remains unpublished (`private: true`, `0.1.0-dev`). The current Action release is
**Status (2026-09-06):** public pre-release, 1 GitHub star, 0 forks, and no
verified external users, downstream repositories, or pilots. The npm package is
[`@daichunghy/patchgate@0.1.0-beta.5`](https://www.npmjs.com/package/%40daichunghy%2Fpatchgate)
(prerelease, dist-tag `beta`; the unscoped `patchgate` name belongs to a
different project). The current Action release is
[`v0.1.0-beta.5`](https://github.com/daichunghy/patchgate/releases/tag/v0.1.0-beta.5),
and consumers should pin the immutable commit shown on that release page for
**shadow** evaluation only. This is not production, not a `v0.1` claim, and
Expand Down
2 changes: 1 addition & 1 deletion dist/action/index.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions docs/PROJECT_CONSTITUTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,10 @@ Reviewability budget defaults to a warning. A repository may deliberately config

Before code is written or a PR is opened:

The npm name `patchgate` is already used by a different project. This CLI
is unpublished (`private: true`). After `npm ci && npm run build` in a clone:
The npm name `patchgate` is already used by a different project, so the
maintainer-authorized package is the scoped prerelease
`@daichunghy/patchgate` (dist-tag `beta`). After `npm ci && npm run build` in
a clone:

```bash
node dist/src/cli.js preflight --base origin/main
Expand Down
9 changes: 5 additions & 4 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# Getting started

PatchGate is a public pre-release. The npm package is unpublished
(`private: true`, `0.1.0-dev`). The current Action release is
PatchGate is a public pre-release. The npm package is the scoped prerelease
[`@daichunghy/patchgate@0.1.0-beta.5`](https://www.npmjs.com/package/%40daichunghy%2Fpatchgate)
(dist-tag `beta`). The current Action release is
[`v0.1.0-beta.5`](https://github.com/daichunghy/patchgate/releases/tag/v0.1.0-beta.5),
which is for shadow evaluation only — not production, not a `v0.1` claim, and
not evidence of external pilots. Pin commit
the immutable commit SHA shown on its release page.

This walkthrough uses a clone and a local build. Do not run `npx patchgate`:
that npm name is a different project. The direct GitHub install is available
for the beta release, while the CLI remains an unpublished npm package.
that npm name is a different project. The direct GitHub install and the scoped
npm prerelease are both available for the beta release.

If you only want to see the decision contract first, run the
[Case Lab](case-lab.md) with `npm ci && npm run case-lab`. It replays local
Expand Down
4 changes: 2 additions & 2 deletions docs/receipt-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ attestation, compliance certificate, or proof that code is correct.

The contract has three independent version namespaces: evaluation-input schema
`0.1`, ContributionReceipt schema `0.1`, and evaluator/package version
`0.1.0-dev`. Unversioned input and unsupported versions are rejected before the
`0.1.0-beta.5`. Unversioned input and unsupported versions are rejected before the
pure evaluator with stable diagnostic IDs and CLI exit `2`.

## Required fields

```json
{
"schemaVersion": "0.1",
"evaluatorVersion": "0.1.0-dev",
"evaluatorVersion": "0.1.0-beta.5",
"repository": { "owner": "example", "name": "service", "pullRequest": 42 },
"revisions": {
"baseSha": "base-commit",
Expand Down
9 changes: 7 additions & 2 deletions docs/reviews/2026-09-06-portfolio-backlog-merge-campaign.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,13 @@ decision for the maintainer.

- No external user, downstream repository, outside issue, outside pull
request, or consented pilot appeared in this pass.
- The portfolio still has no published stable release; the npm publication
decision remains open and pending the maintainer's registry authentication.
- The portfolio still has no published stable release. Later on the same day
the maintainer authorized npm publication of the prepared prereleases:
`contribkit@0.1.0-alpha.7`, `opensheet-ai@0.1.0-alpha.5`,
`@agentbiz/quant-research@0.1.0-alpha.6`, and the scoped
`@daichunghy/patchgate@0.1.0-beta.5` — all published to their documented
prerelease dist-tags. Prerelease publication is not a `v0.1` claim and does
not by itself constitute adoption evidence.
- Repository status snapshots outside this record (per-repository `AGENTS.md`
and status documents) were refreshed for patchgate in the same pass; the
other repositories' status documents continue to state their own limits.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "patchgate",
"version": "0.1.0-dev",
"private": true,
"name": "@daichunghy/patchgate",
"version": "0.1.0-beta.5",
"private": false,
"description": "Checks GitHub pull requests for required issue links, CI evidence, code owners, and human approval before maintainer review",
"license": "Apache-2.0",
"repository": {
Expand Down
7 changes: 4 additions & 3 deletions scripts/check-release-candidate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ const rollbackText = fs.readFileSync(path.join(root, "docs/releases/beta-release
const checklistText = fs.readFileSync(path.join(root, "docs/release-candidate-checklist.md"), "utf8");
const failures = [];

if (packageJson.private !== true) failures.push("package.json must remain private until a maintainer authorizes a public release");
if (typeof packageJson.version !== "string" || !packageJson.version.endsWith("-dev")) failures.push("the current package version must remain an explicit development version");
if (packageJson.private === true) failures.push("package.json must publish the maintainer-authorized scoped prerelease; private:true blocks installation");
if (packageJson.name !== "@daichunghy/patchgate") failures.push("the npm package name must stay scoped as @daichunghy/patchgate because the unscoped name belongs to another project");
if (typeof packageJson.version !== "string" || !/^0\.1\.0-beta\.\d+$/.test(packageJson.version)) failures.push("the current package version must be an explicit 0.1.0 beta prerelease");
if (!actionText.includes("main: 'dist/action/index.js'")) failures.push("root action.yml must point to the committed bundle");
for (const requiredText of [
"same immutable candidate",
Expand Down Expand Up @@ -51,4 +52,4 @@ if (failures.length > 0) {
process.exit(1);
}

console.log(`release candidate checks passed: ${packageJson.name}@${packageJson.version} remains an unpublished development package with a complete CLI/Action pack surface`);
console.log(`release candidate checks passed: ${packageJson.name}@${packageJson.version} is the authorized scoped prerelease with a complete CLI/Action pack surface`);
4 changes: 2 additions & 2 deletions scripts/check-release-guide.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ for (const forbidden of ["contents", "pull-requests", "actions", "administration
}
}

if (packageJson.private !== true || packageJson.version !== "0.1.0-dev") {
failures.push("release guide validator expects the package to remain private at 0.1.0-dev");
if (packageJson.private === true || packageJson.name !== "@daichunghy/patchgate" || !/^0\.1\.0-beta\.\d+$/.test(packageJson.version)) {
failures.push("release guide validator expects the authorized scoped @daichunghy/patchgate 0.1.0 beta prerelease");
}

if (failures.length > 0) {
Expand Down
4 changes: 2 additions & 2 deletions src/version.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { EvaluatorVersion } from "./types.js";

/** Kept in source so receipts never present the dev package as a release. */
export const EVALUATOR_VERSION: EvaluatorVersion = "0.1.0-dev";
/** Kept in source so receipts always identify the exact evaluator prerelease. */
export const EVALUATOR_VERSION: EvaluatorVersion = "0.1.0-beta.5";
2 changes: 1 addition & 1 deletion test/action.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ describe("GitHub Action runner unit tests", () => {
it("formats markdown summary for ready_for_review receipt", () => {
const mockReceipt: ContributionReceipt = {
schemaVersion: "0.1",
evaluatorVersion: "0.1.0-dev",
evaluatorVersion: "0.1.0-beta.5",
repository: { owner: "patchgate", name: "core", pullRequest: 42 },
revisions: {
baseSha: "0123456789abcdef0123456789abcdef01234567",
Expand Down
2 changes: 1 addition & 1 deletion test/cli-smoke.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe("CLI process smoke contract", () => {

const rootVersion = runCommand(["--version"]);
expect(rootVersion.exit).toBe(0);
expect(rootVersion.stdout).toContain("patchgate v0.1.0-dev");
expect(rootVersion.stdout).toContain("patchgate v0.1.0-beta.5");

const preflightHelp = runCommand(["preflight", "--help"]);
expect(preflightHelp.exit).toBe(0);
Expand Down
4 changes: 2 additions & 2 deletions test/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe("runtime contract schemas", () => {
const receipt = evaluate(input);
expect(() => assertContributionReceipt(receipt)).not.toThrow();
expect(receipt.evaluatedAt).toBe("2026-08-13T00:00:00Z");
expect(receipt.evaluatorVersion).toBe("0.1.0-dev");
expect(receipt.evaluatorVersion).toBe("0.1.0-beta.5");
});

it("rejects malformed and unversioned input before evaluation", () => {
Expand Down Expand Up @@ -100,7 +100,7 @@ describe("runtime contract schemas", () => {
const receipt = evaluate(input);
expect(input.schemaVersion).toBe("0.1");
expect(receipt.schemaVersion).toBe("0.1");
expect(receipt.evaluatorVersion).toBe("0.1.0-dev");
expect(receipt.evaluatorVersion).toBe("0.1.0-beta.5");
// A future evaluator bump stays valid against this schema; only the
// receipt digest defends integrity.
const bumped: typeof receipt = { ...receipt, evaluatorVersion: "0.1.0" };
Expand Down