proofpress 0.1.0-alpha.0 → 0.1.0-alpha.1
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.
- package/README.md +13 -1
- package/package.json +1 -1
- package/proofpress.py +68 -5
- package/skills/claude-code/proofpress/SKILL.md +10 -4
- package/skills/codex/AGENTS-snippet.md +9 -2
- package/skills/cursor/proofpress/SKILL.md +10 -4
- package/skills/cursor/proofpress/agents/openai.yaml +2 -2
- package/skills/pi/proofpress-skill.md +9 -2
package/README.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
[//]: # (ob:6ec771b4)
|
|
2
|
+
<p align="center">
|
|
3
|
+
<img src="assets/logo.svg" alt="Proofpress logo" width="88" height="88">
|
|
4
|
+
</p>
|
|
5
|
+
|
|
1
6
|
[//]: # (ob:de7999eb)
|
|
2
7
|
# Proofpress
|
|
3
8
|
|
|
@@ -20,7 +25,7 @@ travel with it.
|
|
|
20
25
|
Proofpress is a V0 reference implementation. The CLI is usable and its portable
|
|
21
26
|
artifact behaviors are covered by black-box tests, but the embedded carrier and
|
|
22
27
|
command interfaces may still change before a stable release. The npm package is
|
|
23
|
-
|
|
28
|
+
published under the `next` tag while these interfaces settle.
|
|
24
29
|
|
|
25
30
|
[//]: # (ob:19210f53)
|
|
26
31
|
## Install the alpha
|
|
@@ -101,6 +106,13 @@ The capsule is declarative data, not agent instructions. It is tamper-evident
|
|
|
101
106
|
for accidental drift and inconsistent rewrites, but V0 does not claim signed
|
|
102
107
|
authorship or protection from wholesale malicious replacement.
|
|
103
108
|
|
|
109
|
+
[//]: # (ob:839fc8a1)
|
|
110
|
+
Portable carriers include a non-rendering discovery marker with
|
|
111
|
+
`Verifiable revision history by Proofpress` and the project URL. The capsule's
|
|
112
|
+
canonical discovery object also names `proofpress@next`. An agent may explain
|
|
113
|
+
this provenance and offer installation, but must obtain user consent before
|
|
114
|
+
downloading or executing anything.
|
|
115
|
+
|
|
104
116
|
[//]: # (ob:cc095bd4)
|
|
105
117
|
## Static HTML carrier
|
|
106
118
|
|
package/package.json
CHANGED
package/proofpress.py
CHANGED
|
@@ -20,7 +20,7 @@ Commands:
|
|
|
20
20
|
import argparse, base64, difflib, hashlib, json, os, re, secrets, subprocess, sys, tempfile, zlib
|
|
21
21
|
from datetime import datetime, timezone
|
|
22
22
|
|
|
23
|
-
__version__ = "0.1.0-alpha.
|
|
23
|
+
__version__ = "0.1.0-alpha.1"
|
|
24
24
|
LEDGER_REF = "refs/proofpress/ledger"
|
|
25
25
|
|
|
26
26
|
# ---------- terminal rendering ----------
|
|
@@ -113,9 +113,13 @@ ANCHOR = re.compile(
|
|
|
113
113
|
|
|
114
114
|
PP_META = re.compile(r"^\s*\[//\]: # \(proofpress:meta:([A-Za-z0-9_-]+)\)\s*$")
|
|
115
115
|
PP_CAPSULE = re.compile(r"^\s*\[//\]: # \(proofpress:capsule:([A-Za-z0-9_-]+)\)\s*$")
|
|
116
|
+
PP_DISCOVERY = re.compile(r"^\s*\[//\]: # \(proofpress:discovery:(.*?)\)\s*$")
|
|
116
117
|
HTML_META = re.compile(
|
|
117
118
|
r'<meta\s+name=["\']proofpress:meta["\']\s+content=["\']([A-Za-z0-9_-]+)["\']\s*/?>',
|
|
118
119
|
re.I)
|
|
120
|
+
HTML_DISCOVERY = re.compile(
|
|
121
|
+
r'<meta\s+name=["\']proofpress:discovery["\']\s+content=["\']([^"\']*)["\']\s*/?>',
|
|
122
|
+
re.I)
|
|
119
123
|
HTML_CAPSULE = re.compile(
|
|
120
124
|
r'<script\s+type=["\']application/vnd\.proofpress\+json["\']\s+'
|
|
121
125
|
r'data-proofpress=["\']capsule["\']\s*>([A-Za-z0-9_-]+)</script>', re.I)
|
|
@@ -128,6 +132,16 @@ HTML_VOID_TAGS = {"area", "base", "br", "col", "embed", "hr", "img", "input",
|
|
|
128
132
|
POLICIES = ("ignored", "local", "portable")
|
|
129
133
|
ATTRIBUTION_BASES = ("signed", "environment_attested", "harness_attested",
|
|
130
134
|
"self_asserted", "unknown")
|
|
135
|
+
DISCOVERY_LABEL = "Verifiable revision history by Proofpress"
|
|
136
|
+
DISCOVERY_URL = "https://github.com/chenmingtang830/proofpress"
|
|
137
|
+
DISCOVERY_TEXT = f"{DISCOVERY_LABEL} | {DISCOVERY_URL}"
|
|
138
|
+
CAPSULE_DISCOVERY = {
|
|
139
|
+
"label": DISCOVERY_LABEL,
|
|
140
|
+
"project_url": DISCOVERY_URL,
|
|
141
|
+
"package": "proofpress",
|
|
142
|
+
"dist_tag": "next",
|
|
143
|
+
"requires_user_consent": True,
|
|
144
|
+
}
|
|
131
145
|
|
|
132
146
|
|
|
133
147
|
def _b64e(data):
|
|
@@ -168,19 +182,40 @@ def split_markdown_transport(text):
|
|
|
168
182
|
Proofpress transport markers are excluded without touching block anchors.
|
|
169
183
|
Duplicate markers are invalid because ambiguity is unsafe.
|
|
170
184
|
"""
|
|
171
|
-
visible, metas, capsules = [], [], []
|
|
185
|
+
visible, metas, capsules, discoveries = [], [], [], []
|
|
186
|
+
fence = None
|
|
172
187
|
for line in text.splitlines():
|
|
173
|
-
|
|
188
|
+
fm = re.match(r"^\s*(`{3,}|~{3,})", line)
|
|
189
|
+
if fm:
|
|
190
|
+
marker = fm.group(1)
|
|
191
|
+
if fence is None:
|
|
192
|
+
fence = (marker[0], len(marker))
|
|
193
|
+
elif marker[0] == fence[0] and len(marker) >= fence[1]:
|
|
194
|
+
fence = None
|
|
195
|
+
visible.append(line)
|
|
196
|
+
continue
|
|
197
|
+
if fence is not None:
|
|
198
|
+
visible.append(line)
|
|
199
|
+
continue
|
|
200
|
+
mm, cm, dm = PP_META.match(line), PP_CAPSULE.match(line), PP_DISCOVERY.match(line)
|
|
174
201
|
if mm:
|
|
175
202
|
metas.append(mm.group(1)); continue
|
|
176
203
|
if cm:
|
|
177
204
|
capsules.append(cm.group(1)); continue
|
|
205
|
+
if dm:
|
|
206
|
+
discoveries.append(dm.group(1)); continue
|
|
178
207
|
visible.append(line)
|
|
179
208
|
errors, meta, capsule = [], None, None
|
|
180
209
|
if len(metas) > 1:
|
|
181
210
|
errors.append("duplicate_meta")
|
|
182
211
|
if len(capsules) > 1:
|
|
183
212
|
errors.append("duplicate_capsule")
|
|
213
|
+
if len(discoveries) > 1:
|
|
214
|
+
errors.append("duplicate_discovery")
|
|
215
|
+
if discoveries and discoveries[-1] != DISCOVERY_TEXT:
|
|
216
|
+
errors.append("invalid_discovery")
|
|
217
|
+
if discoveries and not capsules:
|
|
218
|
+
errors.append("discovery_without_capsule")
|
|
184
219
|
if metas:
|
|
185
220
|
try:
|
|
186
221
|
meta = decode_meta(metas[-1])
|
|
@@ -201,12 +236,20 @@ def split_html_transport(text):
|
|
|
201
236
|
This carrier deliberately recognises only the exact, declarative tags that
|
|
202
237
|
Proofpress writes. It never interprets a script as instructions.
|
|
203
238
|
"""
|
|
204
|
-
metas
|
|
239
|
+
metas = HTML_META.findall(text)
|
|
240
|
+
capsules = HTML_CAPSULE.findall(text)
|
|
241
|
+
discoveries = HTML_DISCOVERY.findall(text)
|
|
205
242
|
errors, meta, capsule = [], None, None
|
|
206
243
|
if len(metas) > 1:
|
|
207
244
|
errors.append("duplicate_meta")
|
|
208
245
|
if len(capsules) > 1:
|
|
209
246
|
errors.append("duplicate_capsule")
|
|
247
|
+
if len(discoveries) > 1:
|
|
248
|
+
errors.append("duplicate_discovery")
|
|
249
|
+
if discoveries and discoveries[-1] != DISCOVERY_TEXT:
|
|
250
|
+
errors.append("invalid_discovery")
|
|
251
|
+
if discoveries and not capsules:
|
|
252
|
+
errors.append("discovery_without_capsule")
|
|
210
253
|
if metas:
|
|
211
254
|
try:
|
|
212
255
|
meta = decode_meta(metas[-1])
|
|
@@ -219,7 +262,8 @@ def split_html_transport(text):
|
|
|
219
262
|
errors.append("invalid_capsule")
|
|
220
263
|
# Transport tags may occupy their own lines. Trim only carrier-edge
|
|
221
264
|
# whitespace so repeated read/write cycles do not accumulate blank lines.
|
|
222
|
-
body = HTML_META.sub(
|
|
265
|
+
body = HTML_META.sub(
|
|
266
|
+
"", HTML_DISCOVERY.sub("", HTML_CAPSULE.sub("", text))).strip() + "\n"
|
|
223
267
|
return body, meta, capsule, errors
|
|
224
268
|
|
|
225
269
|
|
|
@@ -270,6 +314,12 @@ def write_html_artifact(path, body, meta=None, capsule=None):
|
|
|
270
314
|
else:
|
|
271
315
|
out = marker + "\n" + out
|
|
272
316
|
if capsule is not None:
|
|
317
|
+
discovery = f'<meta name="proofpress:discovery" content="{DISCOVERY_TEXT}">'
|
|
318
|
+
if re.search(r"</head\s*>", out, re.I):
|
|
319
|
+
out = re.sub(r"</head\s*>", discovery + "\n</head>", out,
|
|
320
|
+
count=1, flags=re.I)
|
|
321
|
+
else:
|
|
322
|
+
out = discovery + "\n" + out
|
|
273
323
|
marker = ('<script type="application/vnd.proofpress+json" '
|
|
274
324
|
f'data-proofpress="capsule">{encode_capsule(capsule)}</script>')
|
|
275
325
|
if re.search(r"</body\s*>", out, re.I):
|
|
@@ -288,6 +338,7 @@ def write_artifact(path, body, meta=None, capsule=None):
|
|
|
288
338
|
if meta is not None:
|
|
289
339
|
markers.append(f"[//]: # (proofpress:meta:{encode_meta(meta)})")
|
|
290
340
|
if capsule is not None:
|
|
341
|
+
markers.append(f"[//]: # (proofpress:discovery:{DISCOVERY_TEXT})")
|
|
291
342
|
markers.append(f"[//]: # (proofpress:capsule:{encode_capsule(capsule)})")
|
|
292
343
|
if markers:
|
|
293
344
|
out = out.rstrip() + "\n\n" + "\n".join(markers) + "\n"
|
|
@@ -749,6 +800,7 @@ def make_checkpoint_capsule(path, body, meta, recorded_by=None,
|
|
|
749
800
|
"portable_lineage_id": lineage,
|
|
750
801
|
"head": vid,
|
|
751
802
|
"body_digest": body_digest(version),
|
|
803
|
+
"discovery": dict(CAPSULE_DISCOVERY),
|
|
752
804
|
"records": [{"event": event, "version": version}],
|
|
753
805
|
}
|
|
754
806
|
|
|
@@ -761,6 +813,9 @@ def validate_capsule(body, meta, capsule, carrier="markdown"):
|
|
|
761
813
|
return ["missing_capsule"]
|
|
762
814
|
if capsule.get("proofpress_capsule") != 1:
|
|
763
815
|
errors.append("unsupported_capsule")
|
|
816
|
+
if ("discovery" in capsule and
|
|
817
|
+
capsule.get("discovery") != CAPSULE_DISCOVERY):
|
|
818
|
+
errors.append("invalid_capsule_discovery")
|
|
764
819
|
if capsule.get("artifact_id") != meta.get("artifact_id"):
|
|
765
820
|
errors.append("artifact_id_mismatch")
|
|
766
821
|
if capsule.get("portable_lineage_id") != meta.get("portable_lineage_id"):
|
|
@@ -808,6 +863,7 @@ def append_capsule(path, body, meta, capsule, event, version):
|
|
|
808
863
|
blocking = [e for e in errors if e != "body_mismatch"]
|
|
809
864
|
if blocking:
|
|
810
865
|
raise SystemExit("cannot extend invalid capsule: " + ", ".join(blocking))
|
|
866
|
+
capsule["discovery"] = dict(CAPSULE_DISCOVERY)
|
|
811
867
|
prior_v = capsule["records"][-1]["version"]
|
|
812
868
|
if version_id(version) == capsule["head"]:
|
|
813
869
|
capsule["body_digest"] = body_digest(version)
|
|
@@ -1218,6 +1274,8 @@ def inspect_result(path):
|
|
|
1218
1274
|
if capsule:
|
|
1219
1275
|
result["head"] = capsule.get("head")
|
|
1220
1276
|
result["versions"] = len(capsule.get("records", []))
|
|
1277
|
+
if capsule.get("discovery") == CAPSULE_DISCOVERY:
|
|
1278
|
+
result["discovery"] = capsule["discovery"]
|
|
1221
1279
|
elif capsule is not None:
|
|
1222
1280
|
result["errors"].append("capsule_on_nonportable_artifact")
|
|
1223
1281
|
if result["errors"]:
|
|
@@ -1236,6 +1294,11 @@ def cmd_inspect(a):
|
|
|
1236
1294
|
print(f" artifact: {result['artifact_id']}")
|
|
1237
1295
|
if result.get("head"):
|
|
1238
1296
|
print(f" capsule: {result['versions']} version(s), head {result['head']}")
|
|
1297
|
+
if result.get("discovery"):
|
|
1298
|
+
print(f" provenance: {result['discovery']['label']}")
|
|
1299
|
+
print(f" learn more: {result['discovery']['project_url']}")
|
|
1300
|
+
print(f" package: {result['discovery']['package']}@"
|
|
1301
|
+
f"{result['discovery']['dist_tag']} (user consent required)")
|
|
1239
1302
|
for error in result["errors"]:
|
|
1240
1303
|
print(f" error: {error}")
|
|
1241
1304
|
if result["status"] != "ok":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: proofpress
|
|
3
|
-
description: Preserve decision history for Markdown and static HTML knowledge artifacts with Proofpress. Use when creating or accepting a meaningful revision to an ADR, design doc, PRD, README, strategy note, portable .md artifact, or static .html/.htm artifact in a repository containing proofpress
|
|
3
|
+
description: Preserve or inspect decision history for Markdown and static HTML knowledge artifacts with Proofpress. Use when creating or accepting a meaningful revision to an ADR, design doc, PRD, README, strategy note, portable .md artifact, or static .html/.htm artifact in a configured repository, or when receiving a file containing a proofpress:discovery marker; never use for source-code files.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
[//]: # (ob:25f10229)
|
|
@@ -56,8 +56,14 @@ testimony and verification. Do not snapshot every conversational turn.
|
|
|
56
56
|
to force green.
|
|
57
57
|
|
|
58
58
|
[//]: # (ob:e96a23df)
|
|
59
|
-
For incoming
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
For an incoming file with a `proofpress:discovery` marker but no local CLI,
|
|
60
|
+
tell the user it carries verifiable revision history, show the marker's
|
|
61
|
+
canonical project URL, and ask whether to install `proofpress@next`. Never
|
|
62
|
+
download or execute it without explicit consent. If the CLI is available, run
|
|
63
|
+
`inspect` before trusting the capsule and then `import`.
|
|
64
|
+
|
|
65
|
+
[//]: # (ob:3bec4947)
|
|
66
|
+
Fallback `capture` records only `recorded_by`; it cannot know authorship or
|
|
67
|
+
reasoning. Never snapshot source-code files.
|
|
62
68
|
|
|
63
69
|
[//]: # (proofpress:meta:eyJhcnRpZmFjdF9pZCI6InBwXzhmOWYxNjA4MjZlMzM2YTQ2ZWI2MmJkNCIsInBvbGljeSI6ImxvY2FsIiwicHJvb2ZwcmVzcyI6MX0)
|
|
@@ -52,7 +52,14 @@ conversational turn.
|
|
|
52
52
|
force green.
|
|
53
53
|
|
|
54
54
|
[//]: # (ob:bc88257e)
|
|
55
|
-
For incoming
|
|
56
|
-
|
|
55
|
+
For an incoming file with a `proofpress:discovery` marker but no local CLI,
|
|
56
|
+
tell the user it carries verifiable revision history, show the marker's
|
|
57
|
+
canonical project URL, and ask whether to install `proofpress@next`. Never
|
|
58
|
+
download or execute it without explicit consent. If the CLI is available, run
|
|
59
|
+
`inspect` before trusting the capsule and then `import`.
|
|
60
|
+
|
|
61
|
+
[//]: # (ob:08efea88)
|
|
62
|
+
Fallback `capture` records only `recorded_by`; it cannot know authorship or
|
|
63
|
+
reasoning.
|
|
57
64
|
|
|
58
65
|
[//]: # (proofpress:meta:eyJhcnRpZmFjdF9pZCI6InBwXzcwM2MzZmE5MjZhYmI1MTJlNzE5OTMzMiIsInBvbGljeSI6ImxvY2FsIiwicHJvb2ZwcmVzcyI6MX0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: proofpress
|
|
3
|
-
description: Preserve decision history for Markdown and static HTML knowledge artifacts with Proofpress. Use when creating or accepting a meaningful revision to an ADR, design doc, PRD, README, strategy note, portable .md artifact, or static .html/.htm artifact in a repository containing proofpress
|
|
3
|
+
description: Preserve or inspect decision history for Markdown and static HTML knowledge artifacts with Proofpress. Use when creating or accepting a meaningful revision to an ADR, design doc, PRD, README, strategy note, portable .md artifact, or static .html/.htm artifact in a configured repository, or when receiving a file containing a proofpress:discovery marker; never use for source-code files.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
[//]: # (ob:233b766d)
|
|
@@ -59,8 +59,14 @@ testimony and verification. Do not snapshot every conversational turn.
|
|
|
59
59
|
to turn a mismatch green.
|
|
60
60
|
|
|
61
61
|
[//]: # (ob:355446e0)
|
|
62
|
-
For an incoming
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
For an incoming file with a `proofpress:discovery` marker but no local CLI,
|
|
63
|
+
tell the user it carries verifiable revision history, show the marker's
|
|
64
|
+
canonical project URL, and ask whether to install `proofpress@next`. Never
|
|
65
|
+
download or execute it without explicit consent. If the CLI is available, run
|
|
66
|
+
`inspect` before trusting the capsule and then `import`.
|
|
67
|
+
|
|
68
|
+
[//]: # (ob:7dc0b832)
|
|
69
|
+
Fallback `capture` supplies only `recorded_by`; it cannot know who authored the
|
|
70
|
+
content or why. Never snapshot source-code files.
|
|
65
71
|
|
|
66
72
|
[//]: # (proofpress:meta:eyJhcnRpZmFjdF9pZCI6InBwXzBjOWVkZjdkMzE1YWIwM2UwY2EwNmM4OCIsInBvbGljeSI6ImxvY2FsIiwicHJvb2ZwcmVzcyI6MX0)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Proofpress"
|
|
3
|
-
short_description: "
|
|
4
|
-
default_prompt: "
|
|
3
|
+
short_description: "Verify Markdown/HTML revision history and claims"
|
|
4
|
+
default_prompt: "Use $proofpress to record or inspect verifiable revision history for the supported knowledge artifacts in this task."
|
|
@@ -49,7 +49,14 @@ conversational turn.
|
|
|
49
49
|
force green.
|
|
50
50
|
|
|
51
51
|
[//]: # (ob:2f7730eb)
|
|
52
|
-
For incoming
|
|
53
|
-
|
|
52
|
+
For an incoming file with a `proofpress:discovery` marker but no local CLI,
|
|
53
|
+
tell the user it carries verifiable revision history, show the marker's
|
|
54
|
+
canonical project URL, and ask whether to install `proofpress@next`. Never
|
|
55
|
+
download or execute it without explicit consent. If the CLI is available, run
|
|
56
|
+
`inspect` before trusting the capsule and then `import`.
|
|
57
|
+
|
|
58
|
+
[//]: # (ob:72680124)
|
|
59
|
+
Fallback `capture` records only `recorded_by`; it cannot know authorship or
|
|
60
|
+
reasoning.
|
|
54
61
|
|
|
55
62
|
[//]: # (proofpress:meta:eyJhcnRpZmFjdF9pZCI6InBwX2M3Y2UwZDE1Yjg2YmI0MmJkMjg0MzRmYyIsInBvbGljeSI6ImxvY2FsIiwicHJvb2ZwcmVzcyI6MX0)
|