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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ The authoritative, curated notes for each release live on the
short index of released versions and links to those notes; it is updated as part of cutting a
release ([CONTRIBUTING §14](CONTRIBUTING.md#14-releases)).

PARTHA is pre-1.0. Minor versions may change behaviour; each release's notes say what moved.
PARTHA follows [Semantic Versioning](VERSIONING.md). It is pre-1.0: minor versions may change behaviour; patch versions are bug fixes only. Each release's notes say what moved.
Unreleased work lives on `dev`.

## Released

| Version | Date | Summary | Notes |
| --- | --- | --- | --- |
| [v0.3.0](https://github.com/Second-Origin/PARTHA/releases/tag/v0.3.0) | 2026-09-26 | Reliability and truthfulness: Engineering Review no longer reports references into external code as findings (894 to 33 on the FastAPI template), cancel works on SQLite, explicit-UTC timestamps, clearer first-run errors, FastAPI decorator/router guards recognised, failed analyses no longer leave facts on disk, and removal of a pre-approved registration email (see the release notes for the security details). | [Release notes](https://github.com/Second-Origin/PARTHA/releases/tag/v0.3.0) · [`v0.2.0…v0.3.0`](https://github.com/Second-Origin/PARTHA/compare/v0.2.0...v0.3.0) |
| [v0.2.0](https://github.com/Second-Origin/PARTHA/releases/tag/v0.2.0) | 2026-09-09 | Sealed `ri.v1` snapshots as the single read model; evidence-backed extractors and deterministic resolution; Repository Lineage (RFC-0002); accounts, owner isolation, and optional OAuth; the marketing site; and a documentation accuracy pass. | [Release notes](https://github.com/Second-Origin/PARTHA/releases/tag/v0.2.0) · [`v0.1.0…v0.2.0`](https://github.com/Second-Origin/PARTHA/compare/v0.1.0...v0.2.0) |
| [v0.1.0](https://github.com/Second-Origin/PARTHA/releases/tag/v0.1.0) | 2026-07-09 | First public release: repository ingestion and analysis, the Repository Intelligence engine, architecture / dependency / documentation / review surfaces, the AI provider foundation, and the export pipeline. | [Release notes](https://github.com/Second-Origin/PARTHA/releases/tag/v0.1.0) |
41 changes: 30 additions & 11 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,21 +480,37 @@ code-owner review, passing required status checks, and no deletion or force-push

**Cutting a release.**

1. Bump the version in `package.json`, `apps/frontend/package.json`,
`apps/marketing/package.json`, `apps/backend/pyproject.toml`, and the FastAPI
`version=` in `apps/backend/app/main.py`, together with any documentation that
is genuinely out of date. Merge that to `dev` like any other change.
2. Open a `dev` → `main` pull request and merge it once checks are green.
3. Tag the release commit `vMAJOR.MINOR.PATCH` and push the tag.
4. Once the GitHub Release exists and its notes are curated (below), add a row for
the version to [`CHANGELOG.md`](CHANGELOG.md) — a one-line summary and a link to
the release notes — so the in-repo index stays current.
Which version number a release gets is decided by [VERSIONING.md](VERSIONING.md): review
everything merged since the last tag, take the highest level it reaches (patch, minor or
major), and increment by exactly one step. A release is a promotion, in this order:

1. **Prepare on `dev`.** Choose the version under the policy, then bump it in `package.json`, `apps/frontend/package.json`,
`apps/marketing/package.json`, both `package-lock.json` files, `apps/backend/pyproject.toml`,
and the FastAPI `version=` in `apps/backend/app/main.py`; point any version-bearing copy
(the marketing site's "Try PARTHA vX.Y.Z" button) at the new version; and update any
documentation that is genuinely out of date. Merge that to `dev` like any other change.
2. **Promote.** Open a `dev` → `main` pull request and merge it once every check is green.
Use a merge commit, not a squash, so `main` and `dev` keep shared history.
3. **Verify.** Check through the GitHub API, not just local git, that `main` still exists and
points at the merge commit (`gh api repos/<owner>/<repo>/branches/main`), and that the
Production deployment for that commit succeeded. Anything user-facing (the marketing
copy) is live only from this point.
4. **Sync back.** The promotion leaves `main` one merge commit ahead of `dev`. Bring it back
with a pull request into `dev` from a **throwaway branch created at `main`'s tip**
(for example `sync/main-into-dev`), never from `main` itself (see the warning below).
5. **Tag from `main`.** Tag the release commit on `main` `vMAJOR.MINOR.PATCH` and push the tag.
6. **Curate the release** (below), then add a row for the version to
[`CHANGELOG.md`](CHANGELOG.md), a one-line summary and a link to the release notes, so
the in-repo index stays current.

Pushing a `v*` tag runs [`.github/workflows/release.yml`](.github/workflows/release.yml):
a `validate` job re-runs the release-relevant frontend and backend checks against real
PostgreSQL and Redis, and only if that passes does a `github-release` job create the
GitHub Release with `gh release create --generate-notes` — an automatically generated
list of merged pull requests and new contributors.
list of merged pull requests and new contributors. **Let the workflow create the release**
rather than creating it by hand first: with the release already present, `github-release`
fails with "tag_name already exists" (the validation still runs and passes, but the run
shows red).

Those generated notes are a **baseline, not the final notes.** After the workflow runs,
a maintainer edits the release (`gh release edit <tag> --notes-file …`, or the Releases
Expand All @@ -505,7 +521,10 @@ done until that curation has happened.

`main` is only ever a pull-request **target**. Never open a pull request whose *source*
branch is `main`: merged head branches are deleted automatically, which would delete
`main` itself.
`main` itself. This is not hypothetical: merging the step-4 sync-back with `main` as its head
did exactly that for v0.3.0, and `main` had to be recreated at the promotion commit. If it
happens, `gh api -X POST repos/<owner>/<repo>/git/refs -f ref=refs/heads/main -f sha=<merge commit>`
restores it (the branch ruleset reapplies), and step 3's API check is how you notice.

PARTHA is pre-1.0. Minor versions may change behaviour; the release notes say so when
they do.
Expand Down
2 changes: 1 addition & 1 deletion GOVERNANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ RFC-0002 (Repository Lineage) are the existing examples.

## Releases

Releases are cut by maintainers: bump versions, promote `dev` → `main`, tag `vMAJOR.MINOR.PATCH`.
Releases are cut by maintainers: choose the version under [VERSIONING.md](VERSIONING.md), bump versions, promote `dev` → `main`, tag `vMAJOR.MINOR.PATCH`.
The tag triggers [`release.yml`](.github/workflows/release.yml), which re-validates against
PostgreSQL and Redis before publishing a GitHub Release; a maintainer then curates the
generated notes. Full steps are in [CONTRIBUTING §14](CONTRIBUTING.md#14-releases). PARTHA
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Each surface reads the sealed snapshot for the analysed revision:
- **Repository Intelligence** — builds an immutable, revision-addressed structural snapshot from supported repository sources, with evidence and provenance on supported facts.
- **Architecture** — an interactive graph of modules and resolved relationships, plus an evidence-cited authentication explanation for supported Python/FastAPI patterns.
- **Dependency Graph** — direct declarations from `package.json`, `pyproject.toml`, and `requirements.txt`, with resolved pins from two lockfile formats recorded as resolutions, never as direct edges.
- **Engineering Review** — findings that are each backed by a stored evidence span; unassessed categories stay visible. No score, grade, or health percentage.
- **Engineering Review** — findings that are each backed by a stored evidence span; unassessed categories stay visible. References into third-party or platform code, local names and non-code assets are not reported as findings. No score, grade, or health percentage.
- **Repository Insights** — defined counts, ratios, diagnostics, and coverage from one snapshot. No change-over-time claims.
- **Repository Lineage** — repeated imports of the same repository and branch grouped into a durable history, browsable through the API and UI. This is revision *history*, not cross-revision comparison.
- **Documentation & export** — structural documentation, and Review / Documentation / Architecture / Dependencies exported through one JSON / Markdown / HTML / PDF pipeline.
Expand Down Expand Up @@ -129,7 +129,7 @@ The [development guide](docs/DEVELOPMENT.md) covers the full test / lint / build
- **Optional AI can be external.** Depending on configuration, AI calls a configured provider; only local providers keep everything on the host. See the [egress policy](docs/security/AI_PROVIDER_EGRESS.md).
- **In-process worker.** One daemon worker thread inside the API process handles one analysis job at a time; there is no separate worker service or job queue.

Non-auth product routes require authentication, repository access is owner-scoped, provider keys are Fernet-encrypted at rest, and AI egress is validated against a deployment-owned allowlist with DNS pinning — meaningful controls, but not a claim of production hardening. See [SECURITY.md](SECURITY.md) and [`docs/CAPABILITIES.md`](docs/CAPABILITIES.md) for the details.
Non-auth product routes require authentication, repository access is owner-scoped, provider keys are Fernet-encrypted at rest, and AI egress is validated against a deployment-owned allowlist with DNS pinning — meaningful controls, but not a claim of production hardening. Registration does not verify email ownership, and in the default `development` environment any address may register. See [SECURITY.md](SECURITY.md) and [`docs/CAPABILITIES.md`](docs/CAPABILITIES.md) for the details.

## Documentation

Expand All @@ -152,7 +152,7 @@ Issues and pull requests are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.

## Releases

`main` carries the latest tagged release; `dev` is where active development happens and is the target of every pull request. PARTHA is pre-1.0, so minor versions may change behaviour — each release's notes say what moved. See [all releases](https://github.com/Second-Origin/PARTHA/releases), the [changelog](CHANGELOG.md), and [CONTRIBUTING § Releases](CONTRIBUTING.md#14-releases).
`main` carries the latest tagged release; `dev` is where active development happens and is the target of every pull request. A release is a promotion: prepare on `dev`, promote `dev` to `main`, verify, sync back, then tag from `main`. PARTHA follows [Semantic Versioning](VERSIONING.md) and is pre-1.0, so minor versions may change behaviour — each release's notes say what moved. See [all releases](https://github.com/Second-Origin/PARTHA/releases), the [changelog](CHANGELOG.md), and [CONTRIBUTING § Releases](CONTRIBUTING.md#14-releases).

## License

Expand Down
2 changes: 1 addition & 1 deletion SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ PARTHA is **pre-1.0 and under active development.**

- Fixes land on `dev` and are included in the next tagged release. Security fixes are
provided for `dev` and the latest release (see [SECURITY.md](SECURITY.md#supported-versions)).
- **Minor version bumps may change behaviour.** Each release's notes state what moved; read
- **Minor version bumps may change behaviour** (PARTHA is pre-1.0; see the [versioning policy](VERSIONING.md)); patch releases are bug fixes only. Each release's notes state what moved; read
them before upgrading. There is no back-porting to older releases and no long-term-support
branch.
- When reporting an issue, say which release tag or commit SHA you are on — behaviour on an
Expand Down
121 changes: 121 additions & 0 deletions VERSIONING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Versioning policy

PARTHA follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). This document
says what that means here: what counts as PARTHA's public API, what qualifies for a patch,
minor or major release, how the pre-1.0 period works, and the rules that keep the version
sequence honest. The mechanics of cutting a release (promote, verify, sync back, tag) are in
[CONTRIBUTING §14](CONTRIBUTING.md#14-releases); this file decides only **which number**.

Versions are written `MAJOR.MINOR.PATCH`, tagged `vMAJOR.MINOR.PATCH`, and are plain integers:
`0.9.0` is followed by `0.10.0`, not `1.0.0`.

## What is the public API

Semantic Versioning is only meaningful relative to a declared public API. PARTHA's is:

| Surface | What is covered |
| --- | --- |
| HTTP API | Routes, request and response shapes, status codes and error `code`s in the generated OpenAPI contract (`apps/frontend/src/shared/services/api/generated.ts` is checked against it in CI). |
| Configuration | Environment variables and their defaults and accepted values (`apps/backend/.env.example`, `docs/operations/`). |
| Operator tooling | The command-line interfaces of `apps/backend/scripts/` (`approve_email.py`, `cleanup_storage.py`, ...): names, flags, exit codes. |
| Upgrade path | That `alembic upgrade head` takes a database from any released version to the new one without manual steps, and what data a migration touches. |
| Exports | The structure of the JSON export and the report schema identifiers (`engineering-review.v2`, `repository-insights.v1`). |
| Snapshot schema | `ri.v1` has its own explicit schema version (RFC-0001). A change to it is governed by the RFC, and any incompatible change is at least a **minor** release before 1.0 and a **major** release after. |

**Not** public API, and free to change in any release: internal Python modules and function
signatures, database table layout beyond the upgrade guarantee above, frontend component
structure and styling, the wording of UI copy and log lines, CI, and the benchmark corpus.

## What qualifies for each bump

Decide by reviewing everything merged since the last tag and taking the **highest** level any
change reaches. A release that is mostly fixes but adds one new capability is a minor release.

### Patch: `0.3.0` -> `0.3.1`

Backward-compatible **bug fixes only**. Nothing a user or operator could describe as "new".

- Fixes that make the software do what its documentation already says.
- Security fixes that do not change the public API.
- Dependency updates that change no behaviour.
- Documentation and internal-only changes (refactors, tests, CI).
- A migration only when the fix requires it and it is data-only or corrective (for example,
deleting a row a bad migration inserted). No new tables or columns.

A patch must **not**: add an endpoint, field, setting, flag, script or UI surface; change a
default; change what an existing response contains beyond correcting a wrong value; or need
any operator action beyond upgrading.

### Minor: `0.3.0` -> `0.4.0`

**New backward-compatible functionality**, or a change to existing behaviour that is visible
to users or operators.

- A new capability: for example Repository Lineage's read API and history page, a new export
format, a new provider.
- New endpoints, response fields, settings, or script options.
- Additive migrations (new tables, columns, indexes).
- Deprecating something (it keeps working; the notes say what replaces it).
- Behaviour changes that are corrections in spirit but observable, such as a different set of
Engineering Review findings or a changed timestamp format. Say so in the notes.

### Major: `1.x` -> `2.0.0`

**Incompatible changes** to the public API, after 1.0.

- Removing or renaming an endpoint, field, setting or script flag; changing what one means.
- A migration that needs manual steps, cannot run on the previous release's data, or discards
data.
- Dropping a supported Python or Node version.
- An incompatible `ri.v1` change (a new schema version is introduced alongside; the old one is
removed only in a major release).

## Before 1.0

SemVer item 4 says anything may change at any time while the major version is `0`. PARTHA
narrows that so that upgraders can still rely on the number:

- The middle number does the work of "major": **a breaking change bumps the minor version**
(`0.3.0` -> `0.4.0`), and the release notes list it under a **Breaking** heading with what to
do about it.
- The last number stays strictly **bug fixes** (the patch rules above apply unchanged), so
`0.4.1` is always safe to take from `0.4.0`.
- Nothing before 1.0 is guaranteed stable across minor versions, which is why
[SUPPORT.md](SUPPORT.md) says to read each release's notes before upgrading.

**1.0.0** is a promise, not a milestone: it declares the public API above stable and starts
enforcing the major rule. It will be cut when the maintainers judge that the HTTP API,
configuration and upgrade path are ones they are prepared to keep compatible, and it will say so.
There is no date or feature list attached to it.

## Rules that keep the sequence honest

1. **Increment by one, never skip.** Each release differs from the previous tag by exactly one
step: the next patch (`0.3.1`), the next minor with patch reset (`0.4.0`), or the next major.
The sequence `0.1.0, 0.1.1, 0.2.0, ..., 0.9.0, 0.10.0, ..., 1.0.0` is the expected shape.
2. **A published version is immutable.** Never delete, move or re-point a tag or replace a
release's contents. A mistake is corrected by publishing the next version and saying so in its
notes; a bad release may be marked in its own notes as superseded.
3. **One version everywhere.** The release commit sets the same number in `package.json`,
`apps/frontend/package.json`, `apps/marketing/package.json` (and both `package-lock.json`
files), `apps/backend/pyproject.toml` and the FastAPI `version=` in `apps/backend/app/main.py`,
and version-bearing copy such as the marketing "Try PARTHA vX.Y.Z" button. Pull requests
never change a version string.
4. **The notes justify the number.** Release notes group changes by area and state under a
heading which of Security, Breaking, New or Fixes each belongs to, so a reader can check the
bump against this policy.
5. **Pre-releases** use a SemVer pre-release suffix (`0.4.0-rc.1`), are marked pre-release on
GitHub, and are never the target of the "latest" label.
6. **Ties go up.** If a change is arguably a patch and arguably a minor, it is a minor.

## Version history

| Version | Date | Kind | Note |
| --- | --- | --- | --- |
| `0.1.0` | 2026-07-09 | first release | The JavaScript packages still read `1.0.0` in this tag (an inconsistency, corrected in 0.2.0). |
| `0.2.0` | 2026-09-09 | minor | Sealed `ri.v1` snapshots, Repository Lineage, accounts. Versions aligned across all packages. |
| `0.3.0` | 2026-09-26 | minor | Reliability and truthfulness release (see the release notes). Published before this policy existed. It is not being re-cut. |

No release was skipped between these. There has not yet been a patch release; every release so far
has been cut when a batch of work was ready rather than by these rules, which is what this file
now settles.
Loading
Loading