repopact 2.0.1__tar.gz → 2.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {repopact-2.0.1 → repopact-2.0.2}/PKG-INFO +14 -6
  2. {repopact-2.0.1 → repopact-2.0.2}/README.md +152 -144
  3. repopact-2.0.2/VERSION +1 -0
  4. {repopact-2.0.1 → repopact-2.0.2}/pyproject.toml +7 -6
  5. repopact-2.0.2/schemas/conformance-manifest.schema.json +34 -0
  6. {repopact-2.0.1 → repopact-2.0.2}/scripts/init_repo.py +11 -7
  7. {repopact-2.0.1 → repopact-2.0.2}/scripts/repopact.egg-info/PKG-INFO +14 -6
  8. {repopact-2.0.1 → repopact-2.0.2}/scripts/repopact.egg-info/SOURCES.txt +2 -0
  9. {repopact-2.0.1 → repopact-2.0.2}/scripts/repopact.egg-info/top_level.txt +1 -0
  10. repopact-2.0.2/scripts/run_conformance.py +112 -0
  11. {repopact-2.0.1 → repopact-2.0.2}/tests/test_conformance.py +27 -6
  12. repopact-2.0.1/VERSION +0 -1
  13. {repopact-2.0.1 → repopact-2.0.2}/LICENSE +0 -0
  14. {repopact-2.0.1 → repopact-2.0.2}/schemas/audit-finding.schema.json +0 -0
  15. {repopact-2.0.1 → repopact-2.0.2}/schemas/evidence-run.schema.json +0 -0
  16. {repopact-2.0.1 → repopact-2.0.2}/schemas/frozen-surface.schema.json +0 -0
  17. {repopact-2.0.1 → repopact-2.0.2}/schemas/invariants.schema.json +0 -0
  18. {repopact-2.0.1 → repopact-2.0.2}/schemas/record-frontmatter.schema.json +0 -0
  19. {repopact-2.0.1 → repopact-2.0.2}/schemas/work-item.schema.json +0 -0
  20. {repopact-2.0.1 → repopact-2.0.2}/scripts/adopt_repo.py +0 -0
  21. {repopact-2.0.1 → repopact-2.0.2}/scripts/check_frozen_surface.py +0 -0
  22. {repopact-2.0.1 → repopact-2.0.2}/scripts/doctor.py +0 -0
  23. {repopact-2.0.1 → repopact-2.0.2}/scripts/frontmatter.py +0 -0
  24. {repopact-2.0.1 → repopact-2.0.2}/scripts/generate_dashboard.py +0 -0
  25. {repopact-2.0.1 → repopact-2.0.2}/scripts/generate_spec.py +0 -0
  26. {repopact-2.0.1 → repopact-2.0.2}/scripts/new.py +0 -0
  27. {repopact-2.0.1 → repopact-2.0.2}/scripts/plan_import.py +0 -0
  28. {repopact-2.0.1 → repopact-2.0.2}/scripts/repo_model.py +0 -0
  29. {repopact-2.0.1 → repopact-2.0.2}/scripts/repopact.egg-info/dependency_links.txt +0 -0
  30. {repopact-2.0.1 → repopact-2.0.2}/scripts/repopact.egg-info/entry_points.txt +0 -0
  31. {repopact-2.0.1 → repopact-2.0.2}/scripts/repopact.egg-info/requires.txt +0 -0
  32. {repopact-2.0.1 → repopact-2.0.2}/scripts/repopact_cli.py +0 -0
  33. {repopact-2.0.1 → repopact-2.0.2}/scripts/takeover.py +0 -0
  34. {repopact-2.0.1 → repopact-2.0.2}/scripts/track_import.py +0 -0
  35. {repopact-2.0.1 → repopact-2.0.2}/scripts/validate_repo.py +0 -0
  36. {repopact-2.0.1 → repopact-2.0.2}/setup.cfg +0 -0
  37. {repopact-2.0.1 → repopact-2.0.2}/templates/README.md +0 -0
  38. {repopact-2.0.1 → repopact-2.0.2}/templates/decision.md +0 -0
  39. {repopact-2.0.1 → repopact-2.0.2}/templates/evidence-run.json +0 -0
  40. {repopact-2.0.1 → repopact-2.0.2}/templates/policy.md +0 -0
  41. {repopact-2.0.1 → repopact-2.0.2}/templates/work-item.README.md +0 -0
  42. {repopact-2.0.1 → repopact-2.0.2}/templates/work-item.json +0 -0
  43. {repopact-2.0.1 → repopact-2.0.2}/tests/test_plan_import_links.py +0 -0
  44. {repopact-2.0.1 → repopact-2.0.2}/tests/test_takeover_refs.py +0 -0
  45. {repopact-2.0.1 → repopact-2.0.2}/tests/test_validate_repo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: repopact
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: A repository-native standard for durable agent work: binding invariants, evidence-gated work items, and drift audits.
5
5
  License: Apache-2.0
6
6
  Project-URL: Homepage, https://github.com/ForgeWireLabs/repopact
@@ -22,15 +22,15 @@ cannot be silently weakened.
22
22
  > The repository is the pact: authority, intent, evidence, and history that survive every
23
23
  > session.
24
24
 
