UCCA engine — current runnable state¶
As at 2026-07-31 UTC. Read from the deployed substrate, not from design documents. Where the substrate and our own canon disagree, the substrate is reported and canon is left alone.
RTOpacks asked for rough, incomplete and honest, and said a long "what breaks" section is a good sign. §5 is the longest section in this document.
0. The three things that matter most for your scoping¶
0.1 — The engine has been run on exactly one real unit of competency, and zero qualifications. (B)
69 jobs have ever been submitted. Across all 69 payloads there are two distinct codes: CHCPRT025 (64 jobs) and a literal placeholder X (2 jobs). Three further jobs are reverify, which targets a prior job and carries no code of its own.
Your request describes a thin thread where "one qualification goes into the engine." The engine has never been given a qualification. It has been given fragments of one unit, 64 times, in three directions. Everything this document says about timing, cost, failure rates and output shape is a statement about CHCPRT025 and should be read that way. We do not know how it behaves at that scale because it has never been asked — and §0.3 sets out why a qualification is not a thing this engine's contract can be handed at all.
And "one unit" is itself generous. CHCPRT025 carries three elements. Canonicalised and hashed, the 45 forward payloads resolve to four distinct triumvirates, not one: 31 jobs ran a one-outcome payload — a single element of three — 9 ran the complete three-element unit, 3 ran a two-outcome payload, and the 2 X rows carried none. The bulk of this engine's record is roughly a third of one unit. Every timing, cost and failure figure below is weighted accordingly, and the weighting runs in the direction that flatters us. Read §6 knowing that its median is mostly a median of one-element runs.
0.2 — Nothing in version control submits a job. (B)
The path from a unit code to an accepted job is a human with a bearer token. Searched and found empty: all six repositories, the four non-repo workspace directories, the deployed operator console, ~/bin, ~/scripts, Downloads, Desktop, Documents, every *.sh, Makefile, justfile and package.json script, every API-client collection format, and all six deployed cron triggers — of which the only reasoner cron is the stuck-job detector, not a submitter. Six Python files in the engine make outbound POSTs; their targets are keys.ucca.online, Moodle, Auth0/Twilio, TGA and internal bindings. None targets the gate.
The surviving shell history (6,076 lines) returns zero hits for the gate host or route. That file carries no timestamps, so we cannot establish it covers the July 19–22 period, and we are not reporting it as proof.
We have not written one to fill the gap, and we will not describe the shape one would have.
What this means in practice: the back half of the engine is real, deployed and unattended. The front half is a person. Any plan that assumes a callable pipeline should treat "build the submitter" as in scope.
0.3 — One job carries one obligation. A qualification is not an input this engine accepts. (D)
This is the third scoping fact, and it may matter more than the other two, because it is not a gap to be filled — it is a boundary to design around.
The gate's structural check names three field paths (workers/gate/src/index.js, structureFault()): job_type, triumvirate, and triumvirate.outcomes — the last requiring a non-empty array whose members each carry a non-empty string outcome_number. It names nothing else. There is no unit, no qualification, no course, and no domain vocabulary of any kind. The frozen v1 content payload carries one source_code — a single string, not a list.
The word "qualification" does not appear in the gate, and does not appear in the reasoner's code. Its only occurrences anywhere in the reasoner package are in the calibration probes, where it means equipment qualification — installation, operational, performance. A different word in a different domain, which is the neutrality rule visible in the substrate rather than merely asserted.
So a twelve-unit qualification is twelve jobs and twelve envelopes. How a qualification decomposes into obligations, in what order they are submitted, and what context each carries are decisions this engine does not make and holds no opinion about. It accepts a triumvirate and reasons about that triumvirate.
And nothing on our side assembles twelve envelopes into a qualification-level artefact. We are naming the gap, not specifying how it should be closed — that is not ours to design, and we are not going to describe the shape of it.
This is the one rule showing its edge. The engine reasons and raises its hands; it never signs. The accountable judgement stays with you — and so, necessarily, does the composition of what is being judged.
1. Input — what you hand it¶
The throat is one HTTP endpoint. (D, read from the deployed gate bundle)
POST https://submit.ucca.online/v1/jobs
Authorization: Bearer <token>
Content-Type: application/json
202 -> { "job_id": "<uuid>", "status": "accepted" }
GET https://submit.ucca.online/v1/jobs/{job_id} (same bearer)
A job you do not own returns 404, not 403 — deliberate; the gate does not confirm the existence of other clients' jobs.
Four job types (workers/gate/src/index.js:28): generation · diagnosis · edit · reverify.
The generation payload, as it actually arrives — measured over 41 of 41 live generation payloads, not read off a schema (B):
| shape | count | keys |
|---|---|---|
| six-key | 39 | triumvirate_schema_version · source_code · title · application · outcomes · validation |
| three-key subset | 2 | the 141-byte pair of 2026-07-19 — the two placeholder rows in §0.1 |
outcomes is an array; each entry carries outcome_number and its requirement references. As of the 2026-07-31 deploy the gate requires outcomes to be a non-empty array whose every entry carries a non-empty string outcome_number — before that deploy it required only truthiness, which is how the two placeholder payloads got in.
Two things about this contract you should not have to discover by trying:
outcome_numberis a string. It was undeclared in the frozen contract until an erratum on 2026-07-31. Historical payloads carry both strings and integers — 9 of 69 jobs carry integers. The declaration is nowstring; the gate now enforces it.requirement_ref— the other half of the pair the engine's trace check compares — is typed in NO frozen schema at all. The generator happens to emit it in the same type as the input across all 26 forward envelopes we measured. That is a by-construction property, not a contract, and you should not build against it. It is owed into the next contract revision.
The throat consumes an already-compiled normal form. It does not read a unit from a registry and it does not compile one. Something upstream must turn a unit of competency into the triumvirate shape above. Where that compiling adapter lives is not settled between our two houses and it is the likeliest place we have made different assumptions — see §8.2.
instruments are read by nothing. Zero of 69 payloads carry them, and outcome_specification has zero occurrences anywhere in the codebase. If your design assumes instruments reach the reasoner, they currently do not.
Rejections return { error_code, severity, phase, affected_element, message, remediation }. affected_element became populated on 2026-07-31 and was NULL on every prior rejection — see §5.7.
2. Output — what comes out¶
2.1 — The terminal artefact is a signed UCCO envelope, written to R2 at default/envelopes/{job_id}.json. (A)
Its structure:
ucco_version: "v1"content_payload—obligation_ref,material_digest(sha256 of the material reasoned over), andfindings[], each carryingelement_ref,state, andanchors[]of{section_id, quote}. The verbatim quote is inside the artefact, which is what makes aTRACEDclaim checkable by a reader instead of trusted.provenance—run_id,direction,assembled_atseal—content_hash, RSA-PSS-SHA256signature,key_version,signed_at,verification_method: https://keys.ucca.online/v1/public-key/v1
And the field that matters most to your surface design:
The seal declares, in the artefact itself, that the signature attests provenance and not the correctness of the findings. The engine raises hands; it never signs is not a policy we wrote about this system in a document — it is a field in the output, and it is machine-checkable. The accountable judgement stays with a human on your side.
2.2 — One real example, verbatim, warts and all
default/envelopes/9a57fdce-1c6c-4b61-90d7-859020671ca5.json — 1,939 B, retrieved by exact key, status 200. (A)
It is a backward-direction (diagnosis) envelope. It ran on a public Australian unit code against UCCA-authored synthetic prose — not on any material you supplied. We state that rather than conceal it.
And it was subsequently REVOKED — default/revocations/9a57fdce-1c6c-4b61-90d7-859020671ca5.json exists. You asked for warts and all. This is a credential that was issued, sealed, and then withdrawn, which makes concrete the thing we told you in the abstract: our credentials expire and are revocable by design. If your surface caches a rendering, the rendering outlives the claim.
{"ucco_version": "v1", "content_payload": {"obligation_ref": "CHCPRT025", "material_digest": "sha256:650d272dc7fbee39507565c2fc072da6333b510671f8eb5805ab7f5448ee2759", "findings": [{"element_ref": "1", "state": "TRACED", "anchors": [{"section_id": "S1", "quote": "The worker observes and documents specific indicators that a child or young person may be at risk of harm, including physical, emotional, and behavioural signs."}]}, {"element_ref": "2", "state": "TRACED", "anchors": [{"section_id": "S2", "quote": "Upon forming a reasonable belief, the worker reports the concern to the relevant statutory child protection authority without delay and records the disclosure accurately."}]}]}, "provenance": {"run_id": "9a57fdce-1c6c-4b61-90d7-859020671ca5", "direction": "backward", "timestamps": {"assembled_at": "2026-07-22T09:04:16.589Z"}, "obligation_ref": "CHCPRT025", "material_digest": "sha256:650d272dc7fbee39507565c2fc072da6333b510671f8eb5805ab7f5448ee2759"}, "seal": {"content_hash": "sha256:WalnGSATaxpp1WZ/v7BfAN3MifNIfp3UlxS3JMFsdTM=", "signature": "TiNDJVGj/N0BbUw67QUt5NN3K/QmbeeQiHKGGDDu5nTJArkuX7HeGGE8WnhRLTxxMPzb/h/Kv6fMWUbtviEoyHWNftUr5Lyya48ASXkRCQIBKBk74uwzdNRVWN5iPRyh1fiMka8T+4UBJnYc8og7NJ/LG4L504iVpbNPB3q3NMk9XbEhp1lu3SDkMWiun224JfeENJ7DCQUwew9nCpyiMNbHPbdlrvm/hRBTiOpV5H9oxbAu7TE2V+LsbD5RHrliO9Y4tt7JlPVTES1fqh2m/s0+rIy5Ok5QFCSbf8iQgjr40brnMX35BhXo48EzKUJv7DHNYLYSlzf410c6H+MHAG8Kwc7VBEDAQ2VlDoYmM6swa541z2hxouD9HU+rsn0z2fJbbpqgDTppxii0LxBidMvYdAlAJc9EqjBh2EtJ2rouaFkmu+Wza0/KAyAilhW/6hySs5h+jpHvPJtclXeOLUiTGmKZ0AB3k5w3FbWhxsp3ujMA6QdJqiZWdrvUOuYjQFQhVK4vGIHMByzQU8sQuwIASQFV2albSGcA8On4EEPb5znI+oYCc6uWU6FDduh8BSq4uJJ/8iCvw+hIFTEGN7+Rh6KAiUCWw+7pzaz9nNK+8uD2wgBgmOyTdB3XIGOP24MYaCaBDBle3LcsnTFoJ53dlCmIAJE7JqCVzJfpXEM=", "key_version": "v1", "algorithm": "RSA-PSS-SHA256", "signed_at": "2026-07-22T09:04:16.888Z", "verification_method": "https://keys.ucca.online/v1/public-key/v1", "attests": "provenance-only"}}
2.3 — It is not human-readable, and there is no renderer. What you receive is machine output because that is what it is. Turning an envelope into something an RTO staff member can read is unassigned work and it is not ours by default — it is the first thing your thin thread will hit after the loop closes.
3. How it is invoked¶
Answered in full at §0.2. Restated in your terms:
- Is a human needed part-way through? A human is needed at the start, and that is the only place. Every run in this engine's history began with a person. (B)
- Does it run start-to-finish unattended? The back half does, and it is proven. Once a job is accepted,
queue → container → reasoner → signed envelope in R2runs with nobody present. The evidence is 43 completed jobs and, independently, a stuck-job detector on a*/5cron that has fired five times without a human. (B) - Command line, script, HTTP endpoint? HTTP,
POST /v1/jobswith a bearer token. But no client for it exists in version control — not a CLI, not a script, not a saved request collection. - Scheduled or triggered? No. Six cron triggers are deployed across the mount; none submits a job.
4. What it has actually been run on¶
All figures from D1 job rows and the 69 R2 payload objects, live read 2026-07-31T12:07:45Z. (B)
| count | |
|---|---|
| jobs ever submitted | 69 |
| completed | 43 — 40 writing a signed envelope, 3 reverify |
| failed, every one sealed with a named disposition | 26 |
| R2 and D1 reconcile exactly | zero orphans in either direction |
By code:
| code | jobs | job types | of which submitted on RTOpacks' credential |
|---|---|---|---|
CHCPRT025 |
64 | generation 39 · diagnosis 21 · edit 4 | 10 |
X (literal placeholder) |
2 | generation | 0 |
(none — reverify targets a prior job) |
3 | reverify | 3 |
Those 64 jobs did not all run the same input. The unit carries three elements; the 45 forward payloads resolve to four distinct triumvirates — 31 one-outcome, 9 complete, 3 two-outcome, 2 empty (the X rows). See §0.1.
When: 2026-07-03 through 2026-07-22. The failure cluster is tightly grouped at 2026-07-03/04.
One point of housekeeping, stated because it is your credential. Thirteen job rows carry client_id = 'rtopacks'. None of them is work you submitted. They are this house's own test traffic, submitted by Tim by hand from this side, nine minutes after minting the credential. We told you earlier that seven rows carried your identity; the true figure is thirteen — seven generation, three diagnosis, three reverify — and that correction has already crossed. The remaining 56 rows carry a NULL client.
A number we got wrong twice and are now stating with its slice attached, because it bears on anything you compute from our figures:
| slice | total | client_id IS NULL |
rtopacks |
|---|---|---|---|
| all rows | 69 | 56 | 13 |
| generation only | 41 | 34 | 7 |
| forward (generation + edit) | 45 | 38 | 7 |
Both of our earlier figures were correct for what they measured and neither said what it was measuring. We have adopted a convention: every count states its slice in the same breath.
The drift-check we owe you, logged and not resolved. The one obligation this engine has ever reasoned over is an Australian VET unit. The envelope's obligation_ref is an opaque string and the reasoning runs over the triumvirate shape rather than over anything VET-specific, so nothing in the artefact is structurally VET-bound — but the only real runs on record are VET-shaped, and that is a fact about our evidence, not a claim about the engine.
5. What breaks¶
You said a long section here is a good sign. Nine items, each sourced, plus the failure distribution.
5.1 — Three of the gate's seven error codes cannot fire. (D, re-verified in the deployed bundle after the 2026-07-31 deploy) adapterSignatureOK, referencesOK and limitsOK are unconditional return true, so GATE_SIGNATURE, GATE_REFERENCES and GATE_LIMITS are dead. Reachable codes are GATE_STRUCTURE, GATE_SCHEMA_VERSION, GATE_UNVALIDATED and GATE_AUTH. You named this class of defect back at us first, and your framing was the sharper one — a populated string implying a protection to every reader who does not hold the convention. We deployed twice today and they are still dead. Do not treat the presence of a code as evidence of the check.
5.2 — validation is checked for presence only. validationBlockOK(t) { return !!t?.validation; }. Any truthy value passes. There is no validation of the validation block.
5.3 — /_build cannot distinguish two builds, on either surface. The gate returns a hardcoded { surface: "gate", version: "0.1.0-spine" } — two of the four fields our own standard mandates, with commit and built_at absent entirely. It reads identically before and after a deploy that changed the accepted input contract. A present endpoint returning a plausible, unchanging answer is worse than an absent one, because it is trusted. We caught this while giving a deploy the go-ahead, against our own confirmation method. It is unfixed.
5.4 — 22 Workers are deployed; our own canon describes roughly six. ucca-transcript-signer, ucca-authz and ucca-status-reader were created 22–23 July and appear in no substrate table we maintain. The reasoner container is at v35 against baselines written for v28. Nothing here is asserted wrong — we are telling you our documentation lags our deployment, so that you weight the substrate over anything we have written.
5.5 — Two failure modes remain unruled. They are carried as open in every internal handover and have not been decided. We are not going to pretend they are decided by omitting them.
5.6 — A correction to our own prior statement, made here rather than quietly. We previously described the async-ack silent-strand gap — a container death after acknowledgement stranding a job row at running with no queue safety net — as open. It is closed. The detector is deployed on a */5 cron and has fired five times, sealing rows as STUCK_QUEUE_TIMEOUT. The error was ours, in a document written this morning, and it is corrected here.
5.7 — Rejection diagnostics changed today and old rejects do not look like new ones. gate_rejects.fault_location is NULL on 12 of 12 recorded rejections, the most recent dated 2026-07-21. From the 2026-07-31 deploy, rejections name the failing contract field in affected_element. No post-deploy rejection exists yet, so the new behaviour is deployed and unwitnessed in rows. If you read our reject history you are reading the old contract.
5.8 — requirement_ref is typed in no frozen schema. See §1. The pair it is compared against is now declared; it is not.
5.9 — course_code cannot yet be null. A v1.1 change making it nullable is ruled and not built. If your thin thread submits without a course code, it will be rejected until that lands. This is a hard gate on your beta and it is the one item in this section we expect to block you first.
Failure distribution across the 26 sealed failures (B):
| disposition | count |
|---|---|
QUEUE_WEDGE_CONTENTION |
11 |
JOB_STEP_RETRY_EXHAUSTED |
7 |
STUCK_QUEUE_TIMEOUT |
5 |
QUEUE_PURGED_CONSUMER_WEDGE |
3 |
All 26 carry a populated completed_at; none is NULL. Job rows in this engine are permanent — a wedged or purged row seals as failed with a named disposition and is never deleted. That rule held across the whole corpus when we checked it.
And the one that is a genuine wart with a name on it. Two envelopes in the store are unsound: the two X-coded placeholder jobs, 86471a69 and 6ca3ba79. They carry no title and no outcomes, and they sealed over an empty trace map — the engine issued a credential that traced nothing, because nothing in the pre-deploy contract stopped it. Both halves of that hole were closed on 2026-07-31: the gate now refuses the input, and the assembler now refuses to seal an artefact whose trace map does not cover every input requirement. The two bad envelopes still exist and their disposition — record or revoke — is not yet decided.
6. Timing and cost¶
Wall-clock, generation, completed jobs only, n = 22 (B):
| seconds | |
|---|---|
| min | 15 |
| median | 207.5 |
| mean | 318 |
| max | 1,178 (19.6 min) |
Use the median. The mean sits at the 64th percentile of this distribution — it is the flattering figure, and our own build notes' "6–12 min" estimate is not supported by the rows. And read it against §0.1: 31 of the 45 forward payloads carried a single outcome of three, so this median is mostly a median of one-element runs and will understate a complete unit — by more again a qualification.
Cost is metered widely and priced narrowly (B):
- The
cognitive_costtable holds 202 rows across 44 distinct jobs — so 44 of 69 jobs are metered, capturing 81,743.9 neurons. - Only 35 rows across 7 jobs carry a
cost_usd. 167 rows are NULL.
Why, established from rows rather than inferred:
pricing_source |
rows | jobs | NULL cost | window |
|---|---|---|---|---|
unknown_model |
145 | 25 | 145 | 07-03 → 07-21 |
| (NULL) | 22 | 12 | 22 | 07-04 → 07-21 |
workers_ai_neurons |
22 | 4 | 0 | from 07-21T07:59 |
repo_pinned |
13 | 3 | 0 | 07-03, an 18-minute window |
Metering works; pricing does not. A USD figure appears only where a pricing source could resolve the model. Where it could not, the run was measured accurately and priced at nothing.
So: we cannot give you a defensible cost per run. The seven priced jobs have a median of $0.052 and total $0.268, and we are telling you the denominator rather than quoting the number alone.
7. Where output currently lands¶
Cloudflare R2, one bucket. (A)
ucca-artefacts — 177 objects, every one accounted for:
| prefix | count | what it is |
|---|---|---|
default/payloads/ |
69 | the input to each run, keyed by job id |
default/calibration/ |
45 | 43 calibration records + 2 failure markers |
default/envelopes/ |
40 | the terminal artefact |
default/diagnostics/ |
12 | 7 failure.json + 5 stuck-sweep.json |
authz/ |
5 | authorisation records |
default/reverify/ |
3 | re-verification records |
default/costprobes/ |
2 | both 2026-07-27 |
default/revocations/ |
1 | one credential has actually been revoked |
Four other buckets exist and hold no engine output: ucca-admin-inventory (one inventory file), ucca-ir-assets (site assets), ucca-terraform-state (IaC state), and ucca-backups — which we did not open at all this pass, deliberately, because it carries a prefix that may hold your material. We describe it and do not enumerate it.
D1 is the truth store. Five databases. The jobs table lives in ucca-input-path, not in engine-db-oc as some of our older documents say — engine-db-oc holds 60 tables and no jobs table. Five KV namespaces support the spine.
Nothing lands on local disk. There is no filesystem output path.
8. What it needs that it doesn't have¶
8.1 — A submitter. See §0.2. This is now the first item on the list and it was not on any list before today.
8.2 — The compiling adapter, and this is the keystone. The throat takes a compiled normal form and no component we can find compiles one from a unit of competency. Internally we carry "instruments 2 & 3 reaching the reasoner" as open and keystone-class. On current evidence this is the single blocker to a second house running the loop, and it is the tier-1 question where our two houses are most likely to have assumed different answers. We are not going to guess which side you expected it on.
8.3 — A renderer. §2.3. Unassigned.
8.4 — Nullable course_code. §5.9. Ruled, not built.
8.5 — Two credentials we do not hold. The R2 Terraform state backend keys exist in no vault file under any name, so terraform plan cannot run and infrastructure drift is unproven rather than proven-zero. No infrastructure changed in today's deploys, so the expected diff is zero from configuration alone — but we are not claiming it as measured.
8.6 — Dependency exposure, examined and bounded. Two critical alerts on the surfaces repository are one advisory: GHSA-5xrq-8626-4rwp / CVE-2026-47429, vitest < 3.2.6 — arbitrary file read and execute when the Vitest UI server is listening. Both are in dev lockfiles; vitest is absent from dependencies in both packages and referenced only in test files. Not reachable in any deployed surface. Remediation is a version bump. The remaining 189 high / 220 moderate / 59 low are unexamined and we say so.
8.7 — Decisions owed on our side, which we list so you are not waiting on them silently: the disposition of the two unsound envelopes; the two unruled failure modes; the type declaration for requirement_ref; and whether the input triumvirate gets a frozen schema at all, which it currently does not have.
9. What this document does not claim¶
It does not describe the engine as designed, as intended, or as it will be. It makes no commitment and constitutes no agreement about scope, per your own framing.
Where we could not establish something we have said so rather than reason around it: the reach of the shell-history negative in §0.2; the full set of Worker secrets, which we could not enumerate because Cloudflare's API was returning 521/525 on Workers sub-resources at read time — a live fault, retryable, not a permission problem; and the completeness of one filesystem sweep that timed out.
One superseded statement of our own, corrected rather than repaired. UCCA-CROSSING-ENGINE-STATE-RESPONSE-01 §2 told you this house's drafting layer "cannot enumerate object storage." That was true when written on 2026-07-30 and false about twenty hours later. We have not amended the filed crossing's bytes — filed artefacts are historical — and this document supersedes the claim.
10. Filing and carry¶
Owed before this crosses:
- The §2.2 seam closed — the verbatim envelope pasted in, with byte count and sha256 recorded here and confirmed against 1,939 B.
- Filed to
ground/, then tocanon/sent/. Filing precedes relay, always. - The fence permits one crossing in flight. Two artefacts are filed and awaiting carry:
UCCA-CROSSING-TIER1-QUESTIONS-ANSWER-01rev 2, filed 2026-07-31, and this document, filed 2026-08-01. Sequencing is Tim's; this document does not move itself.
| envelope bytes | 1,939 B — confirmed against the stated figure, retrieved by exact key, GET only |
| envelope sha256 | 50715e26dd48a542754c7a1fc7cc252b984a77a74984819844545e2a2110e689 |
| this document's digest | derived at filing, from the committed git object |
Authored by UCCA Inc. Engine-side. Crosses verbatim under FENCE-PROTOCOL-01; authorship stays home.
RECEIPT-CHECK: echo this line's end before acting.