repopact 2.1.0__tar.gz → 2.3.0__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.
- {repopact-2.1.0 → repopact-2.3.0}/PKG-INFO +3 -3
- {repopact-2.1.0 → repopact-2.3.0}/README.md +2 -2
- repopact-2.3.0/VERSION +1 -0
- {repopact-2.1.0 → repopact-2.3.0}/pyproject.toml +1 -0
- repopact-2.3.0/schemas/adopter-fleet.schema.json +96 -0
- {repopact-2.1.0 → repopact-2.3.0}/schemas/conformance-manifest.schema.json +20 -1
- {repopact-2.1.0 → repopact-2.3.0}/scripts/adopt_repo.py +17 -10
- {repopact-2.1.0 → repopact-2.3.0}/scripts/doctor.py +17 -8
- repopact-2.3.0/scripts/fleet_verify.py +529 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/generate_dashboard.py +30 -16
- {repopact-2.1.0 → repopact-2.3.0}/scripts/init_repo.py +3 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/new.py +3 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/plan_import.py +3 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/repopact.egg-info/PKG-INFO +3 -3
- {repopact-2.1.0 → repopact-2.3.0}/scripts/repopact.egg-info/SOURCES.txt +3 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/repopact.egg-info/top_level.txt +1 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/repopact_cli.py +51 -13
- {repopact-2.1.0 → repopact-2.3.0}/scripts/run_conformance.py +60 -1
- {repopact-2.1.0 → repopact-2.3.0}/scripts/takeover.py +3 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/validate_repo.py +129 -12
- {repopact-2.1.0 → repopact-2.3.0}/tests/test_conformance.py +43 -9
- repopact-2.3.0/tests/test_fleet_verify.py +233 -0
- {repopact-2.1.0 → repopact-2.3.0}/tests/test_validate_repo.py +33 -10
- repopact-2.1.0/VERSION +0 -1
- {repopact-2.1.0 → repopact-2.3.0}/LICENSE +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/schemas/audit-finding.schema.json +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/schemas/evidence-run.schema.json +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/schemas/frozen-surface.schema.json +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/schemas/invariants.schema.json +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/schemas/record-frontmatter.schema.json +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/schemas/work-item.schema.json +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/check_frozen_surface.py +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/frontmatter.py +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/generate_spec.py +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/repo_model.py +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/repopact.egg-info/dependency_links.txt +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/repopact.egg-info/entry_points.txt +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/repopact.egg-info/requires.txt +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/scripts/track_import.py +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/setup.cfg +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/templates/README.md +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/templates/decision.md +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/templates/evidence-run.json +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/templates/policy.md +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/templates/work-item.README.md +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/templates/work-item.json +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/tests/test_plan_import_links.py +0 -0
- {repopact-2.1.0 → repopact-2.3.0}/tests/test_takeover_refs.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: repopact
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
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,8 +22,8 @@ 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.
|
|
26
|
-
([changelog](decisions/
|
|
25
|
+
`pip install repopact` · Apache-2.0 · current release **2.2.0**
|
|
26
|
+
([changelog](decisions/0025-release-2.2.0-dashboard-integrity.md)).
|
|
27
27
|
|
|
28
28
|
## How it relates to `AGENTS.md`
|
|
29
29
|
|
|
@@ -9,8 +9,8 @@ cannot be silently weakened.
|
|
|
9
9
|
> The repository is the pact: authority, intent, evidence, and history that survive every
|
|
10
10
|
> session.
|
|
11
11
|
|
|
12
|
-
`pip install repopact` · Apache-2.0 · current release **2.
|
|
13
|
-
([changelog](decisions/
|
|
12
|
+
`pip install repopact` · Apache-2.0 · current release **2.2.0**
|
|
13
|
+
([changelog](decisions/0025-release-2.2.0-dashboard-integrity.md)).
|
|
14
14
|
|
|
15
15
|
## How it relates to `AGENTS.md`
|
|
16
16
|
|
repopact-2.3.0/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.3.0
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "adopter-fleet.schema.json",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"additionalProperties": false,
|
|
6
|
+
"required": ["version", "upstream", "adopters"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"$schema": {"type": "string"},
|
|
9
|
+
"version": {"const": 1},
|
|
10
|
+
"upstream": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"additionalProperties": false,
|
|
13
|
+
"required": ["repository", "version_file"],
|
|
14
|
+
"properties": {
|
|
15
|
+
"repository": {"type": "string", "pattern": "^[^/]+/[^/]+$"},
|
|
16
|
+
"version_file": {"type": "string", "minLength": 1}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"adopters": {
|
|
20
|
+
"type": "array",
|
|
21
|
+
"minItems": 1,
|
|
22
|
+
"items": {"$ref": "#/$defs/adopter"}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"$defs": {
|
|
26
|
+
"sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
|
|
27
|
+
"adopter": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"additionalProperties": false,
|
|
30
|
+
"required": ["id", "repository", "default_branch", "consumption", "validation_commands"],
|
|
31
|
+
"properties": {
|
|
32
|
+
"id": {"type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$"},
|
|
33
|
+
"repository": {"type": "string", "pattern": "^[^/]+/[^/]+$"},
|
|
34
|
+
"default_branch": {"type": "string", "minLength": 1},
|
|
35
|
+
"consumption": {
|
|
36
|
+
"oneOf": [
|
|
37
|
+
{"$ref": "#/$defs/pypiConsumption"},
|
|
38
|
+
{"$ref": "#/$defs/vendoredConsumption"}
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"validation_commands": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"minItems": 1,
|
|
44
|
+
"items": {"type": "string", "minLength": 1}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"pypiConsumption": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": false,
|
|
51
|
+
"required": ["type", "package", "version_file"],
|
|
52
|
+
"properties": {
|
|
53
|
+
"type": {"const": "pypi"},
|
|
54
|
+
"package": {"const": "repopact"},
|
|
55
|
+
"version_file": {"type": "string", "minLength": 1}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"vendoredConsumption": {
|
|
59
|
+
"type": "object",
|
|
60
|
+
"additionalProperties": false,
|
|
61
|
+
"required": ["type", "version_file", "upstream_version", "upstream_revision", "files"],
|
|
62
|
+
"properties": {
|
|
63
|
+
"type": {"const": "vendored"},
|
|
64
|
+
"version_file": {"type": "string", "minLength": 1},
|
|
65
|
+
"upstream_version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
|
|
66
|
+
"upstream_revision": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
|
|
67
|
+
"files": {
|
|
68
|
+
"type": "array",
|
|
69
|
+
"minItems": 1,
|
|
70
|
+
"items": {"$ref": "#/$defs/vendoredFile"}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"vendoredFile": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"additionalProperties": false,
|
|
77
|
+
"required": ["upstream_path", "adopter_path", "mode", "upstream_sha256", "adopter_sha256"],
|
|
78
|
+
"properties": {
|
|
79
|
+
"upstream_path": {"type": "string", "minLength": 1},
|
|
80
|
+
"adopter_path": {"type": "string", "minLength": 1},
|
|
81
|
+
"mode": {"enum": ["exact", "overlay"]},
|
|
82
|
+
"upstream_sha256": {"$ref": "#/$defs/sha256"},
|
|
83
|
+
"adopter_sha256": {"$ref": "#/$defs/sha256"},
|
|
84
|
+
"overlay_path": {"type": "string", "minLength": 1},
|
|
85
|
+
"overlay_sha256": {"$ref": "#/$defs/sha256"}
|
|
86
|
+
},
|
|
87
|
+
"allOf": [
|
|
88
|
+
{
|
|
89
|
+
"if": {"properties": {"mode": {"const": "overlay"}}},
|
|
90
|
+
"then": {"required": ["overlay_path", "overlay_sha256"]},
|
|
91
|
+
"else": {"not": {"anyOf": [{"required": ["overlay_path"]}, {"required": ["overlay_sha256"]}]}}
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -2,16 +2,34 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "conformance-manifest.schema.json",
|
|
4
4
|
"type": "object",
|
|
5
|
-
"
|
|
5
|
+
"additionalProperties": false,
|
|
6
|
+
"required": ["suite_version", "fixtures_root", "rules", "cases"],
|
|
6
7
|
"properties": {
|
|
8
|
+
"$schema": {"type": "string"},
|
|
7
9
|
"suite_version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
|
|
8
10
|
"spec_version_file": {"type": "string"},
|
|
9
11
|
"fixtures_root": {"type": "string", "minLength": 1},
|
|
12
|
+
"rules": {
|
|
13
|
+
"type": "array",
|
|
14
|
+
"minItems": 1,
|
|
15
|
+
"items": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"additionalProperties": false,
|
|
18
|
+
"required": ["id", "source", "enforced_by", "description"],
|
|
19
|
+
"properties": {
|
|
20
|
+
"id": {"type": "string", "minLength": 1},
|
|
21
|
+
"source": {"type": "string", "minLength": 1},
|
|
22
|
+
"enforced_by": {"type": "string", "minLength": 1},
|
|
23
|
+
"description": {"type": "string", "minLength": 1}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
10
27
|
"cases": {
|
|
11
28
|
"type": "array",
|
|
12
29
|
"minItems": 1,
|
|
13
30
|
"items": {
|
|
14
31
|
"type": "object",
|
|
32
|
+
"additionalProperties": false,
|
|
15
33
|
"required": ["id", "path", "expect", "rules", "description"],
|
|
16
34
|
"properties": {
|
|
17
35
|
"id": {"type": "string", "minLength": 1},
|
|
@@ -19,6 +37,7 @@
|
|
|
19
37
|
"overlay_on": {"type": "string", "minLength": 1},
|
|
20
38
|
"expect": {"enum": ["accept", "reject"]},
|
|
21
39
|
"expected_message": {"type": "string"},
|
|
40
|
+
"dashboard": {"enum": ["canonical", "preserve", "remove"]},
|
|
22
41
|
"rules": {"type": "array", "items": {"type": "string"}, "minItems": 1},
|
|
23
42
|
"description": {"type": "string", "minLength": 1}
|
|
24
43
|
},
|
|
@@ -21,9 +21,10 @@ import re
|
|
|
21
21
|
import subprocess
|
|
22
22
|
import sys
|
|
23
23
|
from datetime import date, datetime, timedelta
|
|
24
|
-
from pathlib import Path
|
|
25
|
-
|
|
26
|
-
import
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
import generate_dashboard
|
|
27
|
+
import init_repo # reuse _seed_dir, _json/_write semantics, LIFECYCLE
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
# --- non-destructive primitives --------------------------------------------
|
|
@@ -330,16 +331,22 @@ def adopt(target: Path, today: date | None = None, dry_run: bool = False) -> Rep
|
|
|
330
331
|
"from the repository scan rather than proven by a run. Attach real verification evidence and\n"
|
|
331
332
|
"run `repopact doctor` to ratchet it to concrete, then complete it. " + summary + "\n", target)
|
|
332
333
|
|
|
333
|
-
rep.write(target / "decisions" / "0001-adopt-repopact.md",
|
|
334
|
+
rep.write(target / "decisions" / "0001-adopt-repopact.md",
|
|
334
335
|
"---\nid: 0001\ntitle: Adopt RepoPact\nstatus: accepted\n"
|
|
335
336
|
f"date: {today.isoformat()}\nsupersedes: []\n---\n\n# 0001: Adopt RepoPact\n\n## Context\n\n"
|
|
336
337
|
"The project already had ad-hoc governance (CODEOWNERS, CI gates, AGENTS.md). RepoPact\n"
|
|
337
|
-
"makes those bindings explicit and machine-checkable.\n\n## Decision\n\n"
|
|
338
|
-
"Adopt RepoPact; existing workflows become binding gates (INV-2) and ownership becomes\n"
|
|
339
|
-
"scopes/roles. Existing files were preserved; RepoPact records were added around them.\n", target)
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
338
|
+
"makes those bindings explicit and machine-checkable.\n\n## Decision\n\n"
|
|
339
|
+
"Adopt RepoPact; existing workflows become binding gates (INV-2) and ownership becomes\n"
|
|
340
|
+
"scopes/roles. Existing files were preserved; RepoPact records were added around them.\n", target)
|
|
341
|
+
|
|
342
|
+
# The dashboard is derived, but adoption remains non-destructive: create the
|
|
343
|
+
# canonical projection only when the reserved path is absent. An existing file
|
|
344
|
+
# is preserved and validation will identify it if it is not canonical.
|
|
345
|
+
dashboard_text = "" if dry_run else generate_dashboard.generate(target, today=today)
|
|
346
|
+
rep.write(target / "audits" / "reports" / "dashboard.md", dashboard_text, target)
|
|
347
|
+
|
|
348
|
+
rep.gitignored = gitignored_records(target, rep.created)
|
|
349
|
+
return rep
|
|
343
350
|
|
|
344
351
|
|
|
345
352
|
def _print_report(rep: Report) -> None:
|
|
@@ -20,10 +20,11 @@ import shutil
|
|
|
20
20
|
import sys
|
|
21
21
|
from dataclasses import dataclass
|
|
22
22
|
from datetime import date, timedelta
|
|
23
|
-
from pathlib import Path
|
|
24
|
-
|
|
25
|
-
import adopt_repo
|
|
26
|
-
import
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
import adopt_repo
|
|
26
|
+
import generate_dashboard
|
|
27
|
+
import validate_repo
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
@dataclass
|
|
@@ -296,10 +297,18 @@ def fix(root: Path, today: date | None = None) -> list[str]:
|
|
|
296
297
|
# 6. ratchet provisional records whose evidence is now concrete (decision 0021)
|
|
297
298
|
actions.extend(_ratchet_provisional(root))
|
|
298
299
|
|
|
299
|
-
# 7. migrate preflight on upgrade: grandfather pre-2.0 work items (decision 0021)
|
|
300
|
-
actions.extend(_migrate_preflight(root, today))
|
|
301
|
-
|
|
302
|
-
|
|
300
|
+
# 7. migrate preflight on upgrade: grandfather pre-2.0 work items (decision 0021)
|
|
301
|
+
actions.extend(_migrate_preflight(root, today))
|
|
302
|
+
|
|
303
|
+
# 8. derived output is safe to repair because it is fully reproducible.
|
|
304
|
+
dashboard = root / "audits" / "reports" / "dashboard.md"
|
|
305
|
+
expected = generate_dashboard.generate(root, today=today)
|
|
306
|
+
actual = dashboard.read_text(encoding="utf-8") if dashboard.is_file() else None
|
|
307
|
+
if actual != expected:
|
|
308
|
+
generate_dashboard.write_dashboard(root, today=today)
|
|
309
|
+
actions.append("regenerated audits/reports/dashboard.md")
|
|
310
|
+
|
|
311
|
+
return actions
|
|
303
312
|
|
|
304
313
|
|
|
305
314
|
def main() -> int:
|