25
- `pip install repopact` · Apache-2.0 · current release **2.0.1**
26
- ([changelog](decisions/0021-preflight-mandatory-and-provenance.md)).
25
+ `pip install repopact` · Apache-2.0 · current release **2.0.2**
26
+ ([changelog](decisions/0022-release-2.0.2-installed-seed-lookup.md)).
27
27
 
28
28
  ## How it relates to `AGENTS.md`
29
29
 
30
30
  `AGENTS.md` (and `CLAUDE.md`, editor rules) tell an agent *what to do* — they're
31
31
  instructions, plain Markdown, with no enforcement. RepoPact is the layer **above** them:
32
32
 
33
- > `AGENTS.md` tells the agent what to do. RepoPact proves it didn't quietly undo it.
33
+ > `AGENTS.md` tells an agent how to behave. RepoPact enforces and records whether the work respected the contract.
34
34
 
35
35
  RepoPact's distinguishing primitive is the **binding invariant** — a declared guarantee with
36
36
  a rationale, an escalation path, and (where its logical type permits) a machine enforcer.
@@ -83,6 +83,14 @@ repopact dashboard
83
83
  [`AGENTS.md`](AGENTS.md), then [`governance/charter.md`](governance/charter.md) and
84
84
  [`governance/workflow.md`](governance/workflow.md).
85
85
 
86
+ Alternative implementations can run the published conformance suite:
87
+
88
+ ```powershell
89
+ python scripts/run_conformance.py --command "your-validator --root {repo}"
90
+ ```
91
+
92
+ See [`CONFORMANCE.md`](CONFORMANCE.md) and [`conformance/`](conformance/).
93
+
86
94
  ## Adopt an *existing* repository
87
95
 
88
96
  For a project that already has CODEOWNERS, CI workflows, and nested `AGENTS.md` contracts,
@@ -102,7 +110,7 @@ idempotent.
102
110
 
103
111
  ## 2.0: mandatory preflight + provenance-typed records
104
112
 
105
- Decision [`0021`](decisions/0021-preflight-mandatory-and-provenance.md) (supersedes 0018):
113
+ Decision [`0021`](decisions/0022-release-2.0.2-installed-seed-lookup.md) (supersedes 0018):
106
114
 
107
115
  - **Mandatory preflight (default on).** No work begins until a work item exists and
108
116
  propagates through the pact; `repopact new` stamps the marker. Existing repos grandfather
@@ -132,7 +140,7 @@ holds a [formal model](research/formal-model.md) (the L0–L5 kernel, the typed
132
140
  lattice, the adoption trilemma), the pre-registered [experiment protocol](research/protocol.md)
133
141
  and [benchmark protocol](research/benchmark-protocol.md) (hypotheses H1–H13, falsification
134
142
  criteria, [threats to validity](research/threats-to-validity.md)), a [findings
135
- register](research/findings.md), and a full [paper draft](research/paper.md).
143
+ register](research/findings.md), and the current [paper](research/paper.md).
136
144
 
