S00-001: Define the Web scope passport and native exclusion boundaries
Changes: Add proposed scope ADR with reasons for all ten excluded IDs, retained Web obligations, lifecycle limits, external provider roles and deferred decisions. Add a document coverage/lifecycle checker with four negative mutations and executor evidence/handoff for security review. Validation: python3 experiments/0000-scope/check.py passed for ten excluded IDs and seven lifecycle scenarios; all four negative mutations were rejected. make check passed validation and 66 tooling tests. Whitespace and allowed source paths checked. No live browser or provider integration was tested; ADR awaits independent review. Task: S00-001 Agent: auto-orchestrator-48aab142ecde Role: orchestrator Action: claim Status: review Task title: Утвердить Web-профиль
This commit is contained in:
1 parent
522311022f
commit
d5ed7eaaed
9 files changed
+247
-8
No files matched your search
@@ -0,0 +1,69 @@
|
||||
"""Check the scope passport against canonical applicability and WEB-002 limits.
|
||||
|
||||
Document-only experiment; no product runtime or provider connection is simulated.
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
ID = re.compile(r"\| ((?:[A-Z]+-)+\d{3}) \| (.+?) \| (.+?) \|")
|
||||
STATES = {"foreground", "hidden", "closed-tab", "browser-terminated",
|
||||
"permission-denied", "offline", "logged-out"}
|
||||
|
||||
|
||||
def check(document, requirements):
|
||||
excluded = {r["id"] for r in requirements if r["applicability"] == "out_of_scope"}
|
||||
rows = ID.findall(document)
|
||||
assert len(rows) == len({r[0] for r in rows}), "Duplicate excluded ID"
|
||||
assert {r[0] for r in rows} == excluded, "Excluded coverage differs from canonical registry"
|
||||
for rid, reason, retained in rows:
|
||||
assert len(reason.strip()) >= 40, f"Missing substantive reason: {rid}"
|
||||
assert len(retained.strip()) >= 30, f"Missing Web boundary: {rid}"
|
||||
entry = next(r for r in requirements if r["id"] == rid)
|
||||
assert f"**{rid}.**" in (ROOT / entry["source"]).read_text(), rid
|
||||
lifecycle = {}
|
||||
for line in document.splitlines():
|
||||
cells = [c.strip() for c in line.split("|")[1:-1]]
|
||||
if cells and cells[0] in STATES:
|
||||
assert len(cells) == 5 and cells[0] not in lifecycle, "Malformed lifecycle row"
|
||||
lifecycle[cells[0]] = cells[1:]
|
||||
assert set(lifecycle) == STATES, "Incomplete lifecycle scenarios"
|
||||
assert all(v in {"conditional", "none", "not-guaranteed"}
|
||||
for row in lifecycle.values() for v in row), "Unsupported guarantee"
|
||||
for state in {"closed-tab", "browser-terminated", "offline", "logged-out"}:
|
||||
row = lifecycle[state]
|
||||
assert row[0] == "none" and row[2:] == ["none", "none"], f"False session/media promise: {state}"
|
||||
assert lifecycle["hidden"][0] == "not-guaranteed", "Hidden socket continuity promise"
|
||||
assert lifecycle["closed-tab"][1] == "conditional", "Push confused with session or guaranteed delivery"
|
||||
assert lifecycle["permission-denied"][1:] == ["none"] * 3, "Denied permissions bypassed"
|
||||
assert lifecycle["logged-out"] == ["none"] * 4, "Logout reactivation promise"
|
||||
return len(excluded), len(lifecycle)
|
||||
|
||||
|
||||
def main():
|
||||
document = (ROOT / "docs/decisions/0000-scope.md").read_text()
|
||||
requirements = json.loads((ROOT / "planning/requirements.json").read_text())
|
||||
counts = check(document, requirements)
|
||||
mutations = [
|
||||
re.sub(r"^\| ACC-003 \|.*\n", "", document, flags=re.M),
|
||||
re.sub(r"^\| ACC-003 \|.*$", "| ACC-003 | | |", document, flags=re.M),
|
||||
document.replace("| closed-tab | none | conditional | none | none |",
|
||||
"| closed-tab | conditional | conditional | none | none |"),
|
||||
document.replace("| closed-tab | none | conditional | none | none |",
|
||||
"| closed-tab | none | conditional | conditional | none |"),
|
||||
]
|
||||
for index, mutant in enumerate(mutations, 1):
|
||||
assert mutant != document, "Negative fixture did not mutate document"
|
||||
try:
|
||||
check(mutant, requirements)
|
||||
except AssertionError:
|
||||
continue
|
||||
raise AssertionError(f"False passport accepted: mutation {index}")
|
||||
print(f"PASS: {counts[0]} excluded IDs match registry/specs with reasons; "
|
||||
f"{counts[1]} lifecycle scenarios; {len(mutations)} negative mutations rejected.")
|
||||
print("LIMIT: document validation only; browser/provider behavior is untested.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user