# -*- coding: utf-8 -*-
"""
build_registers.py — C2 REGISTER PROJECTOR.
Projects project_data.py into:
03_Registers/Project_Registers_v2.0.xlsx (one typed sheet per register, GOV-F5.2)
03_Registers/<NAME>.csv (plain-text projection, GOV-F9.8)
The RTM and the Closure Log are GENERATED here, never hand-maintained (GOV-B5.2, GOV-H2.2).
"""
import os, csv, datetime
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
import project_data as P
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
REG = os.path.join(ROOT, "03_Registers")
os.makedirs(REG, exist_ok=True)
HDR_FILL = PatternFill("solid", fgColor="1B2A38")
HDR_FONT = Font(name="Arial", size=10, bold=True, color="FFFFFF")
BODY = Font(name="Arial", size=10)
BOLD = Font(name="Arial", size=10, bold=True)
ALT = PatternFill("solid", fgColor="F2F6F8")
THIN = Side(style="thin", color="D5DEE4")
BOX = Border(left=THIN, right=THIN, top=THIN, bottom=THIN)
# --------------------------------------------------------------- generated registers
def rtm():
"""GOV-B5.2 — generated Requirements Traceability Matrix."""
comp_for = {}
for cid, name, resp, inp, outp, owner, reqs in P.COMPONENTS:
for r in reqs:
comp_for.setdefault(r, []).append("%s %s" % (cid, name))
evd_for = {}
for eid, req, method, artefact, date, by in P.EVD:
evd_for.setdefault(req, []).append("%s (%s, verified by %s)" % (eid, method, by))
obj_for = {
"REQ-SYS-01": "OBJ-1", "REQ-SYS-06": "OBJ-1", "REQ-SYS-11": "OBJ-1", "REQ-SYS-18": "OBJ-1",
"REQ-SYS-05": "OBJ-2", "REQ-SYS-07": "OBJ-2", "REQ-SYS-10": "OBJ-2",
"REQ-SYS-03": "OBJ-3", "REQ-SYS-04": "OBJ-3", "REQ-SYS-08": "OBJ-3", "REQ-SYS-09": "OBJ-3",
"REQ-SYS-12": "OBJ-4",
"REQ-SYS-13": "OBJ-5", "REQ-SYS-14": "OBJ-5", "REQ-SYS-15": "OBJ-5", "REQ-SYS-16": "OBJ-5",
"REQ-SYS-17": "OBJ-5", "REQ-CON-01": "OBJ-5", "REQ-CON-02": "OBJ-1", "REQ-CON-03": "OBJ-5",
"REQ-CON-04": "OBJ-5", "REQ-CON-05": "OBJ-1", "REQ-CON-06": "OBJ-5",
"REQ-MOE-01": "OBJ-3", "REQ-MOP-01": "OBJ-5",
}
rows = []
for r in P.REQ:
rid = r[0]
rows.append([
"Purpose", obj_for.get(rid, "UNALLOCATED"), rid,
"; ".join(comp_for.get(rid, [])) or "UNALLOCATED",
r[5], r[7], "; ".join(evd_for.get(rid, [])) or "NO EVIDENCE",
])
return rows
def closure_log():
"""GOV-H2.2 — generated projection of every register that must reach a terminal state."""
rows = []
def add(t, i, what, owner, raised, due, blocking, status, cond):
rows.append([t, i, what, owner, raised, due, blocking, status, cond])
for r in P.RQ:
add("Request", r[0], r[2][:110], "Master Brain", r[1], r[1], "-", r[5],
"The thing Zaid asked for exists and is delivered")
for a in P.ACT:
add("Action owed by Zaid", a[0], a[1], "Zaid", a[3], a[4], a[5], a[6],
"Zaid has provided the input or made the decision")
for c in P.CR:
add("Change", c[0], c[3][:110], "Master Brain", c[1], c[1], "-", c[13],
"Implemented, verified and synchronised")
for d in P.DEF:
add("Defect", d[0], d[1][:110], d[5], P.CURRENCY_DATE, P.CURRENCY_DATE, "-", d[8],
"Corrective action done AND independently verified")
for r in P.RSK:
add("Risk", r[0], r[1][:110], r[7], P.CURRENCY_DATE, "2026-09-20",
"Capital decision", r[8], "Mitigated, or accepted by Zaid in writing")
for i in P.ISS:
add("Issue", i[0], i[1][:110], i[5], P.CURRENCY_DATE, "2026-09-20", "Confidence level", i[6],
"Resolved or accepted by Zaid")
for b in P.BKL:
add("Backlog", b[0], b[1][:110], b[6], P.CURRENCY_DATE, "-", b[3], b[7],
"Done, or explicitly dropped with a reason")
for d in P.DEC:
add("Decision", d[0], d[1][:110], "Zaid", d[7], d[7], "-", d[8],
"Recorded with alternatives, weights, scoring and sensitivity")
return rows
# --------------------------------------------------------------- sheet definitions
SHEETS = [
("REQ", ["ID","Statement","Rationale","Source","Acceptance criteria","Verification method",
"Owner","Status","Type","Priority","Baseline"], P.REQ),
("SRC", ["ID","Claim","Value","Source URL","Publisher","Source date","Accessed","Confidence",
"Why below High"], P.SRC),
("ASM", ["ID","Assumption","Why it was needed","Confidence","What breaks if it is wrong",
"Who can confirm it","Status"], P.ASM),
("RQ", ["ID","Date","Zaid's words, verbatim and unedited","The interpretation acted on",
"Outcome","Status","% complete"], P.RQ),
("ACT", ["ID","Action owed by Zaid","Why it matters","Raised","Due","What it is blocking","Status"], P.ACT),
("DEC", ["ID","Decision","Alternatives considered","Criteria and weights (fixed before scoring)",
"Scoring","Sensitivity","Rationale","Date","Status"], P.DEC),
("RSK", ["ID","Risk","Cause","Impact","Likelihood 1-5","Consequence 1-5","Rating","Mitigation",
"Owner","Status"], [(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],r[8],r[9]) for r in P.RSK]),
("ISS", ["ID","Issue","Cause","Impact","Mitigation","Owner","Status"], P.ISS),
("DEF", ["ID","What was defective","Rule breached","Severity","Cause","Owner",
"Corrective action","Verification of the fix","Status"], P.DEF),
("IF", ["ID","Endpoint A","Endpoint B","Direction","Item exchanged","Format","Trigger",
"Owner A","Owner B"], P.IF_REG),
("CR", ["ID","Date","Initiated by","What changed","Why","Class and deciding question",
"Affected REQ IDs","Affected interfaces","Approval","V&V and regression evidence",
"Sync check result","Archive snapshot","Version","Status"], P.CR),
("BKL", ["ID","What","Why it matters","REQ served","Priority","Effort","Owner","Status"], P.BKL),
("WVR", ["ID","Rule waived","Reason","Risk accepted","Compensating control","Approver","Expiry"], P.WVR),
("CI", ["ID","Configuration item","Owner","Version","Location (relative to project root)","Baseline"], P.CI),
("STD", ["ID","Standard or code","Edition","Clauses that apply","Compliance evidence",
"Currency last verified"], P.STD),
("RUN", ["ID","Date","Model","Platform","Tools and connectors","Standard version",
"Accepted by","Note"], P.RUN),
("SITE",["ID","Date","Domain","Why (task and REQ)","What was done","What data it saw",
"Approval gate hit","Outcome"], P.SITE),
("FEEDBACK", ["ID","Date","Correction or preference","Reason class","How it was applied"], P.FEEDBACK),
("COMPONENTS", ["ID","Component","Single responsibility","Inputs","Outputs","Owner","Requirements scoped to it"],
[(c[0],c[1],c[2],c[3],c[4],c[5],", ".join(c[6])) for c in P.COMPONENTS]),
("AGENTS", ["ID","Role","Mission","REQ IDs it must satisfy","Inputs","Expected output (artefact + path)",
"Prohibitions","Exit gate"], P.AGENTS),
("RACI", ["Artefact","Built by","Verified by","Validated by"], P.RACI),
("EVD", ["ID","REQ ID proven","Method","Evidence artefact path","Date","Produced by"], P.EVD),
("FAH", ["FUN-ID","Function","Deliverable / location","ACT-ID","Action (user does...)","Control",
"HLP-ID","Help entry title","Diataxis type","Help link","Back link","Owner",
"Version / last verified","Status"], P.FAH),
("METRIC_LINEAGE", ["Metric","What this number means","Formula in words","Source data",
"As at","Owner"], P.METRIC_LINEAGE),
("GLOSSARY", ["Term","Definition"], P.GLOSSARY),
("RTM", ["Purpose","Objective","Requirement","Component","Verification method","Status","Evidence"], None),
("CLOSURE_LOG", ["Type","ID","What","Owner","Raised","Due","Blocking","Status","Closure condition"], None),
]
WIDTHS = {
"ID": 14, "Statement": 62, "Rationale": 42, "Source": 24, "Acceptance criteria": 60,
"Claim": 46, "Value": 46, "Source URL": 52, "Assumption": 56, "What breaks if it is wrong": 60,
"Zaid's words, verbatim and unedited": 70, "The interpretation acted on": 70, "Outcome": 40,
"Action owed by Zaid": 56, "Why it matters": 66, "Decision": 52, "Alternatives considered": 70,
"Criteria and weights (fixed before scoring)": 60, "Scoring": 40, "Sensitivity": 66, "Rationale": 60,
"Risk": 62, "Cause": 34, "Impact": 62, "Mitigation": 62, "What was defective": 58,
"Corrective action": 60, "Verification of the fix": 46, "What changed": 60, "Why": 46,
"Item exchanged": 34, "What": 60, "Definition": 92, "Function": 34, "Action (user does...)": 34,
"Evidence artefact path": 62, "Evidence": 62, "Formula in words": 62, "Mission": 50,
"Prohibitions": 60, "Exit gate": 50, "Inputs": 30, "Outputs": 34, "Expected output (artefact + path)": 40,
"Requirements scoped to it": 40, "Compliance evidence": 30, "What it is blocking": 40,
"Closure condition": 46, "What was done": 40, "Why (task and REQ)": 40,
}
def write_sheet(ws, headers, rows, title_note):
# REQ-CON-04 as amended: a frozen HEADER ROW alone still loses the row label when a wide
# register is scrolled sideways on a phone. Freezing the ID column as well is what the
# rule actually asks for (DEF-051).
ws.freeze_panes = "B3"
ws.cell(row=1, column=1, value=title_note).font = Font(name="Arial", size=10, italic=True, color="55636E")
ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=max(len(headers), 1))
for c, h in enumerate(headers, start=1):
cell = ws.cell(row=2, column=c, value=h)
cell.fill, cell.font = HDR_FILL, HDR_FONT
cell.alignment = Alignment(vertical="center", wrap_text=True)
ws.column_dimensions[get_column_letter(c)].width = WIDTHS.get(h, 20)
ws.row_dimensions[2].height = 30
for r, row in enumerate(rows, start=3):
for c, val in enumerate(row, start=1):
cell = ws.cell(row=r, column=c, value=val)
cell.font = BOLD if c == 1 else BODY
cell.alignment = Alignment(vertical="top", wrap_text=True)
cell.border = BOX
if r % 2 == 1:
cell.fill = ALT
ws.auto_filter.ref = "A2:%s%d" % (get_column_letter(len(headers)), max(2, len(rows) + 2))
def main():
wb = Workbook()
wb.remove(wb.active)
idx = wb.create_sheet("INDEX")
idx.column_dimensions["A"].width = 22
idx.column_dimensions["B"].width = 96
idx.cell(row=1, column=1, value="%s — REGISTER SET %s" % (P.PROJECT_NAME, P.BASELINE_VERSION)).font = \
Font(name="Arial", size=14, bold=True, color="1B2A38")
idx.cell(row=2, column=1,
value=("GENERATED FILE. Every sheet in this workbook is a projection of "
"01_System/project_data.py (GOV-B3.2, GOV-F2.2). Do not hand-edit it — "
"your edit will be overwritten on the next build. Edit project_data.py and "
"re-run 01_System/build_all.py.")).font = Font(name="Arial", size=10, italic=True, color="B03A2E")
idx.merge_cells("A2:B2")
idx.cell(row=3, column=1, value="Project class: %s Jurisdiction: %s All facts current at: %s"
% (P.PROJECT_CLASS, P.JURISDICTION, P.CURRENCY_DATE)).font = BODY
idx.merge_cells("A3:B3")
descriptions = {
"REQ":"What is required. Eleven fields, exactly one 'shall', a pass/fail acceptance criterion. The single source of truth.",
"SRC":"Every external fact in this project, with its URL, publisher, date and confidence. The anti-fabrication spine.",
"ASM":"Everything the study relies on that is NOT proven, with what breaks if it is wrong.",
"RQ":"Zaid's requests, in his own words, next to the interpretation the AI acted on.",
"ACT":"Things only Zaid can do. Each says what it unblocks.",
"DEC":"Decisions, with alternatives, weights fixed before scoring, and a sensitivity statement.",
"RSK":"Risks scored against criteria set before the first risk was logged.",
"ISS":"Risks that have already happened.",
"DEF":"Defects. Anything the governance standard calls defective lands here.",
"IF":"Interfaces between components. Both endpoints, both owners.",
"CR":"Change records. Eight-state lifecycle, class and deciding question recorded.",
"BKL":"Identified but not yet done.",
"WVR":"Waivers. Empty — none were raised, and the AI cannot self-grant one.",
"CI":"Configuration items: every controlled file with its version and location.",
"STD":"External standards and codes cited, with edition and currency date.",
"RUN":"AI run record: what produced these artefacts, on what platform, under which standard.",
"SITE":"Every domain reached, why, and what it saw. Zero banking or payment domains.",
"FEEDBACK":"Corrections and standing preferences from Zaid, and how they were applied.",
"COMPONENTS":"The nine components, each with exactly one responsibility.",
"AGENTS":"Sub-agent charters. Six mandatory fields each.",
"RACI":"Proof that the builder of a thing is never its verifier.",
"EVD":"Evidence set. The trace chain terminates here.",
"FAH":"Function to action to help entry. Fourteen fixed columns.",
"METRIC_LINEAGE":"What every number on the dashboard means and where it comes from.",
"GLOSSARY":"Every abbreviation used anywhere in this project.",
"RTM":"GENERATED traceability matrix: purpose to objective to requirement to component to evidence.",
"CLOSURE_LOG":"GENERATED. Everything that must reach a terminal state, in one list.",
}
idx.cell(row=5, column=1, value="Sheet").font = HDR_FONT
idx.cell(row=5, column=1).fill = HDR_FILL
idx.cell(row=5, column=2, value="What it holds").font = HDR_FONT
idx.cell(row=5, column=2).fill = HDR_FILL
r = 6
for name, headers, rows in SHEETS:
data = rows if rows is not None else (rtm() if name == "RTM" else closure_log())
ws = wb.create_sheet(name)
note = ("GENERATED PROJECTION of 01_System/project_data.py — do not hand-edit. "
"Project %s, baseline %s, facts current at %s."
% (P.PROJECT_NAME, P.BASELINE_VERSION, P.CURRENCY_DATE))
write_sheet(ws, headers, [list(x) for x in data], note)
idx.cell(row=r, column=1, value=name).font = BOLD
idx.cell(row=r, column=2, value="%s (%d rows)" % (descriptions.get(name, ""), len(data))).font = BODY
idx.cell(row=r, column=2).alignment = Alignment(wrap_text=True, vertical="top")
r += 1
# plain-text projection — GOV-F9.8
with open(os.path.join(REG, name + ".csv"), "w", newline="", encoding="utf-8") as f:
w = csv.writer(f)
w.writerow(headers)
for row in data:
w.writerow(list(row))
out = os.path.join(REG, "Project_Registers_v2.0.xlsx")
wb.save(out)
print("wrote", out)
print("wrote %d csv projections into %s" % (len(SHEETS), REG))
if __name__ == "__main__":
main()