137
145
  **PactBench** — the runnable benchmark suite (pre-registered tasks measuring whether RepoPact
138
146
  enforcement reduces silent guarantee drift, with a model-agnostic harness and an S5 drift
@@ -1,144 +1,152 @@
1
- # RepoPact
2
-
3
- RepoPact is a **repository-native governance kernel for durable agent work**. It keeps the
4
- load-bearing state of a project — intent, authority, evidence, decisions, and drift — as
5
- typed, version-controlled records in the filesystem, so a new contributor or agent can
6
- recover where things stand *without* a prior conversation, and so the guarantees that matter
7
- cannot be silently weakened.
8
-
9
- > The repository is the pact: authority, intent, evidence, and history that survive every
10
- > session.
11
-
12
- `pip install repopact` · Apache-2.0 · current release **2.0.1**
13
- ([changelog](decisions/0021-preflight-mandatory-and-provenance.md)).
14
-
15
- ## How it relates to `AGENTS.md`
16
-
17
- `AGENTS.md` (and `CLAUDE.md`, editor rules) tell an agent *what to do* — they're
18
- instructions, plain Markdown, with no enforcement. RepoPact is the layer **above** them:
19
-
20
- > `AGENTS.md` tells the agent what to do. RepoPact proves it didn't quietly undo it.
21
-
22
- RepoPact's distinguishing primitive is the **binding invariant** — a declared guarantee with
23
- a rationale, an escalation path, and (where its logical type permits) a machine enforcer.
24
- That, plus evidence-gated completion and a filesystem state machine, is what turns a folder
25
- convention into a contract. `repopact adopt` ingests an existing `AGENTS.md` rather than
26
- replacing it (decision [`0020`](decisions/0020-launch-positioning-layer-above-agents-md.md)).
27
-
28
- ## Core loop
29
-
30
- ```text
31
- intent -> scoped authority -> work item -> implementation -> evidence -> audit -> history
32
- ```
33
-
34
- ![RepoPact core loop over a filesystem state machine](docs/assets/repopact-flow.svg)
35
-
36
- ## Primitives
37
-
38
- 1. **Charter & invariants** — principles (judgment) and binding invariants
39
- (escalation-gated) in `governance/`.
40
- 2. **Frozen surface** — paths and symbols that require operator approval (`--ack`) to change.
41
- 3. **Scopes & roles** — layered `AGENTS.md` contracts plus a role/scope map in
42
- `governance/owners.json`.
43
- 4. **Work items** — narrative `README.md` + machine-readable `work-item.json` with
44
- evidence-linked acceptance criteria. **Mandatory preflight** (2.0): a work item must be
45
- recorded *before* implementation begins (`repopact new` stamps the marker).
46
- 5. **Evidence** — immutable run manifests under `evidence/runs/`.
47
- 6. **Decisions & policies** — durable choices (`decisions/`) and operating rules
48
- (`governance/policies/`) whose rationale outlives any single work item.
49
- 7. **Provenance** (2.0) — every record is `concrete`, `provisional`, or `inferred`.
50
- `adopt` emits provisional/inferred records (honest, not fabricated); `doctor` ratchets
51
- them to `concrete` as real evidence arrives. See *2.0 changes* below.
52
- 8. **Reconciliation** — audits and a *generated* dashboard surface drift and review
53
- staleness rather than hand-maintaining it.
54
-
55
- ## Install & quick start
56
-
57
- ```powershell
58
- pip install repopact # the CLI + reference validator, from PyPI
59
- repopact init --target ../your-repo # seed a valid RepoPact in a new repo
60
- cd ../your-repo
61
- repopact new work-item "Title of the work" # stamps records (incl. the preflight marker)
62
- repopact validate
63
- repopact dashboard
64
- ```
65
-
66
- `repopact` dispatches `init`, `adopt`, `validate`, `new`, `dashboard`, `spec`,
67
- `check-frozen`, `import-plan`, and `doctor`. Records are validated against `schemas/*.json`
68
- (structure) and by the validator (cross-record semantics; decision
69
- [`0003`](decisions/0003-validate-records-against-json-schemas.md)). Begin with
70
- [`AGENTS.md`](AGENTS.md), then [`governance/charter.md`](governance/charter.md) and
71
- [`governance/workflow.md`](governance/workflow.md).
72
-
73
- ## Adopt an *existing* repository
74
-
75
- For a project that already has CODEOWNERS, CI workflows, and nested `AGENTS.md` contracts,
76
- `adopt` maps those existing signals into RepoPact records without overwriting anything:
77
-
78
- ```powershell
79
- repopact adopt --target ../existing-repo --dry-run # preview the plan, write nothing
80
- repopact adopt --target ../existing-repo # create records, then validate
81
- repopact doctor # diagnose + repair drift; migrate on upgrade
82
- ```
83
-
84
- CODEOWNERS becomes scopes and roles; each `.github/workflows/*` becomes a binding-gate policy
85
- (plus invariant `INV-2` and a frozen-surface entry); every nested `AGENTS.md` is registered as
86
- a contract; git history seeds a first **inferred** evidence run, and the adoption record is
87
- recorded as **provisional** honestly typed, not a fabricated "completed" claim. Adoption is
88
- idempotent.
89
-
90
- ## 2.0: mandatory preflight + provenance-typed records
91
-
92
- Decision [`0021`](decisions/0021-preflight-mandatory-and-provenance.md) (supersedes 0018):
93
-
94
- - **Mandatory preflight (default on).** No work begins until a work item exists and
95
- propagates through the pact; `repopact new` stamps the marker. Existing repos grandfather
96
- their pre-2.0 items automatically — `adopt`/`init` set a preflight epoch and `doctor`
97
- migrates on upgrade. *This is a breaking change*: run `repopact doctor` after upgrading.
98
- - **Provenance typing** (`concrete` / `provisional` / `inferred`, default `concrete`). This
99
- is the principled escape from the *adoption trilemma*: `adopt` emits provisional/inferred
100
- records so the result is both **valid** and **faithful** (reconstruction is labelled, not
101
- faked). Completion still requires `concrete` evidence; `doctor` ratchets when it arrives.
102
-
103
- ## Status is a filesystem transition
104
-
105
- Work moves between `work/active`, `work/blocked`, `work/deferred`, and `work/completed`; its
106
- `work-item.json` status must match its directory. Moving a work item never deletes its
107
- reasoning, decisions, or evidence links.
108
-
109
- ## Derive over declare
110
-
111
- Anything computable from source records is generated, not authored by hand (the dashboard,
112
- audit-freshness views, and the derived blocks of `SPEC.md`). Only genuine sources are
113
- hand-maintained. See policy `001`.
114
-
115
- ## Evaluation, formal model & the Proving Ground
116
-
117
- RepoPact is developed against its own evidence, not assertion. The `research/` lab notebook
118
- holds a [formal model](research/formal-model.md) (the L0–L5 kernel, the typed invariant
119
- lattice, the adoption trilemma), the pre-registered [experiment protocol](research/protocol.md)
120
- and [benchmark protocol](research/benchmark-protocol.md) (hypotheses H1–H13, falsification
121
- criteria, [threats to validity](research/threats-to-validity.md)), a [findings
122
- register](research/findings.md), and a full [paper draft](research/paper.md).
123
-
124
- **PactBench** — the runnable benchmark suite (pre-registered tasks measuring whether RepoPact
125
- enforcement reduces silent guarantee drift, with a model-agnostic harness and an S5 drift
126
- harness) lives in the **[RepoPact Proving
127
- Ground](https://github.com/ForgeWireLabs/repopact-proving-ground)**, a throwaway-but-real
128
- project that consumes RepoPact from PyPI and is driven across every primitive, including cases
129
- designed to break it. RepoPact defines the *protocol* (`research/`); the Proving Ground hosts
130
- the runnable suite. *RepoPact defines the pact; the Proving Ground tests whether the pact
131
- holds under agent pressure.*
132
-
133
- ## Ecosystem
134
-
135
- RepoPact is the work-governance layer of [ForgeWire Labs](https://github.com/ForgeWireLabs)
136
- inspectable agentic infrastructure (*inspect the work, bound the authority, preserve the
137
- evidence*). It composes with Fabric (execution governance) and ForgeLink (human-agent
138
- communication governance), but is independently useful on its own.
139
-
140
- ## License & version
141
-
142
- Apache-2.0 ([`LICENSE`](LICENSE), decision [`0002`](decisions/0002-license-apache-2.0.md)).
143
- The spec version is in [`VERSION`](VERSION); templates for every record type live in
144
- [`templates/`](templates/).
1
+ # RepoPact
2
+
3
+ RepoPact is a **repository-native governance kernel for durable agent work**. It keeps the
4
+ load-bearing state of a project — intent, authority, evidence, decisions, and drift — as
5
+ typed, version-controlled records in the filesystem, so a new contributor or agent can
6
+ recover where things stand *without* a prior conversation, and so the guarantees that matter
7
+ cannot be silently weakened.
8
+
9
+ > The repository is the pact: authority, intent, evidence, and history that survive every
10
+ > session.
11
+
12
+ `pip install repopact` · Apache-2.0 · current release **2.0.2**
13
+ ([changelog](decisions/0022-release-2.0.2-installed-seed-lookup.md)).
14
+
15
+ ## How it relates to `AGENTS.md`
16
+
17
+ `AGENTS.md` (and `CLAUDE.md`, editor rules) tell an agent *what to do* — they're
18
+ instructions, plain Markdown, with no enforcement. RepoPact is the layer **above** them:
19
+
20
+ > `AGENTS.md` tells an agent how to behave. RepoPact enforces and records whether the work respected the contract.
21
+
22
+ RepoPact's distinguishing primitive is the **binding invariant** — a declared guarantee with
23
+ a rationale, an escalation path, and (where its logical type permits) a machine enforcer.
24
+ That, plus evidence-gated completion and a filesystem state machine, is what turns a folder
25
+ convention into a contract. `repopact adopt` ingests an existing `AGENTS.md` rather than
26
+ replacing it (decision [`0020`](decisions/0020-launch-positioning-layer-above-agents-md.md)).
27
+
28
+ ## Core loop
29
+
30
+ ```text
31
+ intent -> scoped authority -> work item -> implementation -> evidence -> audit -> history
32
+ ```
33
+
34
+ ![RepoPact core loop over a filesystem state machine](docs/assets/repopact-flow.svg)
35
+
36
+ ## Primitives
37
+
38
+ 1. **Charter & invariants** — principles (judgment) and binding invariants
39
+ (escalation-gated) in `governance/`.
40
+ 2. **Frozen surface** — paths and symbols that require operator approval (`--ack`) to change.
41
+ 3. **Scopes & roles** — layered `AGENTS.md` contracts plus a role/scope map in
42
+ `governance/owners.json`.
43
+ 4. **Work items** — narrative `README.md` + machine-readable `work-item.json` with
44
+ evidence-linked acceptance criteria. **Mandatory preflight** (2.0): a work item must be
45
+ recorded *before* implementation begins (`repopact new` stamps the marker).
46
+ 5. **Evidence** — immutable run manifests under `evidence/runs/`.
47
+ 6. **Decisions & policies** — durable choices (`decisions/`) and operating rules
48
+ (`governance/policies/`) whose rationale outlives any single work item.
49
+ 7. **Provenance** (2.0) — every record is `concrete`, `provisional`, or `inferred`.
50
+ `adopt` emits provisional/inferred records (honest, not fabricated); `doctor` ratchets
51
+ them to `concrete` as real evidence arrives. See *2.0 changes* below.
52
+ 8. **Reconciliation** — audits and a *generated* dashboard surface drift and review
53
+ staleness rather than hand-maintaining it.
54
+
55
+ ## Install & quick start
56
+
57
+ ```powershell
58
+ pip install repopact # the CLI + reference validator, from PyPI
59
+ repopact init --target ../your-repo # seed a valid RepoPact in a new repo
60
+ cd ../your-repo
61
+ repopact new work-item "Title of the work" # stamps records (incl. the preflight marker)
62
+ repopact validate
63
+ repopact dashboard
64
+ ```
65
+
66
+ `repopact` dispatches `init`, `adopt`, `validate`, `new`, `dashboard`, `spec`,
67
+ `check-frozen`, `import-plan`, and `doctor`. Records are validated against `schemas/*.json`
68
+ (structure) and by the validator (cross-record semantics; decision
69
+ [`0003`](decisions/0003-validate-records-against-json-schemas.md)). Begin with
70
+ [`AGENTS.md`](AGENTS.md), then [`governance/charter.md`](governance/charter.md) and
71
+ [`governance/workflow.md`](governance/workflow.md).
72
+
73
+ Alternative implementations can run the published conformance suite:
74
+
75
+ ```powershell
76
+ python scripts/run_conformance.py --command "your-validator --root {repo}"
77
+ ```
78
+
79
+ See [`CONFORMANCE.md`](CONFORMANCE.md) and [`conformance/`](conformance/).
80
+
81
+ ## Adopt an *existing* repository
82
+
83
+ For a project that already has CODEOWNERS, CI workflows, and nested `AGENTS.md` contracts,
84
+ `adopt` maps those existing signals into RepoPact records without overwriting anything:
85
+
86
+ ```powershell
87
+ repopact adopt --target ../existing-repo --dry-run # preview the plan, write nothing
88
+ repopact adopt --target ../existing-repo # create records, then validate
89
+ repopact doctor # diagnose + repair drift; migrate on upgrade
90
+ ```
91
+
92
+ CODEOWNERS becomes scopes and roles; each `.github/workflows/*` becomes a binding-gate policy
93
+ (plus invariant `INV-2` and a frozen-surface entry); every nested `AGENTS.md` is registered as
94
+ a contract; git history seeds a first **inferred** evidence run, and the adoption record is
95
+ recorded as **provisional** honestly typed, not a fabricated "completed" claim. Adoption is
96
+ idempotent.
97
+
98
+ ## 2.0: mandatory preflight + provenance-typed records
99
+
100
+ Decision [`0021`](decisions/0022-release-2.0.2-installed-seed-lookup.md) (supersedes 0018):
101
+
102
+ - **Mandatory preflight (default on).** No work begins until a work item exists and
103
+ propagates through the pact; `repopact new` stamps the marker. Existing repos grandfather
104
+ their pre-2.0 items automatically — `adopt`/`init` set a preflight epoch and `doctor`
105
+ migrates on upgrade. *This is a breaking change*: run `repopact doctor` after upgrading.
106
+ - **Provenance typing** (`concrete` / `provisional` / `inferred`, default `concrete`). This
107
+ is the principled escape from the *adoption trilemma*: `adopt` emits provisional/inferred
108
+ records so the result is both **valid** and **faithful** (reconstruction is labelled, not
109
+ faked). Completion still requires `concrete` evidence; `doctor` ratchets when it arrives.
110
+
111
+ ## Status is a filesystem transition
112
+
113
+ Work moves between `work/active`, `work/blocked`, `work/deferred`, and `work/completed`; its
114
+ `work-item.json` status must match its directory. Moving a work item never deletes its
115
+ reasoning, decisions, or evidence links.
116
+
117
+ ## Derive over declare
118
+
119
+ Anything computable from source records is generated, not authored by hand (the dashboard,
120
+ audit-freshness views, and the derived blocks of `SPEC.md`). Only genuine sources are
121
+ hand-maintained. See policy `001`.
122
+
123
+ ## Evaluation, formal model & the Proving Ground
124
+
125
+ RepoPact is developed against its own evidence, not assertion. The `research/` lab notebook
126
+ holds a [formal model](research/formal-model.md) (the L0–L5 kernel, the typed invariant
127
+ lattice, the adoption trilemma), the pre-registered [experiment protocol](research/protocol.md)
128
+ and [benchmark protocol](research/benchmark-protocol.md) (hypotheses H1–H13, falsification
129
+ criteria, [threats to validity](research/threats-to-validity.md)), a [findings
130
+ register](research/findings.md), and the current [paper](research/paper.md).
131
+
132
+ **PactBench** — the runnable benchmark suite (pre-registered tasks measuring whether RepoPact
133
+ enforcement reduces silent guarantee drift, with a model-agnostic harness and an S5 drift
134
+ harness) — lives in the **[RepoPact Proving
135
+ Ground](https://github.com/ForgeWireLabs/repopact-proving-ground)**, a throwaway-but-real
136
+ project that consumes RepoPact from PyPI and is driven across every primitive, including cases
137
+ designed to break it. RepoPact defines the *protocol* (`research/`); the Proving Ground hosts
138
+ the runnable suite. *RepoPact defines the pact; the Proving Ground tests whether the pact
139
+ holds under agent pressure.*
140
+
141
+ ## Ecosystem
142
+
143
+ RepoPact is the work-governance layer of [ForgeWire Labs](https://github.com/ForgeWireLabs)
144
+ inspectable agentic infrastructure (*inspect the work, bound the authority, preserve the
145
+ evidence*). It composes with Fabric (execution governance) and ForgeLink (human-agent
146
+ communication governance), but is independently useful on its own.
147
+
148
+ ## License & version
149
+
150
+ Apache-2.0 ([`LICENSE`](LICENSE), decision [`0002`](decisions/0002-license-apache-2.0.md)).
151
+ The spec version is in [`VERSION`](VERSION); templates for every record type live in
152
+ [`templates/`](templates/).
repopact-2.0.2/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.0.2
@@ -31,10 +31,11 @@ py-modules = [
31
31
  "track_import",
32
32
  "takeover",
33
33
  "doctor",
34
- "new",
35
- "check_frozen_surface",
36
- "frontmatter",
37
- ]
34
+ "new",
35
+ "check_frozen_surface",
36
+ "frontmatter",
37
+ "run_conformance",
38
+ ]
38
39
 
39
40
  [tool.setuptools.package-dir]
40
41
  "" = "scripts"
@@ -45,5 +46,5 @@ version = { file = "VERSION" }
45
46
  # Seed content shipped so `repopact init` works from an installed wheel. These
46
47
  # reference the canonical top-level files (one source of truth — no duplication).
47
48
  [tool.setuptools.data-files]
48
- "share/repopact/schemas" = ["schemas/*.json"]
49
- "share/repopact/templates" = ["templates/*"]
49
+ "share/repopact/schemas" = ["schemas/*.json"]
50
+ "share/repopact/templates" = ["templates/*"]
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "conformance-manifest.schema.json",
4
+ "type": "object",
5
+ "required": ["suite_version", "fixtures_root", "cases"],
6
+ "properties": {
7
+ "suite_version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
8
+ "spec_version_file": {"type": "string"},
9
+ "fixtures_root": {"type": "string", "minLength": 1},
10
+ "cases": {
11
+ "type": "array",
12
+ "minItems": 1,
13
+ "items": {
14
+ "type": "object",
15
+ "required": ["id", "path", "expect", "rules", "description"],
16
+ "properties": {
17
+ "id": {"type": "string", "minLength": 1},
18
+ "path": {"type": "string", "minLength": 1},
19
+ "overlay_on": {"type": "string", "minLength": 1},
20
+ "expect": {"enum": ["accept", "reject"]},
21
+ "expected_message": {"type": "string"},
22
+ "rules": {"type": "array", "items": {"type": "string"}, "minItems": 1},
23
+ "description": {"type": "string", "minLength": 1}
24
+ },
25
+ "allOf": [
26
+ {
27
+ "if": {"properties": {"expect": {"const": "reject"}}},
28
+ "then": {"required": ["expected_message", "overlay_on"]}
29
+ }
30
+ ]
31
+ }
32
+ }
33
+ }
34
+ }
@@ -11,6 +11,7 @@ from __future__ import annotations
11
11
  import argparse
12
12
  import json
13
13
  import shutil
14
+ import site
14
15
  import sys
15
16
  from datetime import date, timedelta
16
17
  from pathlib import Path
@@ -26,13 +27,16 @@ MODULES = (
26
27
 
27
28
  def _seed_dir(name: str) -> Path:
28
29
  """Locate seed content (schemas/templates) in a checkout or an installed wheel."""
29
- checkout = CHECKOUT / name
30
- if checkout.is_dir():
31
- return checkout
32
- installed = Path(sys.prefix) / "share" / "repopact" / name
33
- if installed.is_dir():
34
- return installed
35
- raise FileNotFoundError(f"cannot locate seed '{name}' (looked in {checkout} and {installed})")
30
+ candidates = [
31
+ CHECKOUT / name,
32
+ Path(sys.prefix) / "share" / "repopact" / name,
33
+ Path(site.USER_BASE) / "share" / "repopact" / name,
34
+ ]
35
+ for candidate in candidates:
36
+ if candidate.is_dir():
37
+ return candidate
38
+ looked = ", ".join(str(candidate) for candidate in candidates)
39
+ raise FileNotFoundError(f"cannot locate seed '{name}' (looked in {looked})")
36
40
 
37
41
 
38
42
  def _write(path: Path, text: str) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: repopact
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: A repository-native standard for durable agent work: binding invariants, evidence-gated work items, and drift audits.
5
5
  License: Apache-2.0
6
6
  Project-URL: Homepage, https://github.com/ForgeWireLabs/repopact
@@ -22,15 +22,15 @@ cannot be silently weakened.
22
22
  > The repository is the pact: authority, intent, evidence, and history that survive every
23
23
  > session.
24
24
 
25
- `pip install repopact` · Apache-2.0 · current release **2.0.1**
26
- ([changelog](decisions/0021-preflight-mandatory-and-provenance.md)).
25
+ `pip install repopact` · Apache-2.0 · current release **2.0.2**
26
+ ([changelog](decisions/0022-release-2.0.2-installed-seed-lookup.md)).
27
27
 
28
28
  ## How it relates to `AGENTS.md`
29
29
 
30
30
  `AGENTS.md` (and `CLAUDE.md`, editor rules) tell an agent *what to do* — they're
31
31
  instructions, plain Markdown, with no enforcement. RepoPact is the layer **above** them:
32
32
 
33
- > `AGENTS.md` tells the agent what to do. RepoPact proves it didn't quietly undo it.
33
+ > `AGENTS.md` tells an agent how to behave. RepoPact enforces and records whether the work respected the contract.
34
34
 
35
35
  RepoPact's distinguishing primitive is the **binding invariant** — a declared guarantee with
36
36
  a rationale, an escalation path, and (where its logical type permits) a machine enforcer.
@@ -83,6 +83,14 @@ repopact dashboard
83
83
  [`AGENTS.md`](AGENTS.md), then [`governance/charter.md`](governance/charter.md) and
84
84
  [`governance/workflow.md`](governance/workflow.md).
85
85
 
86
+ Alternative implementations can run the published conformance suite:
87
+
88
+ ```powershell
89
+ python scripts/run_conformance.py --command "your-validator --root {repo}"
90
+ ```
91
+
92
+ See [`CONFORMANCE.md`](CONFORMANCE.md) and [`conformance/`](conformance/).
93
+
86
94
  ## Adopt an *existing* repository
87
95
 
88
96
  For a project that already has CODEOWNERS, CI workflows, and nested `AGENTS.md` contracts,
@@ -102,7 +110,7 @@ idempotent.
102
110
 
103
111
  ## 2.0: mandatory preflight + provenance-typed records
104
112
 
105
- Decision [`0021`](decisions/0021-preflight-mandatory-and-provenance.md) (supersedes 0018):
113
+ Decision [`0021`](decisions/0022-release-2.0.2-installed-seed-lookup.md) (supersedes 0018):
106
114
 
107
115
  - **Mandatory preflight (default on).** No work begins until a work item exists and
108
116
  propagates through the pact; `repopact new` stamps the marker. Existing repos grandfather
@@ -132,7 +140,7 @@ holds a [formal model](research/formal-model.md) (the L0–L5 kernel, the typed
132
140
  lattice, the adoption trilemma), the pre-registered [experiment protocol](research/protocol.md)
133
141
  and [benchmark protocol](research/benchmark-protocol.md) (hypotheses H1–H13, falsification
134
142
  criteria, [threats to validity](research/threats-to-validity.md)), a [findings
135
- register](research/findings.md), and a full [paper draft](research/paper.md).
143
+ register](research/findings.md), and the current [paper](research/paper.md).
136
144
 
137
145
  **PactBench** — the runnable benchmark suite (pre-registered tasks measuring whether RepoPact
138
146
  enforcement reduces silent guarantee drift, with a model-agnostic harness and an S5 drift
@@ -3,6 +3,7 @@ README.md
3
3
  VERSION
4
4
  pyproject.toml
5
5
  schemas/audit-finding.schema.json
6
+ schemas/conformance-manifest.schema.json
6
7
  schemas/evidence-run.schema.json
7
8
  schemas/frozen-surface.schema.json
8
9
  schemas/invariants.schema.json
@@ -19,6 +20,7 @@ scripts/new.py
19
20
  scripts/plan_import.py
20
21
  scripts/repo_model.py
21
22
  scripts/repopact_cli.py
23
+ scripts/run_conformance.py
22
24
  scripts/takeover.py
23
25
  scripts/track_import.py
24
26
  scripts/validate_repo.py
@@ -9,6 +9,7 @@ new
9
9
  plan_import
10
10
  repo_model
11
11
  repopact_cli
12
+ run_conformance
12
13
  takeover
13
14
  track_import
14
15
  validate_repo
@@ -0,0 +1,112 @@
1
+ """Run the published RepoPact conformance suite.
2
+
3
+ The runner materializes each fixture as an isolated temporary repository, injects
4
+ the canonical schemas from this checkout, runs a RepoPact implementation, and
5
+ compares the result with conformance/manifest.json.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import argparse
11
+ import json
12
+ import shutil
13
+ import subprocess
14
+ import sys
15
+ import tempfile
16
+ from dataclasses import dataclass
17
+ from pathlib import Path
18
+
19
+
20
+ ROOT = Path(__file__).resolve().parents[1]
21
+ MANIFEST = ROOT / "conformance" / "manifest.json"
22
+
23
+
24
+ @dataclass(frozen=True)
25
+ class CaseResult:
26
+ case_id: str
27
+ passed: bool
28
+ detail: str
29
+
30
+
31
+ def load_manifest(path: Path = MANIFEST) -> dict:
32
+ with path.open(encoding="utf-8") as handle:
33
+ data = json.load(handle)
34
+ if not isinstance(data, dict):
35
+ raise ValueError(f"manifest must be a JSON object: {path}")
36
+ return data
37
+
38
+
39
+ def _copy_overlay(src: Path, dst: Path) -> None:
40
+ for path in src.rglob("*"):
41
+ if path.is_dir() or path.name == "meta.json":
42
+ continue
43
+ target = dst / path.relative_to(src)
44
+ target.parent.mkdir(parents=True, exist_ok=True)
45
+ shutil.copy2(path, target)
46
+
47
+
48
+ def materialize_case(root: Path, fixtures_root: Path, case: dict) -> Path:
49
+ repo = root / "repo"
50
+ overlay_on = case.get("overlay_on")
51
+ if overlay_on:
52
+ shutil.copytree(fixtures_root / str(overlay_on), repo)
53
+ _copy_overlay(fixtures_root / str(case["path"]), repo)
54
+ else:
55
+ shutil.copytree(fixtures_root / str(case["path"]), repo)
56
+ shutil.copytree(ROOT / "schemas", repo / "schemas")
57
+ return repo
58
+
59
+
60
+ def run_command(command: str, repo: Path) -> subprocess.CompletedProcess[str]:
61
+ rendered = command.format(repo=str(repo))
62
+ return subprocess.run(rendered, shell=True, text=True, capture_output=True)
63
+
64
+
65
+ def evaluate_case(case: dict, command: str, fixtures_root: Path) -> CaseResult:
66
+ case_id = str(case["id"])
67
+ with tempfile.TemporaryDirectory(prefix=f"repopact-conformance-{case_id}-") as tmp:
68
+ repo = materialize_case(Path(tmp), fixtures_root, case)
69
+ proc = run_command(command, repo)
70
+ output = "\n".join(part for part in (proc.stdout, proc.stderr) if part)
71
+ expect = case.get("expect")
72
+ if expect == "accept":
73
+ passed = proc.returncode == 0
74
+ detail = "accepted" if passed else f"expected accept, exit={proc.returncode}: {output.strip()}"
75
+ return CaseResult(case_id, passed, detail)
76
+ expected = str(case.get("expected_message", ""))
77
+ passed = proc.returncode != 0 and expected in output
78
+ detail = (
79
+ f"rejected with '{expected}'"
80
+ if passed
81
+ else f"expected reject containing '{expected}', exit={proc.returncode}: {output.strip()}"
82
+ )
83
+ return CaseResult(case_id, passed, detail)
84
+
85
+
86
+ def run_suite(command: str, manifest_path: Path = MANIFEST) -> list[CaseResult]:
87
+ manifest = load_manifest(manifest_path)
88
+ fixtures_root = manifest_path.parent / str(manifest.get("fixtures_root", "fixtures"))
89
+ return [evaluate_case(case, command, fixtures_root) for case in manifest.get("cases", [])]
90
+
91
+
92
+ def main() -> int:
93
+ parser = argparse.ArgumentParser(description="Run the RepoPact conformance suite")
94
+ parser.add_argument("--manifest", type=Path, default=MANIFEST)
95
+ parser.add_argument(
96
+ "--command",
97
+ default=f'"{sys.executable}" "{ROOT / "scripts" / "validate_repo.py"}" --root "{{repo}}"',
98
+ help="Implementation command template; {repo} is replaced with the fixture repo path.",
99
+ )
100
+ args = parser.parse_args()
101
+
102
+ results = run_suite(args.command, args.manifest.resolve())
103
+ failed = [result for result in results if not result.passed]
104
+ for result in results:
105
+ status = "PASS" if result.passed else "FAIL"
106
+ print(f"{status} {result.case_id}: {result.detail}")
107
+ print(f"\n{len(results) - len(failed)}/{len(results)} conformance cases passed.")
108
+ return 1 if failed else 0
109
+
110
+
111
+ if __name__ == "__main__":
112
+ sys.exit(main())
@@ -1,9 +1,9 @@
1
- """Conformance corpus test (work item 006, issue #4).
1
+ """Conformance corpus test (work items 006 and 019).
2
2
 
3
- Validates the fixtures under tests/fixtures/: the valid baseline must be accepted,
4
- and each invalid overlay must be rejected with its declared message. Fixtures do
5
- not vendor schemas; the canonical schemas/ are injected here so a fixture can never
6
- pass against a stale schema copy (no drift).
3
+ Validates the published suite under conformance/: the valid baseline must be
4
+ accepted, and each invalid overlay must be rejected with its declared message.
5
+ Fixtures do not vendor schemas; the canonical schemas/ are injected here so a
6
+ fixture can never pass against a stale schema copy (no drift).
7
7
  """
8
8
 
9
9
  from __future__ import annotations
@@ -15,12 +15,17 @@ import tempfile
15
15
  import unittest
16
16
  from pathlib import Path
17
17
 
18
+ import jsonschema
19
+
18
20
  ROOT = Path(__file__).resolve().parents[1]
19
21
  sys.path.insert(0, str(ROOT / "scripts"))
20
22
 
21
23
  from validate_repo import validate # noqa: E402
22
24
 
23
- FIXTURES = ROOT / "tests" / "fixtures"
25
+ import run_conformance # noqa: E402
26
+
27
+ MANIFEST = ROOT / "conformance" / "manifest.json"
28
+ FIXTURES = ROOT / "conformance" / "fixtures"
24
29
  VALID = FIXTURES / "valid"
25
30
  INVALID = FIXTURES / "invalid"
26
31
 
@@ -39,6 +44,22 @@ def build_repo(dst: Path, overlay: Path | None = None) -> Path:
39
44
 
40
45
 
41
46
  class ConformanceTests(unittest.TestCase):
47
+ def test_manifest_is_structurally_valid(self) -> None:
48
+ manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
49
+ schema = json.loads((ROOT / "schemas" / "conformance-manifest.schema.json").read_text(encoding="utf-8"))
50
+ jsonschema.Draft202012Validator(schema).validate(manifest)
51
+ self.assertEqual((ROOT / "VERSION").read_text(encoding="utf-8").strip(), manifest["suite_version"])
52
+ for case in manifest["cases"]:
53
+ self.assertTrue((FIXTURES / case["path"]).exists(), case["path"])
54
+
55
+ def test_manifest_matches_reference_suite(self) -> None:
56
+ results = run_conformance.run_suite(
57
+ f'"{sys.executable}" "{ROOT / "scripts" / "validate_repo.py"}" --root "{{repo}}"',
58
+ MANIFEST,
59
+ )
60
+ self.assertTrue(results, "no conformance cases found")
61
+ self.assertEqual([], [result.detail for result in results if not result.passed])
62
+
42
63
  def test_valid_fixture_is_accepted(self) -> None:
43
64
  with tempfile.TemporaryDirectory() as tmp:
44
65
  repo = build_repo(Path(tmp) / "repo")
repopact-2.0.1/VERSION DELETED
@@ -1 +0,0 @@
1
- 2.0.1
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes