Moves TargetRevenueLicenseConcept.md from the separate singular spec/ directory into specs/ (git mv, preserving history) and updates every live cross-reference (README, CONTRIBUTING, all specs/*.md, workplans, schema comments, source docstrings, test file) to the new path. This resolves the spec/ vs specs/ split that history/260728-SWOT-Assessment.md flagged as a "perpetual footgun" and recommended deciding on. The historical record of that split and the recommendation itself are left unedited in history/ (a dated assessment, not a living document) — only README and TSD now document the merge as resolved, with a pointer back to that history file for context. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
128 lines
3.7 KiB
Python
128 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Regenerate examples/phase-001/ledger.json with a correct hash chain.
|
|
|
|
The golden Phase package must exercise a real SHA-256 hash chain, not
|
|
hand-typed digests. This script builds the entry sequence from
|
|
specs/TargetRevenueLicenseConcept.md §23's illustrative example and writes it
|
|
out via the same hashing.entry_hash() the library and tests use, so the
|
|
fixture and the code that verifies it can never silently drift apart.
|
|
|
|
Run: python3 scripts/generate_golden_phase.py
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(REPO_ROOT / "src"))
|
|
|
|
from target_revenue import hashing # noqa: E402
|
|
|
|
PHASE_ID = "trsl:phase:example-001"
|
|
|
|
|
|
def entry(
|
|
entry_id: str,
|
|
entry_type: str,
|
|
amount: float,
|
|
recognized_at: str,
|
|
extension_id: str,
|
|
extension_version: str,
|
|
evidence_reference: str,
|
|
previous_entry_hash: str,
|
|
) -> dict:
|
|
return {
|
|
"id": entry_id,
|
|
"phase": PHASE_ID,
|
|
"type": entry_type,
|
|
"amount": amount,
|
|
"currency": "USD",
|
|
"recognized_at": recognized_at,
|
|
"extension": {"id": extension_id, "version": extension_version},
|
|
"evidence_reference": evidence_reference,
|
|
"previous_entry_hash": previous_entry_hash,
|
|
}
|
|
|
|
|
|
def main() -> None:
|
|
entries: list[dict] = []
|
|
previous_hash = hashing.GENESIS
|
|
|
|
specs = [
|
|
# (id, type, amount, recognized_at, extension_id, evidence_reference)
|
|
(
|
|
"trsl:entry:example0010001",
|
|
"development-credit",
|
|
25000,
|
|
"2026-09-01T09:00:00Z",
|
|
"trsl:extension:development-license",
|
|
"confidential:evidence:example-001-dc-0001",
|
|
),
|
|
(
|
|
"trsl:entry:example0010002",
|
|
"development-credit",
|
|
10000,
|
|
"2026-09-15T09:00:00Z",
|
|
"trsl:extension:phase-sponsorship",
|
|
"confidential:evidence:example-001-dc-0002",
|
|
),
|
|
(
|
|
"trsl:entry:example0010003",
|
|
"development-credit",
|
|
2000,
|
|
"2026-10-01T09:00:00Z",
|
|
"trsl:extension:service-with-development-allocation",
|
|
"confidential:evidence:example-001-dc-0003",
|
|
),
|
|
(
|
|
"trsl:entry:example0010004",
|
|
"remission-credit",
|
|
18000,
|
|
"2026-12-01T00:00:00Z",
|
|
"trsl:policy:linear-longstop-v0",
|
|
"confidential:evidence:example-001-rc-0001",
|
|
),
|
|
(
|
|
"trsl:entry:example0010005",
|
|
"development-credit",
|
|
30000,
|
|
"2027-03-01T09:00:00Z",
|
|
"trsl:extension:development-license",
|
|
"confidential:evidence:example-001-dc-0004",
|
|
),
|
|
(
|
|
"trsl:entry:example0010006",
|
|
"remission-credit",
|
|
15000,
|
|
"2027-06-01T00:00:00Z",
|
|
"trsl:policy:linear-longstop-v0",
|
|
"confidential:evidence:example-001-rc-0002",
|
|
),
|
|
]
|
|
|
|
for entry_id, entry_type, amount, recognized_at, ext_id, evidence in specs:
|
|
record = entry(
|
|
entry_id,
|
|
entry_type,
|
|
amount,
|
|
recognized_at,
|
|
ext_id,
|
|
"1.0",
|
|
evidence,
|
|
previous_hash,
|
|
)
|
|
entries.append(record)
|
|
previous_hash = hashing.entry_hash(record)
|
|
|
|
out_path = REPO_ROOT / "examples" / "phase-001" / "ledger.json"
|
|
with open(out_path, "w", encoding="utf-8") as f:
|
|
json.dump(entries, f, indent=2)
|
|
f.write("\n")
|
|
print(f"wrote {len(entries)} entries to {out_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|