diff --git a/docs/automation/handoffs/pre-phase10/.gitattributes b/docs/automation/handoffs/pre-phase10/.gitattributes new file mode 100644 index 0000000..a9f0f6f --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/.gitattributes @@ -0,0 +1,2 @@ +# Preserve source instructions and hash-indexed evidence identically across Windows/Linux checkouts. +* -text diff --git a/docs/automation/handoffs/pre-phase10/AI_RESULTS.md b/docs/automation/handoffs/pre-phase10/AI_RESULTS.md new file mode 100644 index 0000000..84275bc --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/AI_RESULTS.md @@ -0,0 +1,29 @@ +# AI and parser qualification reconciliation + +## What was actually exercised + +| Layer | Evidence / decision | What it does not establish | +|---|---|---| +| Real Docling parsing | Fresh14 real document-extractor tests; actual PDF/DOCX import browser lanes and live local PDF worker. Native extraction uses pinned model-free Docling | OCR/layout-model or arbitrary-document completeness | +| Deterministic interpretation | Frozen benchmark evidence remains separately attributed: PDF typed precision100%, recall81.967%; DOCX122/122 typed facts. Fresh oracle/structural helper tests validate their own logic | Population accuracy, real model quality, or every unusual layout | +| Review/correction/application | Real browser/MariaDB/RD21 lanes exercise approved facts, duplicates, rollback, stale writes and historical preservation | Automatic model semantic truth or human usability approval | +| Generic queued strategy | Fresh actual local operation succeeded with saved nonempty160-character summary; admin retained a prior provider_unavailable event | First-attempt reliability, latency guarantees or factual CV interpretation | +| Scheduled job enrichment | Fresh actual scheduler persisted summary681characters plus tags, then read back through API | Semantic quality or external provider/production acceptance | +| Optional CV model adapter | Three real isolated Qwen requests completed but all three were rejected with ValueError by the adapter. **Compatibility and factual accuracy remain BLOCKED** | Zero accepted suggestions is not zero hallucinations or100% precision | +| Active CV processing configuration | CV_IMPORT_AI_ENABLED=false; adapter remains disconnected from active deterministic processing | No model activation or owner security-risk acceptance | + +## Real adapter probe + +[AI_EVALUATION_PLAN.md](AI_EVALUATION_PLAN.md) records authority and guards before inference. The official local qwen2.5:7b Q4_K_M manifest845dbda0ea48ed749caafd9e6037047aa19acfcfd82e704d7ca97d631a0b697e and all stored blobs were hash-verified. A disposable Ollama instance reused those bytes through a **read-only** model-volume mount, with no published ports, internal-only network, cloud disabled, four CPUs/8GiB, one loaded model/parallel request and no daemon socket. A bounded read-only Python client exercised the unchanged adapter using its real transport, JSON schema, source grounding and120-second timeout. Existing development Ollama/services/configuration/cache were not changed. Exact generated containers and the empty network were removed, with cleanup recorded. + +EN, Bokmål and instruction-in-source cases took79.009,47.308 and35.811 seconds respectively. All returned the explicit rejected/failed outcome. No raw response was retained by this first probe, so the precise invalid suggestion/schema distinction is not claimed. No accepted semantic precision/recall is computed. These three independently authored development probes are not the frozen corpus and are not PDF/DOCX end-to-end model evaluations. They supply genuine negative compatibility evidence; they do not replace the outstanding full qualification. + +Raw source-bound process/results/cases/client hashes are in `.artifacts/automation-handoff-01/model-probe-01/`; portable evidence is indexed in TEST_EVIDENCE.json. The probe process exit0 means the measurement completed and cleanup ran, **not that AI acceptance passed**. + +The local runtime's original model volume was found writable despite a read-only container root. This finding informed the isolated read-only mirror above; no stronger existing-cache protection is inferred. Artifact integrity and scoped known-advisory evidence are independent of whole-image/native sandbox security. A fresh read-only inventory of the exact current sidecar image found63 installed distributions;126 exact OSV/PyPI queries returned zero advisory records and one retained PyPI404 for torch2.13.0+cpu. The new raw audit remains INCOMPLETE. Python remains CONDITIONAL under the retained P9-SEC-02 disposition; neither this probe, this incomplete scan nor import-lock zero advisories closes native/whole-image/production qualifications. No package was resolved or installed by the audit. + +Future owner-approved qualification must use immutable approved artifacts/runtime and identical frozen documents/annotations, source and prompt hashes; measure precision/recall, record association, dates, hallucinated/unsupported claims, provenance, duplicate behavior, multilingual semantics and review burden. Add missing/malformed output, unavailable service, timeout/cancel/retry, injection, resource and cache-integrity probes. Keep deterministic, model-assisted, user-corrected and persisted outcomes separate. Do not select a permanent general-purpose model or enable the adapter from these results. + +## Existing generic-AI precondition + +StrategySnapshotService currently requires nonempty legacy ProfileCvText in both admission and generation. The reviewed Docling apply path persists canonical structured facts and deliberately does not overwrite that user-controlled text. Therefore the successful strategy smoke used separately authored fictional CV text as an explicit precondition; it does **not** prove strategy generation from a canonical-only imported profile. Career Profile → CV Editor → PDF is independently tested and does not require this legacy text. Product Review should assess this generic-AI source compatibility as a separate bounded backlog item; do not silently populate legacy text from unreviewed uploaded content or claim every AI option works for every profile/account. diff --git a/docs/automation/handoffs/pre-phase10/BLOCKERS.json b/docs/automation/handoffs/pre-phase10/BLOCKERS.json new file mode 100644 index 0000000..c35c2a2 --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/BLOCKERS.json @@ -0,0 +1,307 @@ +{ + "schemaVersion": 1, + "workstreamId": "AUTOMATION-HANDOFF-01", + "kind": "BLOCKERS", + "items": [ + { + "id": "P10-ENTRY-01", + "description": "No protected owner approval of the final published development baseline and exact cleanup scope was supplied to this handoff.", + "evidence": [ + "AUTHORITY.md", + "docs/cv-integration-qa/PHASE_10_HANDOFF.md" + ], + "severity": "HIGH", + "acceptanceCriterion": "Exact baseline/scope and independent stage entry", + "requiredAction": "Review the completed package and candidate scope; grant phase10-development-entry only through the separate protected approval process. A repository GO is insufficient.", + "blockingPhase": [ + "PHASE-10" + ], + "responsibleParty": "Owner / protected controller approval authority", + "deferralAuthority": null, + "classification": "MANDATORY_ENTRY", + "status": "BLOCKED" + }, + { + "id": "P10-CANDIDATE-01", + "description": "No proposed product deletion has proven absence of static, dynamic, route and historical-data consumers.", + "evidence": [ + "CLEANUP_INVENTORY.md", + "docs/redesign/IMPLEMENTATION_PLAN.md" + ], + "severity": "HIGH", + "acceptanceCriterion": "Unused-route proof; passing affected tests; satisfied functionality inventory", + "requiredAction": "Prepare and approve a concrete candidate with caller/route/inventory/rollback proof and affected native regression; retain every active compatibility path.", + "blockingPhase": [ + "PHASE-10: each removal candidate" + ], + "responsibleParty": "Development owner / reviewer", + "deferralAuthority": null, + "classification": "MANDATORY_ENTRY", + "status": "BLOCKED" + }, + { + "id": "AUTO-RUNTIME-01", + "description": "The separate orchestrator reports an unqualified native Codex sandbox and missing isolated runner/signing boundary.", + "evidence": [ + "AUTHORITY.md", + "ROADMAP.md" + ], + "severity": "HIGH", + "acceptanceCriterion": "Independent qualified execution boundary", + "requiredAction": "Qualify the sandbox/isolated account or VM, protected approval/state ACLs, process/CPU/memory/tool/read/egress/secret boundaries and actual worker execution. This workstream must not modify that runtime.", + "blockingPhase": [ + "AUTOMATIC_PHASE-10_EXECUTION" + ], + "responsibleParty": "AUTONOMOUS-ROADMAP-01 platform operator", + "deferralAuthority": null, + "classification": "MANDATORY_ENTRY", + "status": "BLOCKED" + }, + { + "id": "AUTO-ADAPTER-01", + "description": "The external controller real-stage test adapter is unconfigured; synthetic orchestration tests are not application qualification.", + "evidence": [ + "ROADMAP.md", + "READY_TO_RUN.md" + ], + "severity": "HIGH", + "acceptanceCriterion": "Qualified real-stage composite test adapter", + "requiredAction": "Install/review actual commands and parsers, source and suite membership, report freshness and failure/skip/retry/cleanup policy. Independently rerun candidate checks; do not set configured=true as a bypass.", + "blockingPhase": [ + "AUTOMATIC_PHASE-10_EXECUTION" + ], + "responsibleParty": "AUTONOMOUS-ROADMAP-01 test-adapter maintainer", + "deferralAuthority": null, + "classification": "MANDATORY_ENTRY", + "status": "BLOCKED" + }, + { + "id": "PDF-S01-01", + "description": "Revised-template S01 DOM Range versus PDF character-cell coordinate failures remain undispositioned. Raster agreement is a different measurement.", + "evidence": [ + "docs/pre-phase10-ux/ACCEPTANCE.md", + "VISUAL_REVIEW.md" + ], + "severity": "MODERATE", + "acceptanceCriterion": "Required preview/PDF fidelity and visual spacing qualification", + "requiredAction": "Retain original oracle and all failures. Investigate/fix an actual measured defect; obtain explicit protected scope/criterion disposition if applicability is ambiguous. Do not waive an automated requirement using a model summary or change goldens to conceal failures.", + "blockingPhase": [ + "PHASE-10: document/rendering scope or required PDF gate", + "PRODUCTION" + ], + "responsibleParty": "Document QA owner / owner acceptance authority", + "deferralAuthority": null, + "classification": "MANDATORY_ENTRY", + "status": "BLOCKED" + }, + { + "id": "HUMAN-01", + "description": "Physical device, keyboard/AT/contrast, human EN/Bokmål, typography and actual printing acceptance are not provided.", + "evidence": [ + "MANUAL_ACCEPTANCE.md" + ], + "severity": "MODERATE", + "acceptanceCriterion": "Genuine human/device/language/print acceptance", + "requiredAction": "Complete the prioritised manual scenarios; record exact device/AT/language/print evidence outside model-writable approval authority. Candidate-specific regressions still block.", + "blockingPhase": [ + "HUMAN_ACCEPTANCE", + "PRODUCTION", + "PHASE-10: affected candidate requires preservation" + ], + "responsibleParty": "Owner / human QA", + "deferralAuthority": "docs/redesign/phase-9/REQUEST.md:246–252 permits genuine unfinished human checks as release gates;426–439 requires individual disposition. This is not automatic Phase10 entry or an executable deferral.", + "classification": "CONDITIONAL_DEVELOPMENT", + "status": "CONDITIONALLY_DEFERRED" + }, + { + "id": "AI-CV-01", + "description": "The disabled/disconnected CV adapter has no accepted end-to-end semantic qualification. Three real isolated synthetic responses were rejected.", + "evidence": [ + "AI_EVALUATION_PLAN.md", + "AI_RESULTS.md", + "docs/cv-import/ACCEPTANCE.md" + ], + "severity": "HIGH", + "acceptanceCriterion": "No invented facts; source-grounded factual accuracy and explicit user review", + "requiredAction": "Keep CV_IMPORT_AI_ENABLED=false and active processing deterministic; qualify immutable model/runtime/schema/prompt on frozen real PDF/DOCX corpus, review burden and adversarial cases before activation. Small generic successes do not qualify CV accuracy.", + "blockingPhase": [ + "CV_MODEL_ACTIVATION", + "CV_AI_ACCURACY", + "PRODUCTION_AI_QUALITY" + ], + "responsibleParty": "AI qualification owner", + "deferralAuthority": "docs/cv-import/ACCEPTANCE.md permits model-independent conditional development with inactive optional adapter; no security-risk waiver or automatic controller deferral.", + "classification": "CONDITIONAL_DEVELOPMENT", + "status": "CONDITIONALLY_DEFERRED" + }, + { + "id": "DET-RECALL-01", + "description": "Frozen deterministic PDF typed recall and unresolved-source precision remain partial; source correction is necessary.", + "evidence": [ + "docs/pre-phase10-ux/ACCEPTANCE.md" + ], + "severity": "MODERATE", + "acceptanceCriterion": "Near-100% is aspirational; preserve unknown/ambiguous facts", + "requiredAction": "Preserve source evidence, unknown values, conservative merges and manual corrections; benchmark changes on frozen corpus separately from model probes.", + "blockingPhase": [ + "BROAD_EXTRACTION_ACCURACY_CLAIMS", + "PHASE-10: review/legacy compatibility removal" + ], + "responsibleParty": "CV/import QA owner", + "deferralAuthority": "docs/cv-import/ACCEPTANCE.md and docs/cv-integration-qa/ACCEPTANCE.md explicitly condition supported workflow acceptance on these retained limitations.", + "classification": "CONDITIONAL_DEVELOPMENT", + "status": "CONDITIONALLY_DEFERRED" + }, + { + "id": "PYSEC-01", + "description": "Full Python dependency security is conditional; retained vendor-local Torch PyPI404 is not a clean two-provider/whole-image verdict.", + "evidence": [ + "docs/redesign/phase-9/p9-sec-02/ACCEPTANCE_ADDENDUM_2026-10-25.md", + "docs/redesign/phase-9/p9-sec-02/DISPOSITIONS.md" + ], + "severity": "HIGH", + "acceptanceCriterion": "No bypass of Python/model/cache qualification", + "requiredAction": "Retain exact installed OSV/vendor wheel/range/source/model evidence and incomplete response; refresh before affected changes/release. Current import-lock zero advisories does not close full runtime/native security.", + "blockingPhase": [ + "PYTHON_UNTRUSTED_PROCESSING_QUALIFICATION", + "PRODUCTION", + "PHASE-10: affected Python/model path" + ], + "responsibleParty": "Security / Python qualification owner", + "deferralAuthority": "Existing P9-SEC-02 scoped CONDITIONAL PASS and Phase9 development decision; no owner residual-risk acceptance.", + "classification": "CONDITIONAL_DEVELOPMENT", + "status": "CONDITIONALLY_DEFERRED" + }, + { + "id": "CI-01", + "description": "Hosted MariaDB remains quarantined; current runner isolation/lifecycle is unverified and no hosted cases are qualified.", + "evidence": [ + "docs/redesign/phase-9/p9-sec-02/CI_ASSESSMENT.md", + ".gitea/workflows/mariadb-integration.yml" + ], + "severity": "HIGH", + "acceptanceCriterion": "Hosted provider and infrastructure isolation evidence", + "requiredAction": "Provision dedicated nonproduction runner/daemon and native private service; prove merged HostConfig/egress/secret boundaries plus success/fail/cancel/crash cleanup, then reviewed enabling change and actual hosted execution. Do not bypass unconditional workflow guard.", + "blockingPhase": [ + "HOSTED_CI_ACCEPTANCE", + "PRODUCTION", + "AUTOMATION: if hosted lane required" + ], + "responsibleParty": "CI infrastructure operator", + "deferralAuthority": "P9-SEC-02 CI-M01 allows operator-blocked hosted CI while independent local qualification continues; does not qualify controller execution.", + "classification": "CONDITIONAL_DEVELOPMENT", + "status": "BLOCKED" + }, + { + "id": "MYSQL-TLS-01", + "description": "MySqlConnector2.4.0 has the retained moderate GHSA-473q-m89c-ghf8 advisory; production TLS configuration was not inspected.", + "evidence": [ + "docs/pre-phase10-ux/DEPENDENCY_AUDIT.md" + ], + "severity": "MODERATE", + "acceptanceCriterion": "Current dependency/reachability disposition; no accepted residual security risk", + "requiredAction": "Qualify >=2.6.1 or the documented trusted-CA mitigation; verify actual affected TLS configuration and rerun MariaDB/RD21. Isolated loopback SslMode=None evidence is not production TLS acceptance.", + "blockingPhase": [ + "PRODUCTION_SECURITY_RELEASE" + ], + "responsibleParty": "Database/security release owner", + "deferralAuthority": null, + "classification": "PRODUCTION_ONLY", + "status": "BLOCKED" + }, + { + "id": "OPS-01", + "description": "Production filesystem integrity, independent off-disk restore/rollback, deployed identity/cache/monitoring and recovery evidence remain unverified.", + "evidence": [ + "docs/redesign/phase-9/p9-sec-02/ACCEPTANCE_ADDENDUM_2026-10-25.md" + ], + "severity": "CRITICAL", + "acceptanceCriterion": "Independent infrastructure, backup, recovery and release acceptance", + "requiredAction": "Complete independent operator verification and release approval on authorised infrastructure; do not perform production repairs, DB operations or service/cache changes from this handoff.", + "blockingPhase": [ + "PRODUCTION" + ], + "responsibleParty": "Production operator / release owner", + "deferralAuthority": null, + "classification": "PRODUCTION_ONLY", + "status": "BLOCKED" + }, + { + "id": "NATIVE-SEC-01", + "description": "Native parser/decoder fuzzing, whole-image review and applicable Windows memory enforcement remain outside the qualified bounded fixture evidence.", + "evidence": [ + "docs/pre-phase10-ux/SECURITY_REVIEW.md" + ], + "severity": "HIGH", + "acceptanceCriterion": "Secure bounded untrusted document processing", + "requiredAction": "Qualify native resource/isolation/security boundaries; retain page/file/time/child/container admission limits and privacy/retention cleanup.", + "blockingPhase": [ + "PRODUCTION_UNTRUSTED_DOCUMENT_PROCESSING" + ], + "responsibleParty": "Security / runtime owner", + "deferralAuthority": null, + "classification": "PRODUCTION_ONLY", + "status": "BLOCKED" + }, + { + "id": "FUTURE-01", + "description": "Separate P5-13/C11, LinkedIn, Android, SQLite retirement, MariaDB upgrade, monitoring and country initiatives remain tracked future work.", + "evidence": [ + "ROADMAP.md" + ], + "severity": "INFORMATIONAL", + "acceptanceCriterion": "No silent backlog loss or unrelated implementation", + "requiredAction": "Retain initiative-specific entry decisions and dependencies; do not activate withheld features, remove compatibility or perform major upgrades during cleanup.", + "blockingPhase": [ + "SEPARATE_AUTHORISED_WORKSTREAMS" + ], + "responsibleParty": "Product / initiative owners", + "deferralAuthority": null, + "classification": "FUTURE_FEATURE", + "status": "OPEN" + }, + { + "id": "AI-CONTEXT-01", + "description": "Generic strategy admission still requires legacy ProfileCvText; successful reviewed structured import alone does not establish that precondition.", + "evidence": ["AI_RESULTS.md", "JobTrackerApi/Services/StrategySnapshotService.cs", "JobTrackerApi/Controllers/ProfileCvController.Import.cs"], + "severity": "MODERATE", + "acceptanceCriterion": "Do not claim canonical-only import to generic AI compatibility without exercising it", + "requiredAction": "Assess canonical-only generic-AI source compatibility during Product Review. Preserve existing consent/source contracts; never silently fill legacy text from unreviewed uploads. The current successful smoke explicitly supplies separately authored fictional CV text.", + "blockingPhase": ["GENERIC_AI_FROM_CANONICAL_ONLY_PROFILE_CLAIM"], + "responsibleParty": "Product / AI integration owner", + "deferralAuthority": null, + "classification": "FUTURE_FEATURE", + "status": "OPEN" + }, + { + "id": "AUTO-SCOPE-01", + "description": "The committed controller policy has stage entry/review approvals but no explicit protected candidate-scope checkpoint after an assessment-only Phase10 entry.", + "evidence": ["CONTRACT.md", "GATES.json", "CLEANUP_INVENTORY.md"], + "severity": "HIGH", + "acceptanceCriterion": "Concrete owner-approved candidate scope before cleanup implementation", + "requiredAction": "Bind a full entry approval to already-proven exact candidates, or use the controller's signed policy update to stop after assessment and require a protected candidate-specific-cleanup-scope decision before removal. Do not treat assessment-only approval or worker-written evidence as deletion authority.", + "blockingPhase": ["AUTOMATIC_PHASE-10_CLEANUP_IMPLEMENTATION"], + "responsibleParty": "Owner / AUTONOMOUS-ROADMAP-01 policy maintainer", + "deferralAuthority": null, + "classification": "MANDATORY_ENTRY", + "status": "BLOCKED" + }, + { + "id": "GIT-RECOVERY-01", + "description": "The originally pending caa0c6a and5032ccb publication was recovered and independently read back.", + "evidence": [ + "AUTHORITY.md" + ], + "severity": "HIGH", + "acceptanceCriterion": "Clean directly verified remote baseline", + "requiredAction": "Reverify exact final local/remote HEAD after publishing the finished package; normal push only. GJ-00 was independently verified without modifying/merging it.", + "blockingPhase": [ + "PHASE-10: final published baseline" + ], + "responsibleParty": "Git integration owner", + "deferralAuthority": null, + "classification": "MANDATORY_ENTRY", + "status": "CLOSED" + } + ] +} diff --git a/docs/automation/handoffs/pre-phase10/CONTRACT.md b/docs/automation/handoffs/pre-phase10/CONTRACT.md new file mode 100644 index 0000000..6297395 --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/CONTRACT.md @@ -0,0 +1,28 @@ +# Proposed evidence adapter v1 + +Contract ID: `urn:jobjakt:pre-phase10-evidence:1`. This is a **proposed evidence import contract**, not a replacement for AUTONOMOUS-ROADMAP-01's committed `automation/schemas/backlog.schema.json` or `result.schema.json`. Both happen to use version1; their document kinds and authority are different. The separate controller snapshot is recorded in GATES.json. Its worktree/policy/state/runtime was not modified or executed. + +| Package field | Existing controller integration | +|---|---| +| ACCEPTANCE.localCommit | Frozen application/test baseline; independently prove ancestry and application-source equality for the resolved final package commit. Never assume the capture-time remote observation is current | +| ACCEPTANCE.snapshotHead / verifiedRemoteCommit | Dated provenance only. Resolve final branch HEAD again, require clean local/remote equality, and bind the protected entry request to that actual hash | +| TEST_EVIDENCE native report/process/source artifacts | Recompute compressed-file hashes, decompress with a strict bound, parse native identities/counters and process exits. Source before/after must agree. Verify all expected ordinary discovery identities exactly once; retain separate lanes and original failures | +| GATES stage IDs / predecessor / manualApprovals | Projection of the existing seven stages05–11 and their protected approval identifiers. Do not insert this evidence package as a second executable queue or enable execution from it | +| BLOCKERS classification / blockingPhase | Scope-dependent entry, conditional development debt, production and future work. Neither a conditional result nor a closed unrelated blocker satisfies a mandatory candidate condition | +| requiredOwnerApprovals | Requests for external protected owner decisions, not records that approval occurred. This package contains no approval token, signature or private key | +| packageStatus READY | All required evidence/documentation is present and schema-consistent. It says nothing about approval to start Phase10 | +| phase10DevelopmentReadiness NO-GO / eligibleForAutomaticExecution false | Current authoritative entry decision. The controller must remain blocked pending actual protected approvals, candidate proof, publication and runtime/test-adapter qualification | + +The controller's existing `result.schema.json` uses outcomes such as blocked/conditional/complete and blocker/approval/checkpoint fields. A valid handoff with this entry decision maps to **blocked** for Phase10; do not translate validator exit0 into `complete` or a satisfied stage requirement. No result payload can sign its own authority. The controller must independently verify real predecessor acceptance and perform its protected `phase10-development-entry` and stage-review flow. + +The current manifest has no declared checkpoint deferrable gates. Human release debt and disabled optional CV AI have individual historical conditional-development authority, but importing that debt does not authorise automatic advancement. A policy change and any actual conditional-deferral must use the controller's owner-controlled signed request process. Required automated failures remain failures. Preserve actual S01 failures and isolated model rejections. + +The controller snapshot also has no explicit protected candidate-scope checkpoint between an assessment-only entry and removal. The proposed GATES contract adds `candidate-specific-cleanup-scope` as a source-derived requirement, not as a claim that the live manifest already enforces it. Either the entry grant must already name proven exact candidates, or the operator must adopt a signed policy update that stops after assessment and requires that protected decision before cleanup implementation. This workstream cannot add that hook in the separate worktree. AUTO-SCOPE-01 stays BLOCKED. + +## Portable evidence + +Native test reports, process observations and source manifests are stored as individually compressed `.gz` files under `evidence/` with exact hashes in TEST_EVIDENCE.json. Native XML/JSON contents are preserved, not rewritten to improve results. The local raw `.artifacts/automation-handoff-01/` evidence remains separately available; large videos, traces, model weights and document corpora are not imported into this package. Visual review uses its separately indexed synthetic comparison package. + +The package verifier only reads bounded local files/Git and optionally verifies the configured remote. It does not execute report commands, install dependencies, run a controller, inspect protected approval keys or grant readiness. Installed pinned Ajv/jsdom from the existing frontend dev dependency tree provide actual JSON Schema/XML validation; no dependency was added. External consumers may use their own qualified parsers and must not trust this model-writable verifier as their security boundary. + +At consumption, require a clean authorised checkout containing the final published package, verify hashes/source/ancestry, and independently run the controller's actual qualified test adapter. Hold protected authority and expected policy/report hashes outside model-writable repository state. If the adapter, signatures, runtime boundary or report transport is unavailable, remain BLOCKED. Do not weaken gates, issue self-approval or edit another worktree as an integration shortcut. diff --git a/docs/automation/handoffs/pre-phase10/GATES.json b/docs/automation/handoffs/pre-phase10/GATES.json new file mode 100644 index 0000000..05dc2a2 --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/GATES.json @@ -0,0 +1,278 @@ +{ + "schemaVersion": 1, + "workstreamId": "AUTOMATION-HANDOFF-01", + "kind": "GATES", + "contractStatus": "PROPOSED_EVIDENCE_ADAPTER_NOT_EXECUTABLE_POLICY", + "controllerCommit": "c1663df44ca54eb1e6fad8facfcbc2d5eb5db8c8", + "controllerFiles": [ + "automation/backlog.json", + "automation/schemas/backlog.schema.json", + "automation/schemas/result.schema.json", + "docs/automation/GATES.md" + ], + "executionEnabledByThisPackage": false, + "externalApprovalPolicy": "Use existing protected RSA/SHA256 owner-SID/request-hash/expiry binding. Bind resolved final baseline, candidate scope, policy/prompt and artifact hashes. No signatures/tokens are created here; all current checkpoint deferrableGates are empty. Any policy update/conditional-deferral requires the controller signed process.", + "stages": [ + { + "id": "PHASE-10", + "sequence": 5, + "requiredPredecessor": [ + "AUTOMATION-HANDOFF-01 accepted entry and protected owner decision" + ], + "requiredTestSuites": [ + "Fresh applicable .NET, React, browser/contracts/import, MariaDB/RD21, Python/Docling, native PDF, type/lint/build/security/preservation lanes", + "Stage-specific requirements and independent source-requirements review" + ], + "minimumEvidence": [ + "Native nonempty reports and command exits; source/commit/image binding; expected test membership; zero hidden failures/skips/retries", + "Original failures retained; actual cleanup and old-data/route compatibility; human/provider/model results separate" + ], + "requiredGitState": [ + "Exact approved published baseline ancestry", + "Clean authorised feature checkout; normal push and independent exact remote HEAD readback", + "No main merge, force push or deployment" + ], + "preservationChecks": [ + "All57 original criteria retain status and scope; all33 old routes plus admin processing route", + "Canonical Career Profile, CV overrides/frozen versions, letters, applications, auth/tenant and RD21 contracts", + "Candidate-specific caller/old-data/rollback proof and unchanged PDF/font oracles" + ], + "manualApprovals": [ + "phase10-development-entry", + "stage-requirements-review", + "candidate-specific-cleanup-scope" + ], + "permissibleConditionalDeferrals": [], + "blockingFindings": [ + "Missing predecessor or protected approval", + "Unqualified runtime/test adapter or missing/wrong-source report", + "Unpublished commit; failed mandatory test; undispositioned affected compatibility or security finding", + "Missing protected candidate-scope decision before removal; assessment-only entry cannot authorise deletions" + ] + }, + { + "id": "PRODUCT-REVIEW-01", + "sequence": 6, + "requiredPredecessor": [ + "PHASE-10" + ], + "requiredTestSuites": [ + "Fresh applicable .NET, React, browser/contracts/import, MariaDB/RD21, Python/Docling, native PDF, type/lint/build/security/preservation lanes", + "Stage-specific requirements and independent source-requirements review" + ], + "minimumEvidence": [ + "Native nonempty reports and command exits; source/commit/image binding; expected test membership; zero hidden failures/skips/retries", + "Original failures retained; actual cleanup and old-data/route compatibility; human/provider/model results separate" + ], + "requiredGitState": [ + "Exact approved published baseline ancestry", + "Clean authorised feature checkout; normal push and independent exact remote HEAD readback", + "No main merge, force push or deployment" + ], + "preservationChecks": [ + "All57 original criteria retain status and scope; all33 old routes plus admin processing route", + "Canonical Career Profile, CV overrides/frozen versions, letters, applications, auth/tenant and RD21 contracts", + "Candidate-specific caller/old-data/rollback proof and unchanged PDF/font oracles" + ], + "manualApprovals": [ + "product-ranked-scope", + "stage-requirements-review" + ], + "permissibleConditionalDeferrals": [], + "blockingFindings": [ + "Missing predecessor or protected approval", + "Unqualified runtime/test adapter or missing/wrong-source report", + "Unpublished commit; failed mandatory test; undispositioned affected compatibility or security finding" + ] + }, + { + "id": "INT-GLOBAL-JOBS-01", + "sequence": 7, + "requiredPredecessor": [ + "PRODUCT-REVIEW-01" + ], + "requiredTestSuites": [ + "Fresh applicable .NET, React, browser/contracts/import, MariaDB/RD21, Python/Docling, native PDF, type/lint/build/security/preservation lanes", + "Stage-specific requirements and independent source-requirements review" + ], + "minimumEvidence": [ + "Native nonempty reports and command exits; source/commit/image binding; expected test membership; zero hidden failures/skips/retries", + "Original failures retained; actual cleanup and old-data/route compatibility; human/provider/model results separate" + ], + "requiredGitState": [ + "Exact approved published baseline ancestry", + "Clean authorised feature checkout; normal push and independent exact remote HEAD readback", + "No main merge, force push or deployment" + ], + "preservationChecks": [ + "All57 original criteria retain status and scope; all33 old routes plus admin processing route", + "Canonical Career Profile, CV overrides/frozen versions, letters, applications, auth/tenant and RD21 contracts", + "Candidate-specific caller/old-data/rollback proof and unchanged PDF/font oracles" + ], + "manualApprovals": [ + "global-jobs-implementation", + "product-ranked-scope", + "provider-licences-and-display-rights", + "stage-requirements-review" + ], + "permissibleConditionalDeferrals": [], + "blockingFindings": [ + "Missing predecessor or protected approval", + "Unqualified runtime/test adapter or missing/wrong-source report", + "Unpublished commit; failed mandatory test; undispositioned affected compatibility or security finding" + ] + }, + { + "id": "I18N-01", + "sequence": 8, + "requiredPredecessor": [ + "INT-GLOBAL-JOBS-01" + ], + "requiredTestSuites": [ + "Fresh applicable .NET, React, browser/contracts/import, MariaDB/RD21, Python/Docling, native PDF, type/lint/build/security/preservation lanes", + "Stage-specific requirements and independent source-requirements review" + ], + "minimumEvidence": [ + "Native nonempty reports and command exits; source/commit/image binding; expected test membership; zero hidden failures/skips/retries", + "Original failures retained; actual cleanup and old-data/route compatibility; human/provider/model results separate" + ], + "requiredGitState": [ + "Exact approved published baseline ancestry", + "Clean authorised feature checkout; normal push and independent exact remote HEAD readback", + "No main merge, force push or deployment" + ], + "preservationChecks": [ + "All57 original criteria retain status and scope; all33 old routes plus admin processing route", + "Canonical Career Profile, CV overrides/frozen versions, letters, applications, auth/tenant and RD21 contracts", + "Candidate-specific caller/old-data/rollback proof and unchanged PDF/font oracles" + ], + "manualApprovals": [ + "human-linguistic-and-market-qualification", + "i18n-scope", + "stage-requirements-review" + ], + "permissibleConditionalDeferrals": [], + "blockingFindings": [ + "Missing predecessor or protected approval", + "Unqualified runtime/test adapter or missing/wrong-source report", + "Unpublished commit; failed mandatory test; undispositioned affected compatibility or security finding" + ] + }, + { + "id": "LAUNCH-SITE-01", + "sequence": 9, + "requiredPredecessor": [ + "I18N-01" + ], + "requiredTestSuites": [ + "Fresh applicable .NET, React, browser/contracts/import, MariaDB/RD21, Python/Docling, native PDF, type/lint/build/security/preservation lanes", + "Stage-specific requirements and independent source-requirements review" + ], + "minimumEvidence": [ + "Native nonempty reports and command exits; source/commit/image binding; expected test membership; zero hidden failures/skips/retries", + "Original failures retained; actual cleanup and old-data/route compatibility; human/provider/model results separate" + ], + "requiredGitState": [ + "Exact approved published baseline ancestry", + "Clean authorised feature checkout; normal push and independent exact remote HEAD readback", + "No main merge, force push or deployment" + ], + "preservationChecks": [ + "All57 original criteria retain status and scope; all33 old routes plus admin processing route", + "Canonical Career Profile, CV overrides/frozen versions, letters, applications, auth/tenant and RD21 contracts", + "Candidate-specific caller/old-data/rollback proof and unchanged PDF/font oracles" + ], + "manualApprovals": [ + "homepage-design-selection", + "stage-requirements-review" + ], + "permissibleConditionalDeferrals": [], + "blockingFindings": [ + "Missing predecessor or protected approval", + "Unqualified runtime/test adapter or missing/wrong-source report", + "Unpublished commit; failed mandatory test; undispositioned affected compatibility or security finding" + ] + }, + { + "id": "SECURITY-AUDIT-01", + "sequence": 10, + "requiredPredecessor": [ + "LAUNCH-SITE-01" + ], + "requiredTestSuites": [ + "Fresh applicable .NET, React, browser/contracts/import, MariaDB/RD21, Python/Docling, native PDF, type/lint/build/security/preservation lanes", + "Stage-specific requirements and independent source-requirements review" + ], + "minimumEvidence": [ + "Native nonempty reports and command exits; source/commit/image binding; expected test membership; zero hidden failures/skips/retries", + "Original failures retained; actual cleanup and old-data/route compatibility; human/provider/model results separate" + ], + "requiredGitState": [ + "Exact approved published baseline ancestry", + "Clean authorised feature checkout; normal push and independent exact remote HEAD readback", + "No main merge, force push or deployment" + ], + "preservationChecks": [ + "All57 original criteria retain status and scope; all33 old routes plus admin processing route", + "Canonical Career Profile, CV overrides/frozen versions, letters, applications, auth/tenant and RD21 contracts", + "Candidate-specific caller/old-data/rollback proof and unchanged PDF/font oracles" + ], + "manualApprovals": [ + "isolated-adversarial-targets", + "material-security-findings-disposition", + "security-test-environment-and-scope", + "stage-requirements-review" + ], + "permissibleConditionalDeferrals": [], + "blockingFindings": [ + "Missing predecessor or protected approval", + "Unqualified runtime/test adapter or missing/wrong-source report", + "Unpublished commit; failed mandatory test; undispositioned affected compatibility or security finding" + ] + }, + { + "id": "RELEASE-READINESS-01", + "sequence": 11, + "requiredPredecessor": [ + "SECURITY-AUDIT-01" + ], + "requiredTestSuites": [ + "Fresh applicable .NET, React, browser/contracts/import, MariaDB/RD21, Python/Docling, native PDF, type/lint/build/security/preservation lanes", + "Stage-specific requirements and independent source-requirements review" + ], + "minimumEvidence": [ + "Native nonempty reports and command exits; source/commit/image binding; expected test membership; zero hidden failures/skips/retries", + "Original failures retained; actual cleanup and old-data/route compatibility; human/provider/model results separate" + ], + "requiredGitState": [ + "Exact approved published baseline ancestry", + "Clean authorised feature checkout; normal push and independent exact remote HEAD readback", + "No main merge, force push or deployment" + ], + "preservationChecks": [ + "All57 original criteria retain status and scope; all33 old routes plus admin processing route", + "Canonical Career Profile, CV overrides/frozen versions, letters, applications, auth/tenant and RD21 contracts", + "Candidate-specific caller/old-data/rollback proof and unchanged PDF/font oracles" + ], + "manualApprovals": [ + "release-evidence-review", + "stage-requirements-review" + ], + "permissibleConditionalDeferrals": [], + "blockingFindings": [ + "Missing predecessor or protected approval", + "Unqualified runtime/test adapter or missing/wrong-source report", + "Unpublished commit; failed mandatory test; undispositioned affected compatibility or security finding" + ] + } + ], + "separateInitiatives": [ + "P5-13/C11 AI qualification and model assessment", + "LinkedIn feasibility", + "Android application", + "SQLite retirement", + "MariaDB upgrade strategy", + "Monitoring and operational improvements", + "Future country integrations" + ] +} diff --git a/docs/automation/handoffs/pre-phase10/HANDOFF_SCHEMA.json b/docs/automation/handoffs/pre-phase10/HANDOFF_SCHEMA.json new file mode 100644 index 0000000..d7647f7 --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/HANDOFF_SCHEMA.json @@ -0,0 +1,119 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "urn:jobjakt:pre-phase10-evidence:1", + "title": "Proposed pre-Phase10 evidence contract v1; not an execution or approval policy", + "oneOf": [ + { "$ref": "#/definitions/acceptance" }, + { "$ref": "#/definitions/gates" }, + { "$ref": "#/definitions/blockers" }, + { "$ref": "#/definitions/evidence" } + ], + "definitions": { + "sha": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, + "commit": { "type": "string", "pattern": "^[a-f0-9]{40}$" }, + "strings": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }, + "commonVersion": { "const": 1 }, + "workstream": { "const": "AUTOMATION-HANDOFF-01" }, + "status": { "enum": ["GO", "CONDITIONAL GO", "NO-GO", "PASS", "PARTIAL", "FAIL", "BLOCKED", "NOT TESTED", "CONDITIONAL", "VERIFIED", "READY", "INCOMPLETE"] }, + "counts": { + "type": "object", "additionalProperties": false, + "required": ["passed", "failed", "skipped", "retries", "unexecuted"], + "properties": { + "passed": { "type": "integer", "minimum": 0 }, "failed": { "type": "integer", "minimum": 0 }, + "skipped": { "type": "integer", "minimum": 0 }, "retries": { "type": "integer", "minimum": 0 }, + "unexecuted": { "type": "integer", "minimum": 0 } + } + }, + "verdict": { + "type": "object", "additionalProperties": false, "required": ["criterion", "status", "evidence", "limits"], + "properties": { "criterion": { "type": "string" }, "status": { "$ref": "#/definitions/status" }, "evidence": { "$ref": "#/definitions/strings" }, "limits": { "type": "string", "minLength": 1 } } + }, + "approval": { + "type": "object", "additionalProperties": false, "required": ["id", "state", "authority"], + "properties": { "id": { "type": "string" }, "state": { "const": "NOT_PROVIDED_TO_HANDOFF" }, "authority": { "const": "EXTERNAL_PROTECTED_CONTROLLER_APPROVAL" } } + }, + "acceptance": { + "type": "object", "additionalProperties": false, + "required": ["schemaVersion", "workstreamId", "kind", "authority", "sourceBranch", "localCommit", "localCommitMeaning", "snapshotHead", "verifiedRemoteCommit", "remoteObservation", "worktreeCleanliness", "acceptanceStatus", "entryGateStatus", "phase10DevelopmentReadiness", "eligibleForAutomaticExecution", "packageStatus", "verdicts", "testEvidenceReferences", "unresolvedBlockerIds", "permissibleDeferrals", "requiredOwnerApprovals", "generatedUtc", "recommendation"], + "properties": { + "schemaVersion": { "$ref": "#/definitions/commonVersion" }, "workstreamId": { "$ref": "#/definitions/workstream" }, "kind": { "const": "ACCEPTANCE" }, + "authority": { "const": "EVIDENCE_ONLY" }, "sourceBranch": { "const": "test/pre-phase10-ux-acceptance" }, + "localCommit": { "$ref": "#/definitions/commit" }, "localCommitMeaning": { "const": "FROZEN_TESTED_APPLICATION_BASELINE" }, + "snapshotHead": { "$ref": "#/definitions/commit" }, "verifiedRemoteCommit": { "anyOf": [{ "$ref": "#/definitions/commit" }, { "type": "null" }] }, + "remoteObservation": { "type": "string", "minLength": 1 }, + "worktreeCleanliness": { "type": "object", "additionalProperties": false, "required": ["atSourceBaseline", "atPackageGeneration", "requiredAtConsumption"], "properties": { "atSourceBaseline": { "const": "CLEAN" }, "atPackageGeneration": { "enum": ["CLEAN", "HANDOFF_FILES_ONLY"] }, "requiredAtConsumption": { "const": "CLEAN" } } }, + "acceptanceStatus": { "const": "CONDITIONAL GO" }, "entryGateStatus": { "const": "BLOCKED" }, + "phase10DevelopmentReadiness": { "const": "NO-GO" }, "eligibleForAutomaticExecution": { "const": false }, + "packageStatus": { "enum": ["READY", "INCOMPLETE"] }, "verdicts": { "type": "array", "minItems": 12, "items": { "$ref": "#/definitions/verdict" } }, + "testEvidenceReferences": { "$ref": "#/definitions/strings" }, "unresolvedBlockerIds": { "$ref": "#/definitions/strings" }, + "permissibleDeferrals": { "$ref": "#/definitions/strings" }, "requiredOwnerApprovals": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/approval" } }, + "generatedUtc": { "type": "string", "format": "date-time" }, "recommendation": { "type": "string", "minLength": 1 } + } + }, + "stage": { + "type": "object", "additionalProperties": false, + "required": ["id", "sequence", "requiredPredecessor", "requiredTestSuites", "minimumEvidence", "requiredGitState", "preservationChecks", "manualApprovals", "permissibleConditionalDeferrals", "blockingFindings"], + "properties": { + "id": { "type": "string" }, "sequence": { "type": "integer", "minimum": 5, "maximum": 11 }, + "requiredPredecessor": { "$ref": "#/definitions/strings" }, "requiredTestSuites": { "$ref": "#/definitions/strings" }, + "minimumEvidence": { "$ref": "#/definitions/strings" }, "requiredGitState": { "$ref": "#/definitions/strings" }, + "preservationChecks": { "$ref": "#/definitions/strings" }, "manualApprovals": { "$ref": "#/definitions/strings" }, + "permissibleConditionalDeferrals": { "$ref": "#/definitions/strings" }, "blockingFindings": { "$ref": "#/definitions/strings" } + } + }, + "gates": { + "type": "object", "additionalProperties": false, + "required": ["schemaVersion", "workstreamId", "kind", "contractStatus", "controllerCommit", "controllerFiles", "executionEnabledByThisPackage", "externalApprovalPolicy", "stages", "separateInitiatives"], + "properties": { + "schemaVersion": { "$ref": "#/definitions/commonVersion" }, "workstreamId": { "$ref": "#/definitions/workstream" }, "kind": { "const": "GATES" }, + "contractStatus": { "const": "PROPOSED_EVIDENCE_ADAPTER_NOT_EXECUTABLE_POLICY" }, "controllerCommit": { "$ref": "#/definitions/commit" }, + "controllerFiles": { "$ref": "#/definitions/strings" }, "executionEnabledByThisPackage": { "const": false }, + "externalApprovalPolicy": { "type": "string", "minLength": 1 }, "stages": { "type": "array", "minItems": 7, "maxItems": 7, "items": { "$ref": "#/definitions/stage" } }, + "separateInitiatives": { "$ref": "#/definitions/strings" } + } + }, + "blocker": { + "type": "object", "additionalProperties": false, + "required": ["id", "description", "evidence", "severity", "acceptanceCriterion", "requiredAction", "blockingPhase", "responsibleParty", "deferralAuthority", "classification", "status"], + "properties": { + "id": { "type": "string", "pattern": "^[A-Z][A-Z0-9-]+$" }, "description": { "type": "string", "minLength": 1 }, "evidence": { "$ref": "#/definitions/strings" }, + "severity": { "enum": ["CRITICAL", "HIGH", "MODERATE", "LOW", "INFORMATIONAL"] }, "acceptanceCriterion": { "type": "string" }, + "requiredAction": { "type": "string", "minLength": 1 }, "blockingPhase": { "$ref": "#/definitions/strings" }, "responsibleParty": { "type": "string", "minLength": 1 }, + "deferralAuthority": { "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] }, + "classification": { "enum": ["MANDATORY_ENTRY", "CONDITIONAL_DEVELOPMENT", "PRODUCTION_ONLY", "FUTURE_FEATURE"] }, + "status": { "enum": ["OPEN", "BLOCKED", "CONDITIONALLY_DEFERRED", "CLOSED"] } + } + }, + "blockers": { + "type": "object", "additionalProperties": false, "required": ["schemaVersion", "workstreamId", "kind", "items"], + "properties": { "schemaVersion": { "$ref": "#/definitions/commonVersion" }, "workstreamId": { "$ref": "#/definitions/workstream" }, "kind": { "const": "BLOCKERS" }, "items": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/blocker" } } } + }, + "artifact": { + "type": "object", "additionalProperties": false, "required": ["id", "path", "sha256", "description"], + "properties": { "id": { "type": "string" }, "path": { "type": "string", "minLength": 1 }, "sha256": { "$ref": "#/definitions/sha" }, "description": { "type": "string" } } + }, + "report": { + "type": "object", "additionalProperties": false, + "required": ["id", "bindingScope", "sourceCommit", "executedFromCommit", "status", "exitCode", "artifactId", "processArtifactId", "processPointer", "nativeFormat", "counts", "membershipSha256", "limits"], + "properties": { + "id": { "type": "string" }, "bindingScope": { "enum": ["APPLICATION", "HANDOFF_VERIFIER"] }, "sourceCommit": { "$ref": "#/definitions/commit" }, "executedFromCommit": { "$ref": "#/definitions/commit" }, + "status": { "enum": ["PASS", "PARTIAL", "FAIL", "BLOCKED", "METADATA"] }, "exitCode": { "type": "integer" }, + "artifactId": { "type": "string" }, "processArtifactId": { "type": "string" }, "processPointer": { "type": "string", "pattern": "^/" }, + "nativeFormat": { "enum": ["trx", "junit", "jest", "playwright", "pytest", "unittest", "node-test", null] }, + "counts": { "$ref": "#/definitions/counts" }, "membershipSha256": { "$ref": "#/definitions/sha" }, "limits": { "type": "string", "minLength": 1 } + } + }, + "evidence": { + "type": "object", "additionalProperties": false, + "required": ["schemaVersion", "workstreamId", "kind", "testedCommit", "verifierCommit", "verifierSourceArtifactId", "sourceManifestArtifactId", "sourceAfterArtifactId", "ordinaryDiscoveryArtifactId", "ordinaryReportIds", "artifacts", "reports", "historicalEvidence", "environment", "notRun", "generatedUtc"], + "properties": { + "schemaVersion": { "$ref": "#/definitions/commonVersion" }, "workstreamId": { "$ref": "#/definitions/workstream" }, "kind": { "const": "TEST_EVIDENCE" }, + "testedCommit": { "$ref": "#/definitions/commit" }, "sourceManifestArtifactId": { "type": "string" }, "sourceAfterArtifactId": { "type": "string" }, + "verifierCommit": { "$ref": "#/definitions/commit" }, "verifierSourceArtifactId": { "type": "string" }, + "ordinaryDiscoveryArtifactId": { "type": "string" }, "ordinaryReportIds": { "$ref": "#/definitions/strings" }, + "artifacts": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/artifact" } }, "reports": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/report" } }, + "historicalEvidence": { "$ref": "#/definitions/strings" }, "environment": { "$ref": "#/definitions/strings" }, "notRun": { "$ref": "#/definitions/strings" }, "generatedUtc": { "type": "string", "format": "date-time" } + } + } + } +} diff --git a/docs/automation/handoffs/pre-phase10/MANUAL_ACCEPTANCE.md b/docs/automation/handoffs/pre-phase10/MANUAL_ACCEPTANCE.md index 8e4610c..87848cf 100644 --- a/docs/automation/handoffs/pre-phase10/MANUAL_ACCEPTANCE.md +++ b/docs/automation/handoffs/pre-phase10/MANUAL_ACCEPTANCE.md @@ -1,6 +1,6 @@ # Prioritised owner acceptance -All human rows are **NOT TESTED** until the owner supplies actual evidence through the protected approval mechanism. Do not commit approval tokens/signatures or personal CVs. Use fictional data and http://jobbjakt.local; admin scenarios require an existing Admin account, AI scenarios require consent/entitlement. Capture date, exact source/image, device/OS/browser/assistive technology, steps, result and synthetic-only screenshot/PDF where appropriate. Never include passwords, cookies or personal documents. +All human rows are **NOT TESTED** until the owner supplies actual evidence through the protected approval mechanism. Do not commit approval tokens/signatures or personal CVs. Use fictional data and http://jobbjakt.local; admin scenarios require an existing Admin account, AI scenarios require consent/entitlement and the workflow's existing CV-text precondition. For revised spacing, use a new CV or explicitly Apply the updated design v2; historical v1 designs remain unchanged. Capture date, exact source/image, device/OS/browser/assistive technology, steps, result and synthetic-only screenshot/PDF where appropriate. Never include passwords, cookies or personal documents. | ID / priority | Workflow and preconditions | Steps and expected pass criterion | Evidence and gate | |---|---|---|---| diff --git a/docs/automation/handoffs/pre-phase10/PHASE10_BASELINE.md b/docs/automation/handoffs/pre-phase10/PHASE10_BASELINE.md new file mode 100644 index 0000000..6f3ebda --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/PHASE10_BASELINE.md @@ -0,0 +1,25 @@ +# Exact Phase10 assessment baseline + +Application baseline: **5032ccb41514807c8ca3008c24ca6326be1170de**, branch **test/pre-phase10-ux-acceptance**, remote origin `https://git.cesnimda.uk/cesnimda/jobtrackingapp.git`. It contains CV-UX4a0af62, CV-QA4a8c907, A–D3255da9 and the structured-strategy correctioncaa0c6a. All four ancestry checks were rerun successfully in this workstream. Do not base cleanup on main. + +The handoff checkpoint8804231be4e7c309a62d9d6e7d07c9ae0809bc3c was normally pushed and independently read back. Later handoff commits must also be published and verified. The **final integration ref is the resolved clean published HEAD containing this package**; obtain its exact hash with Git and bind the protected owner decision to it. A file cannot contain its own Git commit hash. ACCEPTANCE.json therefore distinguishes the frozen tested application baseline, capture-time HEAD/remote observation and required current consumption checks. Documentation-only descendants are bounded to `docs/automation/handoffs/pre-phase10/`; application or existing-test changes invalidate that shortcut and require fresh affected evidence. + +The separate controller snapshot is c1663df44ca54eb1e6fad8facfcbc2d5eb5db8c8, based on5032ccb. Its branch is not modified here. The operator must use its existing signed policy-update/configure process to adopt the final approved integration baseline/context artifacts **before real execution**, qualify its runtime/test adapter and obtain the required entry approval. Do not edit its policy silently or run another controller. No baseline replacement after started work is authorised by this package. + +GJ-00 planning local/remote0ec9f98e6ed4a646fc5e017d8eb6fade07653f37 is separately verified. Relative to5032ccb, the integration and planning branches have18 and2 unique commits respectively. Neither is a safe blind replacement for the other. No merge/cherry-pick was performed. Future authorised integration must reconcile the planning documents against the later accepted application source. + +## Preservation contract + +Retain all57 original capability groups and their existing56PARTIAL/oneDEFERRED qualification states. Preserve the33 original routes plus `/admin/processing` (34 current source routes), including legacy aliases. Route membership is only a source check, not full behavior acceptance. Keep the original criteria rather than promoting them from new unit/browser results. + +Career Profile stays canonical; null-as-inherit overrides, explicit blank flags, per-CV customisation, frozen/submitted packages, letter/application versions, tenant/owner filters, durable operation state, transactional profile application and RD21 expected-version/rollback/retry contracts remain active. Do not reinterpret creation-intent idempotency as proven: the earlier provider observation explicitly records repeated creation bodies as non-idempotent. + +Keep design-version1 rendering for existing/historical CVs; v2 is explicit. Keep old-run import review/accept DTOs and routes. Keep SQLite compatibility/migrations pending separately approved retirement; no MariaDB major upgrade. Preserve licensed fonts, unchanged original PDF goldens and all recorded S01 failures. Keep disabled C11/P5-13/model interpretation withheld. + +## Scope and compatibility checks + +[CLEANUP_INVENTORY.md](CLEANUP_INVENTORY.md) contains concrete current consumers and risks. **No product removal is approved or proven unused.** The safe next activity is candidate assessment and owner review; implementation needs the independent entry decision. Each proposed candidate must name exact symbols/routes/replacement/consumers, old-data and dynamic-reference risks, affected preservation IDs, rollback and focused proof. Then run applicable full backend/frontend/browser/contracts/import/MariaDB/RD21/Python/security/native Windows/Linux PDF/type/lint/build checks with native identities and exits. + +The current native/Node/browser producer commands and source/process identities are retained in the portable TEST_EVIDENCE package. Regenerate isolated fixture databases, never target jobtracker_dev or production for destructive testing. Development runtime application commit remainscaa0c6a, which is source-equivalent to the application portions of5032ccb and these documentation-only descendants. It was not replaced merely to change a displayed documentation commit. + +Production remains NO-GO; physical-device, human/AT/language/print, affected S01 disposition, real CV semantic quality, hosted CI/runtime isolation, native/image review and production operator qualifications remain separately tracked. None of these histories is deleted or accepted on the owner's behalf. diff --git a/docs/automation/handoffs/pre-phase10/PLAN.md b/docs/automation/handoffs/pre-phase10/PLAN.md index 894d586..05342fa 100644 --- a/docs/automation/handoffs/pre-phase10/PLAN.md +++ b/docs/automation/handoffs/pre-phase10/PLAN.md @@ -37,4 +37,6 @@ The sole active app-inventory chat using this cwd is this task; the separate act The existing controller's result/backlog schemas are not acceptance-package schemas. Use a separately versioned **proposed evidence contract**, with explicit mapping to its protected signed entry/deferral/review gates, not a competing executable queue. Do not copy/configure its runtime or fabricate signatures. +The initial commit normalised the copied request's CRLF bytes. Scoped .gitattributes now preserves the original request and hash-indexed package bytes exactly across checkouts; no instruction or acceptance criterion is changed. Native evidence is compressed individually for portable verification rather than relying on ignored files in another worktree. + Existing Phase9 authority allows genuinely unfinished human checks as release debt and individually scoped conditional development; it does not grant broad Phase10 entry or accept unresolved security risks. Exact candidate approval and unused-caller proof remain mandatory. This handoff can be READY as evidence while Phase10 remains BLOCKED. diff --git a/docs/automation/handoffs/pre-phase10/QUALIFICATION_FAILURES.md b/docs/automation/handoffs/pre-phase10/QUALIFICATION_FAILURES.md new file mode 100644 index 0000000..8800840 --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/QUALIFICATION_FAILURES.md @@ -0,0 +1,14 @@ +# Retained failures and recovery + +Failed attempts are not deleted, counted as passing tests or hidden by retries. + +| Attempt | Actual failure | Correction / boundary | +|---|---|---| +| post-01 | Temporary proxy exited before any browser case; immediate port lookup raised KeyError | A separate reproduction retained nginx's exact `mkdir /var/cache/nginx/fastcgi_temp: Read-only file system` error. The one-off fixture omitted FastCGI/uwsgi/scgi paths. post-02 points all temporary paths into the existing bounded `/tmp` mount and checks startup state. Root stays read-only; no application/configuration or test assertion changed | +| proxy-reproduction-02 | Expected diagnostic exit1 before tests | Exact logs/state and owned-resource cleanup retained; not a product failure or extra test case | +| post-02 Linux build | The runner incorrectly supplied an output outside `.artifacts/cv-ux-01`; existing helper rejected it before build | linux-post-03 resumes only the unfinished Linux/audit work under a fresh allowed child. The helper guard was preserved; already passing import/MariaDB/Windows lanes were not rerun or double-counted | +| Revised S01 oracle | Windows8/36 and the separately recorded Linux result; original2mm coordinate threshold unchanged | Content, name wrapping, sidebar raster and visible-ink diagnostics are distinct evidence. No golden/tolerance change or aesthetic self-approval | +| Isolated real CV-model probe | All3 synthetic responses rejected with ValueError | No model/validator replacement or activation. Compatibility/semantic accuracy remains BLOCKED; process exit0 means the measurement completed | +| Initial handoff-validator RED | New tests failed because implementation module was absent | Native parser/hash/approval tests implemented and rerun; final unit/integration results supersede overlapping focused runs, without adding them | + +Raw evidence is under `.artifacts/automation-handoff-01/`, with portable native reports/process/source artifacts in TEST_EVIDENCE.json. The original broad regression ran once to completion with all four groups passing and source unchanged; it is not the previous workstream's composite recovery result. Transient provider_unavailable history on the fresh successful strategy operation is retained in the local-worker result; it is not described as first-attempt success. diff --git a/docs/automation/handoffs/pre-phase10/READY_TO_RUN.md b/docs/automation/handoffs/pre-phase10/READY_TO_RUN.md new file mode 100644 index 0000000..005bd80 --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/READY_TO_RUN.md @@ -0,0 +1,26 @@ +# Ready-to-run conditions + +**Phase10 and real autonomous execution remain BLOCKED. This package does not authorise either.** A structurally READY evidence package can truthfully contain a NO-GO entry decision. + +Before the separate controller starts anything, its operator must independently: + +1. Resolve the final `test/pre-phase10-ux-acceptance` HEAD from Gitea and local Git; require exact equality, clean checkout and ancestry of5032ccb. Do not assume main contains the redesign. The package's localCommit is the frozen application baseline; its snapshotHead/remote observation are dated evidence, not self-referential claims about the later package commit. +2. Validate HANDOFF_SCHEMA.json and every indexed compressed native report/process/source artifact. Recompute hashes, native counters and identities, reject absent/unexecuted/failing/skipped/retried required cases, and check commit/source/image correspondence. Documentation-only descendants are explicitly bounded; any application/test change requires affected fresh qualification. Package metadata is not its own authority. +3. Obtain a protected `phase10-development-entry` approval bound to the **resolved final published commit**, exact candidate scope, current policy/prompt and artifact hashes. No approval was supplied to this handoff, and none is generated. A worker-written GO or signed-looking JSON is not approval. +4. Establish concrete unused caller/route/old-data proof, affected57-group/34-route preservation, rollback and candidate tests before any removal. Current inventory has **no approved removal**. Retain legacy CV design/run behavior, aliases, revision/persistence contracts, SQLite and migrations. +5. Resolve affected S01/rendering acceptance or obtain an explicit protected applicability decision supported by unchanged original failures and real visual evidence. Do not silently reinterpret a required automated failure as a deferral. Complete applicable human checks; existing release-only debt does not independently forbid unrelated assessment, but also does not grant implementation authority. +6. Qualify the separate controller's native sandbox/host/process/secret/read/egress/control-plane boundary and install/approve the actual stage composite test adapter. Its synthetic48+6 test evidence and static queue validity do not qualify real roadmap execution. This workstream did not modify or run it. +7. Reconcile individual conditional debt with the existing signed policy. Current checkpoint deferrableGates arrays are empty. Any future policy/conditional-deferral requires the controller's protected approval flow and cannot override a mandatory automated requirement. Keep hosted CI BLOCKED until actual isolated execution and cleanup proof; keep CV AI disabled and production NO-GO. + +Local package checks: + +```powershell +rtk proxy node --test docs/automation/handoffs/pre-phase10/verify.test.mjs +rtk proxy node docs/automation/handoffs/pre-phase10/verify.mjs +rtk proxy node docs/automation/handoffs/pre-phase10/verify.mjs --verify-remote +rtk proxy node docs/automation/handoffs/pre-phase10/verify.mjs --require-ready +``` + +Normal validation exit0 means evidence integrity is consistent; it prints Phase10 BLOCKED. `--require-ready` deliberately exits3 for this unapproved snapshot. This verifier does not run tests, launch a queue, validate/issue owner signatures or modify the controller. The controller must perform its own protected checks and fresh candidate verification. If it lacks these capabilities, stop rather than trusting a repository status. + +No protected owner key/token, credentials, model cache or production endpoint belongs in this package. The separate worktree was inspected through committed Git objects only. No second orchestrator, scheduled automation, main merge, deployment or Phase10 implementation was started. diff --git a/docs/automation/handoffs/pre-phase10/REQUEST.md b/docs/automation/handoffs/pre-phase10/REQUEST.md index a168e77..47fc629 100644 --- a/docs/automation/handoffs/pre-phase10/REQUEST.md +++ b/docs/automation/handoffs/pre-phase10/REQUEST.md @@ -1,909 +1,909 @@ -# Jobjakt — AUTOMATION-HANDOFF-01 -## Finish Pre-Phase-10 Acceptance and Prepare for Autonomous Roadmap Execution - -### Your role - -Act as Jobjakt's senior QA engineer, release engineer, software architect, Git integration specialist and autonomous-development handoff coordinator. - -Your task is to complete the remaining safely achievable Pre-Phase-10 acceptance work and prepare a reliable, machine-readable handoff for the separate AUTONOMOUS-ROADMAP-01 Codex orchestrator. - -**Do not begin Phase 10.** - -Your objective is to leave the development repository in a verified, clean, reproducible state from which an independently authorised automation system can safely begin Phase 10 and eventually continue through the remaining roadmap. - -Work autonomously through normal development, testing, remediation, documentation and feature-branch publication. - -Only interrupt me when genuine human approval, manual testing or external infrastructure action is needed. - ---- - -# 1. Starting baseline - -Latest reported development environment: - -Local URL: -`http://jobbjakt.local/` - -Branch: -`test/pre-phase10-ux-acceptance` - -Latest reported commit: -`5032ccb` - -Reported status: - -- Working tree clean. -- Backend: 1,448 tests passed. -- Frontend: 1,031 tests passed. -- Python: 83 tests passed. -- Real MariaDB: 90 tests passed. -- Ordinary browser regression: 380 tests passed. -- Real CV extraction verified. -- Queued AI strategy generation verified. -- Scheduled job enrichment verified. -- Conflicting JSON instructions in the strategy route corrected. -- Synthetic accounts and temporary test containers cleaned up. -- Two local commits remain unpublished because Git server connectivity failed. -- Production remains NO-GO. -- No merge or deployment occurred. - -Outstanding qualifications include: - -- CV AI extraction and semantic accuracy. -- Human accessibility testing. -- Physical-device testing. -- Human language review. -- PDF template spacing and visual qualification. -- Historical Phase 9, Python dependency and CI requirements where still applicable. -- Existing production-only infrastructure and recovery gates. - -Read the actual current evidence before relying on this summary. - -Primary documentation: - -`docs/pre-phase10-ux/ACCEPTANCE.md` - -`docs/pre-phase10-ux/CV_QA_HANDOFF.md` - -Also inspect the authoritative CV-UX, CV-IMPORT, CV-QA, RD21, Phase 9, Phase 10 and preservation documentation. - -Verify which reported checks are actually complete, which were conditionally accepted and which remain outstanding. - -Do not invent evidence for missing results. - ---- - -# 2. Relationship to the automation orchestrator - -A separate workstream named: - -`AUTONOMOUS-ROADMAP-01` - -is responsible for building a persistent Windows-compatible Codex orchestrator. - -That orchestrator will eventually process the approved roadmap: - -05 — Phase 10 cleanup. - -06 — PRODUCT-REVIEW-01. - -07 — INT-GLOBAL-JOBS-01. - -08 — I18N-01 translations. - -09 — LAUNCH-SITE-01 homepage redesign. - -10 — SECURITY-AUDIT-01. - -11 — RELEASE-READINESS-01. - -Your responsibility is **not** to implement or run this orchestrator. - -Your responsibility is to make the current repository and its acceptance evidence suitable for the orchestrator to consume. - -You must provide: - -- An authoritative accepted development baseline. -- A complete pre-Phase-10 blocker register. -- Structured acceptance evidence. -- Stage dependency and gate definitions. -- Explicit deferrals and reasons. -- Human approval requirements. -- Git branch and remote state. -- Reproducible verification commands. -- An exact Phase 10 handoff. - -Coordinate through documented contracts, not by modifying the other worktree or running a second orchestrator. - ---- - -# 3. Git and worktree safety - -Stay on the currently authorised Pre-Phase-10 development branch, or the verified equivalent worktree containing its complete history. - -Before making changes: - -1. Verify Git status. -2. Verify current HEAD. -3. Verify ancestry of commit `5032ccb`. -4. Inspect pending local commits. -5. Identify the configured Gitea remote. -6. Confirm the worktree is not being modified by another Codex session. -7. Determine which branch contains the latest accepted integration history. - -Do not assume `main` includes the redesign. - -Do not reset, rebase destructively, cherry-pick blindly or force-push. - -Do not alter the separate automation worktree. - -Do not merge into `main`. - -Do not deploy production. - -If new commits are required, keep them on the authorised pre-Phase-10 branch and document their hashes. - ---- - -# 4. P10-HANDOFF-00 — Comprehensive acceptance reconciliation - -Begin with a complete review of the existing acceptance evidence. - -Determine whether the currently reported implementation genuinely satisfies the mandatory development requirements. - -Investigate: - -### CV Builder - -- Creating a completely blank CV with zero unwanted content sections. -- Creating a CV from Career Profile. -- Undo/redo across supported editor operations. -- Save, refresh and recovery. -- Multiple-session editing. -- Existing CV compatibility. -- Historical document preservation. - -### CV templates - -- Existing template spacing. -- New template library. -- Optional-photo templates. -- Font consistency. -- Page margins. -- Section spacing. -- Bullet indentation. -- Multi-page layout. -- PDF preview/export agreement. - -### CV import - -- Real PDF extraction. -- Real DOCX extraction. -- Career Profile mapping. -- New-record creation. -- Review and corrections. -- Duplicate handling. -- Transactional MariaDB persistence. -- Failure recovery. -- Source provenance. - -### Dashboard - -- Widget drag-and-drop. -- Resizing. -- Show/hide controls. -- Layout persistence. -- Mobile behaviour. -- Keyboard accessibility. -- Existing preference compatibility. - -### Admin Processing Monitor - -- Job attribution to the submitting user. -- Related job application or import record. -- Processing stage. -- Status and duration. -- Failure diagnostics. -- Sanitised event logs. -- Administrative authorisation. -- Tenant isolation. -- Log redaction. - -### AI workflows - -- CV extraction. -- Queued AI strategy generation. -- Scheduled job enrichment. -- Safe structured outputs. -- Processing failure handling. -- Disabled/unqualified AI functionality. -- Model compatibility and semantic qualification requirements. - -### Application preservation - -- Existing routes. -- Authentication. -- Career Profile. -- Jobs and applications. -- CVs. -- Cover letters. -- Dashboard. -- Settings. -- Administration. -- English/Norwegian. -- Existing functionality-preservation contracts. - -Use actual repository implementation and evidence. - -Create a traceability matrix mapping each required capability to its test evidence and acceptance status. - -Do not claim that an untested feature passed merely because its implementation exists. - ---- - -# 5. P10-HANDOFF-01 — Fix remaining bounded defects - -Investigate the remaining pre-Phase-10 defects. - -Prioritise: - -1. User-data loss or corruption. -2. Broken Career Profile persistence. -3. Import approval failures. -4. Missing-record creation. -5. Undo/redo defects. -6. Incorrect blank CV behaviour. -7. Broken template spacing or clipping. -8. Missing PDF content. -9. Admin authorisation or sensitive-log exposure. -10. Broken dashboard persistence. -11. Confirmed regressions in existing workflows. - -Fix reproducible defects that are within the current acceptance scope. - -For each fix: - -- Record the reproduction. -- Identify the root cause. -- Implement the smallest maintainable correction. -- Add regression tests. -- Run targeted verification. -- Update the acceptance matrix. - -Do not begin unrelated product features. - -Do not redesign major parts of Jobjakt unnecessarily. - -If a requested change is genuinely outside the existing acceptance scope, record it as a separate backlog item rather than silently expanding Phase 10. - -Do not change acceptance criteria solely to obtain a PASS. - ---- - -# 6. P10-HANDOFF-02 — PDF spacing and document qualification - -The remaining PDF spacing review requires particular attention. - -The original PDF fidelity fixtures previously passed on Windows and Linux, but this does not automatically establish that every template has excellent spacing. - -Perform a dedicated visual and functional audit of the current CV template library. - -Render representative synthetic CVs using every available template. - -Include: - -- Short CV. -- Long CV. -- Multiple employers. -- Dense education. -- Long skill lists. -- Several languages. -- Norwegian characters. -- Optional profile photographs. -- Multi-page content. -- Cover letters where applicable. - -Check: - -- Section spacing. -- Line height. -- Paragraph rhythm. -- Headers. -- Margins. -- List indentation. -- Column alignment. -- Page breaks. -- Font weights. -- Text clipping. -- Missing content. -- Excessive whitespace. -- Preview/PDF differences. - -Generate actual rendered preview images or PDFs for inspection. - -Fix measurable formatting defects. - -Create a visual comparison package for owner review where aesthetic approval is necessary. - -Retain historical document compatibility and existing licensed-font arrangements. - -Do not modify golden fixtures merely to conceal regressions. - -Distinguish: - -- Automated PDF fidelity: PASS/FAIL. -- Semantic content completeness: PASS/FAIL. -- Visual spacing qualification: PASS/PARTIAL/FAIL. -- Human print approval: PASS/NOT TESTED. - -If human visual or printing acceptance is required by the authoritative Phase 10 entry criteria, prepare the relevant review artifacts and keep that gate pending until I approve them. - ---- - -# 7. P10-HANDOFF-03 — Real AI and security qualification - -Review the actual current AI architecture. - -The latest report states real CV extraction, queued AI strategy generation and scheduled enrichment have been verified. - -Determine precisely what was exercised. - -Distinguish: - -- Real Docling parsing. -- Deterministic extraction. -- Model-assisted processing. -- Queued task execution. -- Structured-output validation. -- Real model inference. -- Semantic correctness. -- User-reviewed final output. -- Source-grounded accuracy. - -Do not interpret a successful AI request or completed background job as proof of good AI output. - -Inspect the existing model qualification and Python dependency security evidence. - -Determine which checks can safely run in the isolated development environment. - -If approved model artifacts and safe runtime conditions exist, conduct authorised targeted model evaluations. - -Otherwise preserve the relevant qualification as BLOCKED or NOT TESTED. - -Do not download large models to production. - -Do not change live Ollama services or model caches. - -Do not accept security risks on my behalf. - -If optional AI functionality is disabled, isolated and not required for Phase 10 code cleanup, document whether its remaining qualification can legally and technically be deferred under the existing acceptance criteria. - -Do not falsely mark AI production-ready. - ---- - -# 8. P10-HANDOFF-04 — Human and manual acceptance - -Prepare a prioritised owner-test package. - -Include: - -- What to test. -- Why it matters. -- Exact page or workflow. -- Preconditions. -- Test steps. -- Expected behaviour. -- Pass/fail criteria. -- Evidence to capture. -- Whether the test blocks Phase 10 or production only. - -Cover: - -- Real mobile/tablet. -- Keyboard-only usage. -- Screen reader. -- English copy. -- Norwegian Bokmål copy. -- Other implemented languages. -- CV editor usability. -- Template visual approval. -- PDF printing. -- Job tracking. -- Dashboard layout. -- Admin diagnostics. -- AI-generated content review where enabled. - -Complete checks that can genuinely be performed automatically. - -Do not fabricate physical-device, human language, screen-reader or printing test results. - -Where a mandatory human decision is needed, flag it clearly. - -Prefer a small, well-prioritised owner checklist over a large unstructured testing document. - ---- - -# 9. P10-HANDOFF-05 — Resolve Git publication - -Two local commits were reported to be awaiting publication. - -Diagnose the Gitea connectivity issue safely. - -Verify: - -- Remote URL. -- DNS. -- Network reachability. -- HTTPS connectivity. -- TLS validation. -- Git authentication, if reached. -- Local/remote branch divergence. - -If the remote becomes available, perform a normal push of the authorised development branch. - -Verify remote HEAD equals the intended local commit. - -Do not force-push. - -Do not disable TLS verification. - -Do not expose tokens or credentials. - -If connectivity remains unavailable: - -- Preserve all local commits. -- Record precise diagnostics. -- Mark Git publication BLOCKED. -- Provide exact operator actions. -- Do not declare the remote branch published. - -A pending or failed push must be represented accurately in the automation handoff. - -Do not let the orchestrator silently assume that a local commit exists remotely. - -Also inspect the separately completed GJ-00 planning branch's publication status without merging or modifying it. - ---- - -# 10. P10-HANDOFF-06 — Full regression baseline - -After bounded remediation, run the applicable regression suites. - -Include: - -- .NET backend. -- React frontend. -- Ordinary browser. -- CV import browser journeys. -- Real MariaDB integration. -- RD21 concurrency and recovery. -- Python sidecar. -- Document extraction. -- Queued processing. -- Scheduled job enrichment. -- CV Editor. -- PDF fidelity. -- Dashboard customisation. -- Admin processing monitor. -- Browser contracts. -- TypeScript. -- Lint. -- Builds. -- Security scans. -- Existing functionality preservation. - -Use approved isolated environments. - -Record: - -- Commands. -- Exit codes. -- Environment details. -- Passed/failed/skipped counts. -- Test report paths. -- Final commit. -- Relevant test artifacts. -- Any checks not run. - -Do not treat previously reported counts as newly executed evidence. - -Never weaken tests merely to achieve a green result. - -Ensure generated test reports are attributable to the specific tested commit. - ---- - -# 11. P10-HANDOFF-07 — Define precise Phase 10 entry gates - -This is the most important orchestration requirement. - -Review the authoritative Phase 10 entry criteria. - -Separate all outstanding work into: - -### A. Mandatory Phase 10 blockers - -Issues that must be resolved before code cleanup can safely begin. - -### B. Permissible conditional-development deferrals - -Items that may remain outstanding during Phase 10 only where an existing approved acceptance rule permits it. - -### C. Production release blockers - -Issues that can be addressed later without invalidating Phase 10 development. - -### D. Future feature work - -Items belonging to the post-Phase-10 product roadmap. - -For every item include: - -- Stable ID. -- Description. -- Evidence. -- Severity. -- Relevant acceptance criterion. -- Required action. -- Blocking phase. -- Responsible party. -- Deferral authority, if any. -- Current status. - -Do not infer that an item is deferrable simply because it is inconvenient. - -If a requirement is ambiguous or a conditional entry needs owner judgement, request approval rather than inventing permission. - -Do not require every production-only infrastructure issue to be resolved before non-production Phase 10 work unless the authoritative criteria actually require it. - -Likewise, do not advance with unresolved mandatory development-entry blockers. - ---- - -# 12. P10-HANDOFF-08 — Machine-readable orchestration contract - -Produce structured artifacts for the AUTONOMOUS-ROADMAP-01 orchestrator. - -Place handoff documentation under: - -`docs/automation/handoffs/pre-phase10/` - -Use repository conventions where appropriate. - -Required artifacts: - -### `HANDOFF.md` - -Human-readable overview of the current accepted state and readiness. - -### `ACCEPTANCE.json` - -Machine-readable status. - -Include: - -- Schema version. -- Workstream ID. -- Source branch. -- Local commit. -- Verified remote commit, if available. -- Worktree cleanliness. -- Acceptance status. -- Entry-gate status. -- Test evidence references. -- Unresolved blocker IDs. -- Permissible deferrals. -- Required owner approvals. -- Generation timestamp. -- Recommendation for Phase 10. - -### `GATES.json` - -Define stage-specific gate requirements, including: - -- Required predecessor. -- Required test suites. -- Minimum acceptable evidence. -- Required Git state. -- Required preservation checks. -- Required manual approvals. -- Permissible conditional deferrals. -- Blocking findings. - -### `BLOCKERS.json` - -Structured unresolved-issue register. - -### `TEST_EVIDENCE.json` - -Index machine-verifiable test results and report artifacts. - -Include commit binding and actual process exit codes. - -### `MANUAL_ACCEPTANCE.md` - -Prioritised human test and approval checklist. - -### `PHASE10_BASELINE.md` - -Exact branch and commit ancestry, preservation scope, safe cleanup targets and required compatibility checks. - -### `READY_TO_RUN.md` - -Exact conditions required to start automated Phase 10. - -### `HANDOFF_SCHEMA.json` - -JSON Schema for the exported acceptance package. - -Validate all structured JSON. - -Use stable keys and explicit status enums. - -Do not include secrets, personal data or machine-specific credentials. - -Absolute local paths may be included as informational references, but prefer repository-relative paths for portable automation. - ---- - -# 13. Critical acceptance-security rule - -The handoff package is evidence, not authority by itself. - -A Codex-generated `ACCEPTANCE.json` must not be able to bypass a gate simply by claiming: - -`"status": "GO"` - -The orchestrator must independently verify: - -- Required report existence. -- Test exit codes. -- Commit correspondence. -- Remote publication. -- Accepted predecessor stages. -- Mandatory blocker status. -- Applicable owner approvals. - -Owner approvals must be maintained outside the model-writable repository or through another protected approval mechanism. - -Do not generate approval tokens or owner signatures. - -Do not mark human acceptance PASS without actual approval evidence. - -If the external orchestrator already defines an acceptance schema, conform to it where compatible rather than creating a conflicting parallel standard. - -If it is still under development, produce a clearly versioned proposed contract and document the integration requirements. - ---- - -# 14. P10-HANDOFF-09 — Phase 10 cleanup inventory - -Prepare the scope for the actual Phase 10 task. - -Identify proven superseded components and code. - -Include: - -- Legacy CV Editor components. -- Old CV import components. -- Replaced dashboard layout configuration. -- Superseded admin-processing views. -- Unused style utilities. -- Duplicate services. -- Unreferenced frontend routes. -- Obsolete feature flags. -- Potentially unused dependencies. -- Historical compatibility components that must remain. -- Database code with active compatibility requirements. - -For every proposed removal include: - -- Location. -- Why it appears obsolete. -- Evidence of actual replacement. -- Current consumers. -- Dynamic/runtime reference risks. -- Related preservation group. -- Required regression test. -- Removal risk. - -Do not remove these items as part of the handoff. - -Do not delete old PDF renderers, document mappings or migrations solely because newer implementations exist. - -Do not retire SQLite automatically. - -Do not perform MariaDB major-version upgrades. - -Phase 10 will make removal decisions using this evidence. - ---- - -# 15. P10-HANDOFF-10 — Reconcile the remaining roadmap - -The automation queue after Phase 10 is intended to contain: - -05 — Phase 10 final redesign cleanup. - -06 — PRODUCT-REVIEW-01 full application review. - -07 — INT-GLOBAL-JOBS-01 international, cross-industry job discovery. - -08 — I18N-01 expanded translations and locale qualification. - -09 — LAUNCH-SITE-01 multilingual homepage redesign. - -10 — SECURITY-AUDIT-01 adversarial audit and remediation. - -11 — RELEASE-READINESS-01 production qualification. - -Also preserve separate tracked initiatives: - -- Deferred P5-13 AI qualification and model assessment. -- LinkedIn integration feasibility. -- Android application. -- SQLite retirement. -- MariaDB upgrade strategy. -- Monitoring and operational improvements. -- Future country integrations. - -These initiatives must not be silently discarded simply because they aren't numbered 05–11. - -Highlight the dependencies: - -- Global Job Search depends on approved planning and provider permissions. -- Internationalisation overlaps with Global Job Search and homepage work. -- Product Review requires owner approval before starting its resulting implementation scope. -- Homepage final visual design requires owner approval. -- Production requires independent security, backup, recovery and release approval. - -Create an automation-friendly roadmap summary without starting any later workstream. - ---- - -# 16. Autonomous execution checkpoints - -Execute safely in this order: - -### AUTO-H01 — Baseline and acceptance reconciliation -Read the reports, verify actual Git state and establish existing evidence. - -### AUTO-H02 — Targeted defect remediation -Fix bounded confirmed pre-Phase-10 defects. - -### AUTO-H03 — PDF and AI qualification -Complete permitted verification and document remaining blocked items. - -### AUTO-H04 — Manual acceptance preparation -Produce focused human test packages and record genuine approvals. - -### AUTO-H05 — Git publication recovery -Publish pending development commits if the remote is available. - -### AUTO-H06 — Full regression -Establish commit-bound verification evidence. - -### AUTO-H07 — Structured automation handoff -Produce and validate schemas, gates, blocker registers and evidence manifests. - -### AUTO-H08 — Phase 10 readiness -Determine the actual acceptance decision and exact automation prerequisites. - -Commit and push validated checkpoints. - -If the remote is unavailable, continue safe independent work and preserve commits locally. - -Do not claim remote publication when it is unverified. - ---- - -# 17. Required final decisions - -Issue independent verdicts for: - -**Pre-Phase-10 UX:** GO / CONDITIONAL GO / NO-GO. - -**CV Integration:** GO / CONDITIONAL GO / NO-GO. - -**PDF Spacing:** PASS / PARTIAL / FAIL. - -**CV AI Accuracy:** PASS / PARTIAL / BLOCKED. - -**Human/Device Acceptance:** PASS / PARTIAL / NOT TESTED. - -**Python Security:** PASS / CONDITIONAL / BLOCKED. - -**Hosted CI:** PASS / BLOCKED / FAIL. - -**Preservation:** PASS / PARTIAL / FAIL. - -**Git Publication:** VERIFIED / BLOCKED. - -**Phase 10 Development Readiness:** GO / CONDITIONAL GO / NO-GO. - -**Automation Handoff Package:** READY / INCOMPLETE. - -**Production:** GO / NO-GO. - -Every verdict must cite actual supporting evidence. - -Distinguish implementation completion from acceptance, deployment and release readiness. - ---- - -# 18. Final report - -At completion, report: - -1. Current branch and final commit. -2. Working-tree status. -3. Remote publication state. -4. Defects fixed. -5. Tests executed and actual totals. -6. Outstanding mandatory blockers. -7. Permitted deferrals. -8. Human actions required. -9. Automation handoff artifacts created. -10. Acceptance schema validation result. -11. Phase 10 entry decision. -12. Exact integration baseline for the orchestrator. -13. Whether the orchestrator may start automatically. -14. What it must verify independently before doing so. - -If Phase 10 receives an authoritative GO or approved CONDITIONAL GO, mark the handoff eligible for orchestration. - -However, **do not actually begin Phase 10**. - -If required conditions remain outstanding, mark the stage BLOCKED and state exactly how it can become READY. - ---- - -# 19. Hard restrictions - -Do not: - -- Merge into `main`. -- Deploy production. -- Start Phase 10. -- Start Global Job Search. -- Start the Product Review. -- Modify the separate automation worktree. -- Fabricate owner approval. -- Self-approve acceptance exceptions. -- Bypass Python security qualifications. -- Modify live Ollama. -- Download unapproved production models. -- Change production MariaDB. -- Perform destructive database migrations. -- Modify production Docker services. -- Modify or repair production filesystems. -- Remove compatibility code prematurely. -- Lower test requirements to achieve a GO. - -Do not introduce unnecessary changes that disrupt the locally running `jobbjakt.local` environment. - -If a test requires destructive operations, use a disposable database or isolated test environment. - ---- - -# FINAL INSTRUCTION - -Starting from the real current Pre-Phase-10 acceptance state, complete all safely achievable outstanding acceptance and remediation work. - -Restore Git publication where possible. - -Prepare a **machine-readable, independently verifiable Phase 10 handoff** suitable for AUTONOMOUS-ROADMAP-01. - -Make the handoff robust enough that the orchestrator can identify: - -- What has passed. -- What is blocked. -- What may be deferred. -- Which human approvals are required. -- Which exact commit forms the accepted baseline. -- Whether Phase 10 may begin. - -Work autonomously, commit and push validated checkpoints, and prepare all necessary documentation. - +# Jobjakt — AUTOMATION-HANDOFF-01 +## Finish Pre-Phase-10 Acceptance and Prepare for Autonomous Roadmap Execution + +### Your role + +Act as Jobjakt's senior QA engineer, release engineer, software architect, Git integration specialist and autonomous-development handoff coordinator. + +Your task is to complete the remaining safely achievable Pre-Phase-10 acceptance work and prepare a reliable, machine-readable handoff for the separate AUTONOMOUS-ROADMAP-01 Codex orchestrator. + +**Do not begin Phase 10.** + +Your objective is to leave the development repository in a verified, clean, reproducible state from which an independently authorised automation system can safely begin Phase 10 and eventually continue through the remaining roadmap. + +Work autonomously through normal development, testing, remediation, documentation and feature-branch publication. + +Only interrupt me when genuine human approval, manual testing or external infrastructure action is needed. + +--- + +# 1. Starting baseline + +Latest reported development environment: + +Local URL: +`http://jobbjakt.local/` + +Branch: +`test/pre-phase10-ux-acceptance` + +Latest reported commit: +`5032ccb` + +Reported status: + +- Working tree clean. +- Backend: 1,448 tests passed. +- Frontend: 1,031 tests passed. +- Python: 83 tests passed. +- Real MariaDB: 90 tests passed. +- Ordinary browser regression: 380 tests passed. +- Real CV extraction verified. +- Queued AI strategy generation verified. +- Scheduled job enrichment verified. +- Conflicting JSON instructions in the strategy route corrected. +- Synthetic accounts and temporary test containers cleaned up. +- Two local commits remain unpublished because Git server connectivity failed. +- Production remains NO-GO. +- No merge or deployment occurred. + +Outstanding qualifications include: + +- CV AI extraction and semantic accuracy. +- Human accessibility testing. +- Physical-device testing. +- Human language review. +- PDF template spacing and visual qualification. +- Historical Phase 9, Python dependency and CI requirements where still applicable. +- Existing production-only infrastructure and recovery gates. + +Read the actual current evidence before relying on this summary. + +Primary documentation: + +`docs/pre-phase10-ux/ACCEPTANCE.md` + +`docs/pre-phase10-ux/CV_QA_HANDOFF.md` + +Also inspect the authoritative CV-UX, CV-IMPORT, CV-QA, RD21, Phase 9, Phase 10 and preservation documentation. + +Verify which reported checks are actually complete, which were conditionally accepted and which remain outstanding. + +Do not invent evidence for missing results. + +--- + +# 2. Relationship to the automation orchestrator + +A separate workstream named: + +`AUTONOMOUS-ROADMAP-01` + +is responsible for building a persistent Windows-compatible Codex orchestrator. + +That orchestrator will eventually process the approved roadmap: + +05 — Phase 10 cleanup. + +06 — PRODUCT-REVIEW-01. + +07 — INT-GLOBAL-JOBS-01. + +08 — I18N-01 translations. + +09 — LAUNCH-SITE-01 homepage redesign. + +10 — SECURITY-AUDIT-01. + +11 — RELEASE-READINESS-01. + +Your responsibility is **not** to implement or run this orchestrator. + +Your responsibility is to make the current repository and its acceptance evidence suitable for the orchestrator to consume. + +You must provide: + +- An authoritative accepted development baseline. +- A complete pre-Phase-10 blocker register. +- Structured acceptance evidence. +- Stage dependency and gate definitions. +- Explicit deferrals and reasons. +- Human approval requirements. +- Git branch and remote state. +- Reproducible verification commands. +- An exact Phase 10 handoff. + +Coordinate through documented contracts, not by modifying the other worktree or running a second orchestrator. + +--- + +# 3. Git and worktree safety + +Stay on the currently authorised Pre-Phase-10 development branch, or the verified equivalent worktree containing its complete history. + +Before making changes: + +1. Verify Git status. +2. Verify current HEAD. +3. Verify ancestry of commit `5032ccb`. +4. Inspect pending local commits. +5. Identify the configured Gitea remote. +6. Confirm the worktree is not being modified by another Codex session. +7. Determine which branch contains the latest accepted integration history. + +Do not assume `main` includes the redesign. + +Do not reset, rebase destructively, cherry-pick blindly or force-push. + +Do not alter the separate automation worktree. + +Do not merge into `main`. + +Do not deploy production. + +If new commits are required, keep them on the authorised pre-Phase-10 branch and document their hashes. + +--- + +# 4. P10-HANDOFF-00 — Comprehensive acceptance reconciliation + +Begin with a complete review of the existing acceptance evidence. + +Determine whether the currently reported implementation genuinely satisfies the mandatory development requirements. + +Investigate: + +### CV Builder + +- Creating a completely blank CV with zero unwanted content sections. +- Creating a CV from Career Profile. +- Undo/redo across supported editor operations. +- Save, refresh and recovery. +- Multiple-session editing. +- Existing CV compatibility. +- Historical document preservation. + +### CV templates + +- Existing template spacing. +- New template library. +- Optional-photo templates. +- Font consistency. +- Page margins. +- Section spacing. +- Bullet indentation. +- Multi-page layout. +- PDF preview/export agreement. + +### CV import + +- Real PDF extraction. +- Real DOCX extraction. +- Career Profile mapping. +- New-record creation. +- Review and corrections. +- Duplicate handling. +- Transactional MariaDB persistence. +- Failure recovery. +- Source provenance. + +### Dashboard + +- Widget drag-and-drop. +- Resizing. +- Show/hide controls. +- Layout persistence. +- Mobile behaviour. +- Keyboard accessibility. +- Existing preference compatibility. + +### Admin Processing Monitor + +- Job attribution to the submitting user. +- Related job application or import record. +- Processing stage. +- Status and duration. +- Failure diagnostics. +- Sanitised event logs. +- Administrative authorisation. +- Tenant isolation. +- Log redaction. + +### AI workflows + +- CV extraction. +- Queued AI strategy generation. +- Scheduled job enrichment. +- Safe structured outputs. +- Processing failure handling. +- Disabled/unqualified AI functionality. +- Model compatibility and semantic qualification requirements. + +### Application preservation + +- Existing routes. +- Authentication. +- Career Profile. +- Jobs and applications. +- CVs. +- Cover letters. +- Dashboard. +- Settings. +- Administration. +- English/Norwegian. +- Existing functionality-preservation contracts. + +Use actual repository implementation and evidence. + +Create a traceability matrix mapping each required capability to its test evidence and acceptance status. + +Do not claim that an untested feature passed merely because its implementation exists. + +--- + +# 5. P10-HANDOFF-01 — Fix remaining bounded defects + +Investigate the remaining pre-Phase-10 defects. + +Prioritise: + +1. User-data loss or corruption. +2. Broken Career Profile persistence. +3. Import approval failures. +4. Missing-record creation. +5. Undo/redo defects. +6. Incorrect blank CV behaviour. +7. Broken template spacing or clipping. +8. Missing PDF content. +9. Admin authorisation or sensitive-log exposure. +10. Broken dashboard persistence. +11. Confirmed regressions in existing workflows. + +Fix reproducible defects that are within the current acceptance scope. + +For each fix: + +- Record the reproduction. +- Identify the root cause. +- Implement the smallest maintainable correction. +- Add regression tests. +- Run targeted verification. +- Update the acceptance matrix. + +Do not begin unrelated product features. + +Do not redesign major parts of Jobjakt unnecessarily. + +If a requested change is genuinely outside the existing acceptance scope, record it as a separate backlog item rather than silently expanding Phase 10. + +Do not change acceptance criteria solely to obtain a PASS. + +--- + +# 6. P10-HANDOFF-02 — PDF spacing and document qualification + +The remaining PDF spacing review requires particular attention. + +The original PDF fidelity fixtures previously passed on Windows and Linux, but this does not automatically establish that every template has excellent spacing. + +Perform a dedicated visual and functional audit of the current CV template library. + +Render representative synthetic CVs using every available template. + +Include: + +- Short CV. +- Long CV. +- Multiple employers. +- Dense education. +- Long skill lists. +- Several languages. +- Norwegian characters. +- Optional profile photographs. +- Multi-page content. +- Cover letters where applicable. + +Check: + +- Section spacing. +- Line height. +- Paragraph rhythm. +- Headers. +- Margins. +- List indentation. +- Column alignment. +- Page breaks. +- Font weights. +- Text clipping. +- Missing content. +- Excessive whitespace. +- Preview/PDF differences. + +Generate actual rendered preview images or PDFs for inspection. + +Fix measurable formatting defects. + +Create a visual comparison package for owner review where aesthetic approval is necessary. + +Retain historical document compatibility and existing licensed-font arrangements. + +Do not modify golden fixtures merely to conceal regressions. + +Distinguish: + +- Automated PDF fidelity: PASS/FAIL. +- Semantic content completeness: PASS/FAIL. +- Visual spacing qualification: PASS/PARTIAL/FAIL. +- Human print approval: PASS/NOT TESTED. + +If human visual or printing acceptance is required by the authoritative Phase 10 entry criteria, prepare the relevant review artifacts and keep that gate pending until I approve them. + +--- + +# 7. P10-HANDOFF-03 — Real AI and security qualification + +Review the actual current AI architecture. + +The latest report states real CV extraction, queued AI strategy generation and scheduled enrichment have been verified. + +Determine precisely what was exercised. + +Distinguish: + +- Real Docling parsing. +- Deterministic extraction. +- Model-assisted processing. +- Queued task execution. +- Structured-output validation. +- Real model inference. +- Semantic correctness. +- User-reviewed final output. +- Source-grounded accuracy. + +Do not interpret a successful AI request or completed background job as proof of good AI output. + +Inspect the existing model qualification and Python dependency security evidence. + +Determine which checks can safely run in the isolated development environment. + +If approved model artifacts and safe runtime conditions exist, conduct authorised targeted model evaluations. + +Otherwise preserve the relevant qualification as BLOCKED or NOT TESTED. + +Do not download large models to production. + +Do not change live Ollama services or model caches. + +Do not accept security risks on my behalf. + +If optional AI functionality is disabled, isolated and not required for Phase 10 code cleanup, document whether its remaining qualification can legally and technically be deferred under the existing acceptance criteria. + +Do not falsely mark AI production-ready. + +--- + +# 8. P10-HANDOFF-04 — Human and manual acceptance + +Prepare a prioritised owner-test package. + +Include: + +- What to test. +- Why it matters. +- Exact page or workflow. +- Preconditions. +- Test steps. +- Expected behaviour. +- Pass/fail criteria. +- Evidence to capture. +- Whether the test blocks Phase 10 or production only. + +Cover: + +- Real mobile/tablet. +- Keyboard-only usage. +- Screen reader. +- English copy. +- Norwegian Bokmål copy. +- Other implemented languages. +- CV editor usability. +- Template visual approval. +- PDF printing. +- Job tracking. +- Dashboard layout. +- Admin diagnostics. +- AI-generated content review where enabled. + +Complete checks that can genuinely be performed automatically. + +Do not fabricate physical-device, human language, screen-reader or printing test results. + +Where a mandatory human decision is needed, flag it clearly. + +Prefer a small, well-prioritised owner checklist over a large unstructured testing document. + +--- + +# 9. P10-HANDOFF-05 — Resolve Git publication + +Two local commits were reported to be awaiting publication. + +Diagnose the Gitea connectivity issue safely. + +Verify: + +- Remote URL. +- DNS. +- Network reachability. +- HTTPS connectivity. +- TLS validation. +- Git authentication, if reached. +- Local/remote branch divergence. + +If the remote becomes available, perform a normal push of the authorised development branch. + +Verify remote HEAD equals the intended local commit. + +Do not force-push. + +Do not disable TLS verification. + +Do not expose tokens or credentials. + +If connectivity remains unavailable: + +- Preserve all local commits. +- Record precise diagnostics. +- Mark Git publication BLOCKED. +- Provide exact operator actions. +- Do not declare the remote branch published. + +A pending or failed push must be represented accurately in the automation handoff. + +Do not let the orchestrator silently assume that a local commit exists remotely. + +Also inspect the separately completed GJ-00 planning branch's publication status without merging or modifying it. + +--- + +# 10. P10-HANDOFF-06 — Full regression baseline + +After bounded remediation, run the applicable regression suites. + +Include: + +- .NET backend. +- React frontend. +- Ordinary browser. +- CV import browser journeys. +- Real MariaDB integration. +- RD21 concurrency and recovery. +- Python sidecar. +- Document extraction. +- Queued processing. +- Scheduled job enrichment. +- CV Editor. +- PDF fidelity. +- Dashboard customisation. +- Admin processing monitor. +- Browser contracts. +- TypeScript. +- Lint. +- Builds. +- Security scans. +- Existing functionality preservation. + +Use approved isolated environments. + +Record: + +- Commands. +- Exit codes. +- Environment details. +- Passed/failed/skipped counts. +- Test report paths. +- Final commit. +- Relevant test artifacts. +- Any checks not run. + +Do not treat previously reported counts as newly executed evidence. + +Never weaken tests merely to achieve a green result. + +Ensure generated test reports are attributable to the specific tested commit. + +--- + +# 11. P10-HANDOFF-07 — Define precise Phase 10 entry gates + +This is the most important orchestration requirement. + +Review the authoritative Phase 10 entry criteria. + +Separate all outstanding work into: + +### A. Mandatory Phase 10 blockers + +Issues that must be resolved before code cleanup can safely begin. + +### B. Permissible conditional-development deferrals + +Items that may remain outstanding during Phase 10 only where an existing approved acceptance rule permits it. + +### C. Production release blockers + +Issues that can be addressed later without invalidating Phase 10 development. + +### D. Future feature work + +Items belonging to the post-Phase-10 product roadmap. + +For every item include: + +- Stable ID. +- Description. +- Evidence. +- Severity. +- Relevant acceptance criterion. +- Required action. +- Blocking phase. +- Responsible party. +- Deferral authority, if any. +- Current status. + +Do not infer that an item is deferrable simply because it is inconvenient. + +If a requirement is ambiguous or a conditional entry needs owner judgement, request approval rather than inventing permission. + +Do not require every production-only infrastructure issue to be resolved before non-production Phase 10 work unless the authoritative criteria actually require it. + +Likewise, do not advance with unresolved mandatory development-entry blockers. + +--- + +# 12. P10-HANDOFF-08 — Machine-readable orchestration contract + +Produce structured artifacts for the AUTONOMOUS-ROADMAP-01 orchestrator. + +Place handoff documentation under: + +`docs/automation/handoffs/pre-phase10/` + +Use repository conventions where appropriate. + +Required artifacts: + +### `HANDOFF.md` + +Human-readable overview of the current accepted state and readiness. + +### `ACCEPTANCE.json` + +Machine-readable status. + +Include: + +- Schema version. +- Workstream ID. +- Source branch. +- Local commit. +- Verified remote commit, if available. +- Worktree cleanliness. +- Acceptance status. +- Entry-gate status. +- Test evidence references. +- Unresolved blocker IDs. +- Permissible deferrals. +- Required owner approvals. +- Generation timestamp. +- Recommendation for Phase 10. + +### `GATES.json` + +Define stage-specific gate requirements, including: + +- Required predecessor. +- Required test suites. +- Minimum acceptable evidence. +- Required Git state. +- Required preservation checks. +- Required manual approvals. +- Permissible conditional deferrals. +- Blocking findings. + +### `BLOCKERS.json` + +Structured unresolved-issue register. + +### `TEST_EVIDENCE.json` + +Index machine-verifiable test results and report artifacts. + +Include commit binding and actual process exit codes. + +### `MANUAL_ACCEPTANCE.md` + +Prioritised human test and approval checklist. + +### `PHASE10_BASELINE.md` + +Exact branch and commit ancestry, preservation scope, safe cleanup targets and required compatibility checks. + +### `READY_TO_RUN.md` + +Exact conditions required to start automated Phase 10. + +### `HANDOFF_SCHEMA.json` + +JSON Schema for the exported acceptance package. + +Validate all structured JSON. + +Use stable keys and explicit status enums. + +Do not include secrets, personal data or machine-specific credentials. + +Absolute local paths may be included as informational references, but prefer repository-relative paths for portable automation. + +--- + +# 13. Critical acceptance-security rule + +The handoff package is evidence, not authority by itself. + +A Codex-generated `ACCEPTANCE.json` must not be able to bypass a gate simply by claiming: + +`"status": "GO"` + +The orchestrator must independently verify: + +- Required report existence. +- Test exit codes. +- Commit correspondence. +- Remote publication. +- Accepted predecessor stages. +- Mandatory blocker status. +- Applicable owner approvals. + +Owner approvals must be maintained outside the model-writable repository or through another protected approval mechanism. + +Do not generate approval tokens or owner signatures. + +Do not mark human acceptance PASS without actual approval evidence. + +If the external orchestrator already defines an acceptance schema, conform to it where compatible rather than creating a conflicting parallel standard. + +If it is still under development, produce a clearly versioned proposed contract and document the integration requirements. + +--- + +# 14. P10-HANDOFF-09 — Phase 10 cleanup inventory + +Prepare the scope for the actual Phase 10 task. + +Identify proven superseded components and code. + +Include: + +- Legacy CV Editor components. +- Old CV import components. +- Replaced dashboard layout configuration. +- Superseded admin-processing views. +- Unused style utilities. +- Duplicate services. +- Unreferenced frontend routes. +- Obsolete feature flags. +- Potentially unused dependencies. +- Historical compatibility components that must remain. +- Database code with active compatibility requirements. + +For every proposed removal include: + +- Location. +- Why it appears obsolete. +- Evidence of actual replacement. +- Current consumers. +- Dynamic/runtime reference risks. +- Related preservation group. +- Required regression test. +- Removal risk. + +Do not remove these items as part of the handoff. + +Do not delete old PDF renderers, document mappings or migrations solely because newer implementations exist. + +Do not retire SQLite automatically. + +Do not perform MariaDB major-version upgrades. + +Phase 10 will make removal decisions using this evidence. + +--- + +# 15. P10-HANDOFF-10 — Reconcile the remaining roadmap + +The automation queue after Phase 10 is intended to contain: + +05 — Phase 10 final redesign cleanup. + +06 — PRODUCT-REVIEW-01 full application review. + +07 — INT-GLOBAL-JOBS-01 international, cross-industry job discovery. + +08 — I18N-01 expanded translations and locale qualification. + +09 — LAUNCH-SITE-01 multilingual homepage redesign. + +10 — SECURITY-AUDIT-01 adversarial audit and remediation. + +11 — RELEASE-READINESS-01 production qualification. + +Also preserve separate tracked initiatives: + +- Deferred P5-13 AI qualification and model assessment. +- LinkedIn integration feasibility. +- Android application. +- SQLite retirement. +- MariaDB upgrade strategy. +- Monitoring and operational improvements. +- Future country integrations. + +These initiatives must not be silently discarded simply because they aren't numbered 05–11. + +Highlight the dependencies: + +- Global Job Search depends on approved planning and provider permissions. +- Internationalisation overlaps with Global Job Search and homepage work. +- Product Review requires owner approval before starting its resulting implementation scope. +- Homepage final visual design requires owner approval. +- Production requires independent security, backup, recovery and release approval. + +Create an automation-friendly roadmap summary without starting any later workstream. + +--- + +# 16. Autonomous execution checkpoints + +Execute safely in this order: + +### AUTO-H01 — Baseline and acceptance reconciliation +Read the reports, verify actual Git state and establish existing evidence. + +### AUTO-H02 — Targeted defect remediation +Fix bounded confirmed pre-Phase-10 defects. + +### AUTO-H03 — PDF and AI qualification +Complete permitted verification and document remaining blocked items. + +### AUTO-H04 — Manual acceptance preparation +Produce focused human test packages and record genuine approvals. + +### AUTO-H05 — Git publication recovery +Publish pending development commits if the remote is available. + +### AUTO-H06 — Full regression +Establish commit-bound verification evidence. + +### AUTO-H07 — Structured automation handoff +Produce and validate schemas, gates, blocker registers and evidence manifests. + +### AUTO-H08 — Phase 10 readiness +Determine the actual acceptance decision and exact automation prerequisites. + +Commit and push validated checkpoints. + +If the remote is unavailable, continue safe independent work and preserve commits locally. + +Do not claim remote publication when it is unverified. + +--- + +# 17. Required final decisions + +Issue independent verdicts for: + +**Pre-Phase-10 UX:** GO / CONDITIONAL GO / NO-GO. + +**CV Integration:** GO / CONDITIONAL GO / NO-GO. + +**PDF Spacing:** PASS / PARTIAL / FAIL. + +**CV AI Accuracy:** PASS / PARTIAL / BLOCKED. + +**Human/Device Acceptance:** PASS / PARTIAL / NOT TESTED. + +**Python Security:** PASS / CONDITIONAL / BLOCKED. + +**Hosted CI:** PASS / BLOCKED / FAIL. + +**Preservation:** PASS / PARTIAL / FAIL. + +**Git Publication:** VERIFIED / BLOCKED. + +**Phase 10 Development Readiness:** GO / CONDITIONAL GO / NO-GO. + +**Automation Handoff Package:** READY / INCOMPLETE. + +**Production:** GO / NO-GO. + +Every verdict must cite actual supporting evidence. + +Distinguish implementation completion from acceptance, deployment and release readiness. + +--- + +# 18. Final report + +At completion, report: + +1. Current branch and final commit. +2. Working-tree status. +3. Remote publication state. +4. Defects fixed. +5. Tests executed and actual totals. +6. Outstanding mandatory blockers. +7. Permitted deferrals. +8. Human actions required. +9. Automation handoff artifacts created. +10. Acceptance schema validation result. +11. Phase 10 entry decision. +12. Exact integration baseline for the orchestrator. +13. Whether the orchestrator may start automatically. +14. What it must verify independently before doing so. + +If Phase 10 receives an authoritative GO or approved CONDITIONAL GO, mark the handoff eligible for orchestration. + +However, **do not actually begin Phase 10**. + +If required conditions remain outstanding, mark the stage BLOCKED and state exactly how it can become READY. + +--- + +# 19. Hard restrictions + +Do not: + +- Merge into `main`. +- Deploy production. +- Start Phase 10. +- Start Global Job Search. +- Start the Product Review. +- Modify the separate automation worktree. +- Fabricate owner approval. +- Self-approve acceptance exceptions. +- Bypass Python security qualifications. +- Modify live Ollama. +- Download unapproved production models. +- Change production MariaDB. +- Perform destructive database migrations. +- Modify production Docker services. +- Modify or repair production filesystems. +- Remove compatibility code prematurely. +- Lower test requirements to achieve a GO. + +Do not introduce unnecessary changes that disrupt the locally running `jobbjakt.local` environment. + +If a test requires destructive operations, use a disposable database or isolated test environment. + +--- + +# FINAL INSTRUCTION + +Starting from the real current Pre-Phase-10 acceptance state, complete all safely achievable outstanding acceptance and remediation work. + +Restore Git publication where possible. + +Prepare a **machine-readable, independently verifiable Phase 10 handoff** suitable for AUTONOMOUS-ROADMAP-01. + +Make the handoff robust enough that the orchestrator can identify: + +- What has passed. +- What is blocked. +- What may be deferred. +- Which human approvals are required. +- Which exact commit forms the accepted baseline. +- Whether Phase 10 may begin. + +Work autonomously, commit and push validated checkpoints, and prepare all necessary documentation. + **STOP after the final handoff report. Do not start Phase 10, merge into main or deploy production.** \ No newline at end of file diff --git a/docs/automation/handoffs/pre-phase10/package.test.mjs b/docs/automation/handoffs/pre-phase10/package.test.mjs new file mode 100644 index 0000000..7be90be --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/package.test.mjs @@ -0,0 +1,85 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import path from 'node:path'; +import crypto from 'node:crypto'; +import zlib from 'node:zlib'; +import { fileURLToPath } from 'node:url'; +import { validatePackage } from './verify.mjs'; + +const directory = path.dirname(fileURLToPath(import.meta.url)); +const artifactRoot = path.resolve(directory, '../../../../.artifacts'); +const hash = bytes => crypto.createHash('sha256').update(bytes).digest('hex'); +function shadow(change) { + const temporary = fs.mkdtempSync(path.join(artifactRoot, 'handoff-verify-')); + try { + fs.cpSync(directory, temporary, { recursive: true }); + change(temporary); + assert.throws(() => validatePackage(temporary)); + } finally { + const resolved = path.resolve(temporary); + assert.ok(resolved.startsWith(artifactRoot + path.sep) && path.basename(resolved).startsWith('handoff-verify-')); + fs.rmSync(resolved, { recursive: true }); + } +} +function json(directory, name, change) { + const file = path.join(directory, name + '.json'); + const value = JSON.parse(fs.readFileSync(file, 'utf8')); + change(value); + fs.writeFileSync(file, JSON.stringify(value)); +} + +test('complete evidence validates while Phase10 remains blocked', () => { + const result = validatePackage(); + assert.equal(result.integrity, 'PASS'); + assert.equal(result.phase10, 'BLOCKED'); + assert.equal(result.eligible, false); +}); +test('worker-written GO and approval-shaped data cannot advance', () => shadow(base => { + json(base, 'ACCEPTANCE', value => { value.phase10DevelopmentReadiness = 'GO'; value.eligibleForAutomaticExecution = true; value.ownerSignature = 'invented'; }); +})); +test('report from a different commit is rejected', () => shadow(base => { + json(base, 'TEST_EVIDENCE', value => { value.reports[0].sourceCommit = '0'.repeat(40); }); +})); +test('missing native artifact is rejected', () => shadow(base => { + const index = JSON.parse(fs.readFileSync(path.join(base, 'TEST_EVIDENCE.json'), 'utf8')); + const report = index.reports.find(item => item.nativeFormat); + fs.unlinkSync(path.join(base, index.artifacts.find(item => item.id === report.artifactId).path)); +})); +test('changed native bytes are rejected', () => shadow(base => { + const index = JSON.parse(fs.readFileSync(path.join(base, 'TEST_EVIDENCE.json'), 'utf8')); + const report = index.reports.find(item => item.nativeFormat); + fs.appendFileSync(path.join(base, index.artifacts.find(item => item.id === report.artifactId).path), 'changed'); +})); +test('rewriting a process hash cannot conceal its nonzero native exit', () => shadow(base => { + json(base, 'TEST_EVIDENCE', index => { + const report = index.reports.find(item => item.nativeFormat); + const artifact = index.artifacts.find(item => item.id === report.processArtifactId); + const file = path.join(base, artifact.path); + const data = JSON.parse(zlib.gunzipSync(fs.readFileSync(file)).toString('utf8')); + const keys = report.processPointer.slice(1).split('/'); + let parent = data; + for (const key of keys.slice(0, -1)) parent = parent[key]; + parent[keys.at(-1)] = 17; + const bytes = zlib.gzipSync(JSON.stringify(data)); + fs.writeFileSync(file, bytes); artifact.sha256 = hash(bytes); + }); +})); +test('omitting a source file from both manifests cannot claim a complete freeze', () => shadow(base => { + json(base, 'TEST_EVIDENCE', index => { + for (const id of [index.sourceManifestArtifactId, index.sourceAfterArtifactId]) { + const artifact = index.artifacts.find(item => item.id === id); + const file = path.join(base, artifact.path); + const data = JSON.parse(zlib.gunzipSync(fs.readFileSync(file)).toString('utf8')); + delete data[Object.keys(data)[0]]; + const bytes = zlib.gzipSync(JSON.stringify(data)); + fs.writeFileSync(file, bytes); artifact.sha256 = hash(bytes); + } + }); +})); +test('artifact paths cannot escape the imported package', () => shadow(base => { + json(base, 'TEST_EVIDENCE', index => { index.artifacts[0].path = '../../outside'; }); +})); +test('an imported schema cannot weaken the trusted schema', () => shadow(base => { + fs.writeFileSync(path.join(base, 'HANDOFF_SCHEMA.json'), '{}'); +})); diff --git a/docs/automation/handoffs/pre-phase10/verify.mjs b/docs/automation/handoffs/pre-phase10/verify.mjs new file mode 100644 index 0000000..c1cbe0f --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/verify.mjs @@ -0,0 +1,206 @@ +// Evidence validation only. Protected approvals and execution belong to the separate controller. +import fs from 'node:fs'; +import path from 'node:path'; +import crypto from 'node:crypto'; +import zlib from 'node:zlib'; +import { createRequire } from 'node:module'; +import { fileURLToPath } from 'node:url'; +import { execFileSync } from 'node:child_process'; + +const directory = path.dirname(fileURLToPath(import.meta.url)); +const root = path.resolve(directory, '../../../..'); +const dependencies = createRequire(path.join(root, 'job-tracker-ui/package.json')); +const Ajv = dependencies('ajv'); +const { JSDOM } = dependencies('jsdom'); +const digest = bytes => crypto.createHash('sha256').update(bytes).digest('hex'); +const demand = (condition, message) => { if (!condition) throw new Error(message); }; + +export function verifyBytes(bytes, expected) { + demand(Buffer.isBuffer(bytes) && /^[a-f0-9]{64}$/.test(expected) && digest(bytes) === expected, 'Missing or changed evidence'); +} + +export function measureNative(format, text) { + demand(Buffer.byteLength(text, 'utf8') <= 8 * 1024 * 1024, 'Native report exceeds its input bound'); + const result = { passed: 0, failed: 0, skipped: 0, retries: 0, unexecuted: 0, names: [] }; + if (format === 'trx') { + demand(!/ { + for (const spec of suite.specs ?? []) for (const item of spec.tests ?? []) { + result.names.push(`${spec.id}::${item.projectName}`); + const attempts = item.results ?? []; + result.retries += Math.max(0, attempts.length - 1); + if (!attempts.length) result.unexecuted++; + else if (attempts.at(-1).status === 'skipped') result.skipped++; + else if (attempts.at(-1).status === 'passed' && item.expectedStatus !== 'failed' && item.status === 'expected') result.passed++; + else result.failed++; + if (attempts.some(attempt => (attempt.retry ?? 0) > 0)) result.retries = Math.max(1, result.retries); + } + for (const child of suite.suites ?? []) visit(child); + }; + const report = JSON.parse(text); + demand(!(report.errors?.length), 'Browser report contains execution errors'); + for (const suite of report.suites ?? []) visit(suite); + } else if (format === 'pytest') { + result.passed = Number(text.match(/\b(\d+) passed\b/)?.[1] ?? 0); + result.failed = Number(text.match(/\b(\d+) failed\b/)?.[1] ?? 0); + result.skipped = Number(text.match(/\b(\d+) skipped\b/)?.[1] ?? 0); + } else if (format === 'unittest') { + const count = Number(text.match(/Ran (\d+) tests? in/)?.[1] ?? 0); + if (/^OK\s*$/m.test(text)) result.passed = count; + else result.failed = count || 1; + result.skipped = Number(text.match(/skipped=(\d+)/)?.[1] ?? 0); + result.names = [...text.matchAll(/^(test\S+ \([^\n]+\)) \.\.\. /gm)].map(match => match[1]); + } else if (format === 'node-test') { + result.passed = Number(text.match(/(?:#|ℹ) pass (\d+)/u)?.[1] ?? 0); + result.failed = Number(text.match(/(?:#|ℹ) fail (\d+)/u)?.[1] ?? 0); + result.skipped = Number(text.match(/(?:#|ℹ) skipped (\d+)/u)?.[1] ?? 0); + result.names = [...text.matchAll(/^(?:✔|✖|ok \d+ -|not ok \d+ -) (.+?)(?: \([\d.]+ms\))?$/gmu)].map(match => match[1]); + } else throw new Error('Unknown native report format'); + result.names.sort(); + result.membershipSha256 = digest(Buffer.from(JSON.stringify(result.names))); + return result; +} + +export function assertPass(result, exitCode) { + demand(exitCode === 0 && result.passed > 0 && !result.failed && !result.skipped && !result.retries && !result.unexecuted, 'Native result cannot qualify as PASS'); +} + +export function requireProtectedEntry() { + return { eligible: false, reason: 'External protected phase10-development-entry, candidate scope, qualified runtime and test adapter are required. This evidence validator grants no authority.' }; +} + +function readSafe(relative, maximum = 64 * 1024 * 1024, base = directory) { + demand(typeof relative === 'string' && !path.isAbsolute(relative) && !relative.split(/[\\/]/).includes('..'), 'Unsafe artifact path'); + const file = path.resolve(base, relative); + demand(fs.realpathSync(file).startsWith(fs.realpathSync(base) + path.sep), 'Artifact escapes package'); + const stat = fs.statSync(file); + demand(stat.isFile() && stat.size <= maximum, 'Missing or excessive artifact'); + return fs.readFileSync(file); +} + +export function validatePackage(base = directory) { + const readPackage = relative => readSafe(relative, 8 * 1024 * 1024, base); + // The schema is trusted verifier source, never replaced by an imported package's schema. + const schema = JSON.parse(readSafe('HANDOFF_SCHEMA.json')); + verifyBytes(readPackage('HANDOFF_SCHEMA.json'), digest(readSafe('HANDOFF_SCHEMA.json'))); + const ajv = new Ajv({ allErrors: true, jsonPointers: true }); + const validate = ajv.compile(schema); + const documents = {}; + for (const name of ['ACCEPTANCE', 'GATES', 'BLOCKERS', 'TEST_EVIDENCE']) { + const document = JSON.parse(readPackage(name + '.json')); + demand(validate(document), `Invalid ${name}: ${ajv.errorsText(validate.errors)}`); + documents[name] = document; + } + const evidence = documents.TEST_EVIDENCE; + demand(new Set(evidence.artifacts.map(item => item.id)).size === evidence.artifacts.length, 'Duplicate artifact IDs'); + demand(new Set(evidence.reports.map(item => item.id)).size === evidence.reports.length, 'Duplicate report IDs'); + for (const artifact of evidence.artifacts) verifyBytes(readPackage(artifact.path), artifact.sha256); + const artifact = name => { + const item = evidence.artifacts.find(entry => entry.id === name); + demand(item, 'Missing indexed artifact'); + const bytes = readPackage(item.path); + return item.path.endsWith('.gz') ? zlib.gunzipSync(bytes, { maxOutputLength: 8 * 1024 * 1024 }) : bytes; + }; + for (const report of evidence.reports) { + const expectedCommit = report.bindingScope === 'HANDOFF_VERIFIER' ? evidence.verifierCommit : evidence.testedCommit; + demand(report.sourceCommit === expectedCommit, 'Report source correspondence missing'); + let nativeExit = JSON.parse(artifact(report.processArtifactId).toString('utf8')); + for (const raw of report.processPointer.slice(1).split('/')) { + const key = raw.replaceAll('~1', '/').replaceAll('~0', '~'); + demand(nativeExit !== null && Object.hasOwn(nativeExit, key), 'Missing native process observation'); + nativeExit = nativeExit[key]; + } + demand(nativeExit === report.exitCode, 'Native process exit does not match the report'); + if (!report.nativeFormat) continue; + const measured = measureNative(report.nativeFormat, artifact(report.artifactId).toString('utf8')); + for (const key of ['passed', 'failed', 'skipped', 'retries', 'unexecuted']) demand(measured[key] === report.counts[key], `Wrong ${report.id} ${key}`); + demand(measured.membershipSha256 === report.membershipSha256, 'Changed report membership'); + if (report.status === 'PASS') assertPass(measured, report.exitCode); + } + const discovery = measureNative('playwright', artifact(evidence.ordinaryDiscoveryArtifactId).toString('utf8')).names; + const ordinary = evidence.ordinaryReportIds.flatMap(id => { + const report = evidence.reports.find(item => item.id === id); + demand(report?.nativeFormat === 'playwright' && report.status === 'PASS', 'Missing ordinary browser lane'); + return measureNative('playwright', artifact(report.artifactId).toString('utf8')).names; + }).sort(); + demand(new Set(ordinary).size === ordinary.length && JSON.stringify(ordinary) === JSON.stringify(discovery), 'Browser discovery differs from executed unique membership'); + const source = JSON.parse(artifact(evidence.sourceManifestArtifactId).toString('utf8')); + const after = JSON.parse(artifact(evidence.sourceAfterArtifactId).toString('utf8')); + demand(JSON.stringify(source) === JSON.stringify(after), 'Source drifted during the regression run'); + const prefixes = ['JobTrackerApi/', 'JobTrackerApi.Tests/', 'JobTrackerApi.MariaDb.Tests/', 'job-tracker-ui/', 'scripts/', 'tools/summarizer/', 'docs/pre-phase10-ux/', 'docs/redesign/phase-9/']; + const tracked = execFileSync('rtk', ['proxy', 'git', 'ls-files', '-z'], { cwd: root, encoding: 'utf8' }).split('\0').filter(name => prefixes.some(prefix => name.startsWith(prefix))).sort(); + demand(Object.keys(source).length <= 5000 && JSON.stringify(Object.keys(source).sort()) === JSON.stringify(tracked), 'Frozen source membership does not match the tracked qualification scope'); + for (const [name, expected] of Object.entries(source)) { + demand(!path.isAbsolute(name) && !name.split(/[\\/]/).includes('..'), 'Unsafe source path'); + const file = path.resolve(root, name); + demand(fs.realpathSync(file).startsWith(fs.realpathSync(root) + path.sep), 'Source escapes repository'); + verifyBytes(fs.readFileSync(file), expected); + } + const verifierFiles = JSON.parse(artifact(evidence.verifierSourceArtifactId).toString('utf8')); + const expectedVerifierFiles = ['verify.mjs', 'verify.test.mjs', 'package.test.mjs', 'verify_git.py', 'HANDOFF_SCHEMA.json'].map(name => 'docs/automation/handoffs/pre-phase10/' + name).sort(); + demand(JSON.stringify(Object.keys(verifierFiles).sort()) === JSON.stringify(expectedVerifierFiles), 'Missing verifier source membership'); + for (const [name, expected] of Object.entries(verifierFiles)) verifyBytes(fs.readFileSync(path.join(root, name)), expected); + execFileSync('rtk', ['proxy', 'git', 'merge-base', '--is-ancestor', evidence.verifierCommit, 'HEAD'], { cwd: root }); + execFileSync('rtk', ['proxy', 'git', 'merge-base', '--is-ancestor', evidence.testedCommit, 'HEAD'], { cwd: root }); + const delta = execFileSync('rtk', ['proxy', 'git', 'diff', '--name-only', evidence.testedCommit, 'HEAD'], { cwd: root, encoding: 'utf8' }).trim().split(/\r?\n/).filter(Boolean); + demand(delta.every(name => name.startsWith('docs/automation/handoffs/pre-phase10/')), 'Application changed after tested baseline'); + const declared = documents.ACCEPTANCE; + demand(declared.localCommit === evidence.testedCommit && declared.authority === 'EVIDENCE_ONLY' && declared.phase10DevelopmentReadiness === 'NO-GO' && declared.eligibleForAutomaticExecution === false, 'Unapproved entry claim'); + const ids = new Set(documents.BLOCKERS.items.map(item => item.id)); + demand(ids.size === documents.BLOCKERS.items.length, 'Duplicate blocker IDs'); + demand(declared.unresolvedBlockerIds.every(id => ids.has(id)), 'Unresolved blocker is not registered'); + const observedLocalCommit = execFileSync('rtk', ['proxy', 'git', 'rev-parse', 'HEAD'], { cwd: root, encoding: 'utf8' }).trim(); + const observedWorkingTreeClean = !execFileSync('rtk', ['proxy', 'git', 'status', '--porcelain'], { cwd: root, encoding: 'utf8' }).trim(); + const branch = execFileSync('rtk', ['proxy', 'git', 'branch', '--show-current'], { cwd: root, encoding: 'utf8' }).trim(); + demand(branch === declared.sourceBranch, 'Wrong checkout branch'); + return { integrity: 'PASS', testedCommit: evidence.testedCommit, observedLocalCommit, observedWorkingTreeClean, reports: evidence.reports.length, artifacts: evidence.artifacts.length, phase10: 'BLOCKED', ...requireProtectedEntry() }; +} + +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + try { + const result = validatePackage(); + if (process.argv.includes('--verify-remote')) { + const branch = 'refs/heads/test/pre-phase10-ux-acceptance'; + const line = execFileSync('rtk', ['proxy', 'git', 'ls-remote', '--exit-code', 'origin', branch], { cwd: root, encoding: 'utf8', timeout: 45000 }).trim(); + demand(line === `${result.observedLocalCommit}\t${branch}`, 'Remote HEAD differs from current local HEAD'); + result.currentRemotePublication = 'VERIFIED'; + } else result.currentRemotePublication = 'NOT_RECHECKED'; + console.log(JSON.stringify(result, null, 2)); + if (process.argv.includes('--require-ready')) process.exitCode = 3; + } catch (error) { + console.error(error.message); + process.exitCode = 1; + } +} diff --git a/docs/automation/handoffs/pre-phase10/verify.test.mjs b/docs/automation/handoffs/pre-phase10/verify.test.mjs new file mode 100644 index 0000000..2f84962 --- /dev/null +++ b/docs/automation/handoffs/pre-phase10/verify.test.mjs @@ -0,0 +1,35 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { measureNative, verifyBytes, assertPass, requireProtectedEntry } from './verify.mjs'; + +test('native Jest membership and counters agree before PASS', () => { + const result = measureNative('jest', JSON.stringify({ numTotalTests: 1, numPassedTests: 1, numFailedTests: 0, numPendingTests: 0, testResults: [{ name: 'fictional.test.ts', assertionResults: [{ fullName: 'preserves facts', status: 'passed' }] }] })); + assert.equal(result.passed, 1); + assertPass(result, 0); +}); +test('zero, failing, skipped or retried results cannot qualify', () => { + for (const patch of [{ passed: 0 }, { failed: 1 }, { skipped: 1 }, { retries: 1 }]) + assert.throws(() => assertPass({ passed: 1, failed: 0, skipped: 0, retries: 0, ...patch }, 0)); + assert.throws(() => assertPass({ passed: 1, failed: 0, skipped: 0, retries: 0 }, 17)); +}); +test('tampered or missing evidence is rejected', () => { + assert.throws(() => verifyBytes(Buffer.from('changed'), '0'.repeat(64))); + assert.throws(() => verifyBytes(null, '0'.repeat(64))); +}); +test('model-written GO and approval-shaped JSON cannot authorise Phase10', () => { + assert.equal(requireProtectedEntry({ status: 'GO', approved: true, ownerSignature: 'invented' }).eligible, false); +}); +test('discovery counters cannot masquerade as an executed browser test', () => { + const report = { suites: [{ specs: [{ id: 'sample', tests: [{ projectName: 'chromium', results: [] }] }] }], stats: { expected: 1 } }; + const result = measureNative('playwright', JSON.stringify(report)); + assert.throws(() => assertPass(result, 0)); +}); +test('JUnit counters alone are not execution membership and entities are refused', () => { + assert.throws(() => assertPass(measureNative('junit', ''), 0)); + assert.throws(() => measureNative('junit', ']>')); + const result = measureNative('junit', ''); + assert.equal(result.passed, 1); +}); +test('oversized native reports are rejected before parsing', () => { + assert.throws(() => measureNative('jest', ' '.repeat(8 * 1024 * 1024 + 1))); +}); diff --git a/docs/automation/handoffs/pre-phase10/verify_git.py b/docs/automation/handoffs/pre-phase10/verify_git.py index 6d10b84..75f6fce 100644 --- a/docs/automation/handoffs/pre-phase10/verify_git.py +++ b/docs/automation/handoffs/pre-phase10/verify_git.py @@ -1,6 +1,7 @@ """Bounded read-only Gitea diagnostics; credentials remain in Git's configured helper.""" import datetime import json +import os from pathlib import Path import socket import ssl @@ -20,6 +21,8 @@ def main(): return result url = git('remote', 'get-url', 'origin').stdout.strip() assert url == 'https://git.cesnimda.uk/cesnimda/jobtrackingapp.git' + assert os.getenv('GIT_SSL_NO_VERIFY', '').lower() not in ('1', 'true', 'yes'), 'Git TLS verification is disabled in the environment' + assert git('config', '--get-urlmatch', 'http.sslVerify', url).stdout.strip().lower() not in ('false', '0', 'no'), 'Git TLS verification is disabled for this remote' record = dict(observedUtc=datetime.datetime.now(datetime.timezone.utc).isoformat(), remote=url, localCommit=git('rev-parse', 'HEAD').stdout.strip(), tlsVerificationDisabled=False) try: