diff --git a/PUBLICATION-CHECKLIST.md b/PUBLICATION-CHECKLIST.md index 4f3eae7..248726c 100644 --- a/PUBLICATION-CHECKLIST.md +++ b/PUBLICATION-CHECKLIST.md @@ -8,6 +8,11 @@ Use this before making the repository public. - [ ] Confirm README links resolve from the repository root. - [ ] Confirm RFC drafts still say HACP is a working draft, not a standard. - [ ] Confirm schemas and examples validate against the current draft intent. +- [ ] For HACP v0.3 candidate material, confirm owner-accepted external proof + exists for single-consumer admission, restart readback, + claim-before-start failure (reject successor start without durable + readback of its accepted claim), ambiguous execution reporting, and + expiry/revocation ordering before merging the consumption-contract draft. - [ ] Confirm issue templates or discussion settings are ready for public review. - [ ] Decide whether to publish as a personal repo first or move under an diff --git a/README.md b/README.md index 24039ef..63a496c 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,9 @@ Start here: public-safe WITS v0 source packet for task packets, agent reports, human decision gates, evidence, stop reasons, transport envelopes, and fixture candidates. +- [docs/source-packets/wits-v0/accountable-continuation-v0.3-draft.md](docs/source-packets/wits-v0/accountable-continuation-v0.3-draft.md): + HACP v0.3 candidate source packet for one-successor consumption receipts, + fail-closed extension processing, and accountable continuation evidence. - [docs/security-boundaries.md](docs/security-boundaries.md): authority, report, match-proof, human-decision, digest-domain, and fail-closed boundaries. @@ -248,8 +251,10 @@ Start here: - [docs/review-packet.md](docs/review-packet.md): severity-ordered review packet for the 0.2 draft. -HACP 0.2 is not 1.0. It is a draft vocabulary and fixture set for review and -independent implementation feedback. +HACP 0.2 is not 1.0. HACP v0.3 material is an even earlier source-packet +candidate, not a released schema or conformance profile. Both are draft +vocabulary and fixture material for review and independent implementation +feedback. For maturity framing across v0.1 and v0.2, see [Stability Lanes](#stability-lanes). @@ -291,6 +296,13 @@ is reviewable through the 0.2 docs, schemas, profile registry, and fixtures listed above. It should not be described as HACP 1.0 or as generally compliant until independent implementations and conformance fixtures exist. +## HACP v0.3 Candidate Status + +HACP v0.3 candidate material is source-packet-level only. It explores +accountable continuation, consumption receipts, successor invocation evidence, +and extension fail-closed behavior. It does not define a released schema, +runtime, worker launch path, hosted execution surface, or product feature. + ## HACP v0.1 Draft Completeness The current draft set is minimally reviewable as a v0.1 protocol sketch. It is @@ -328,8 +340,9 @@ RFC-0008 transport-boundary checks. ## Core Invariants 1. Human authority is explicit and cannot be silently delegated away. -2. Authority comes from an approved task packet, not from the mechanism that - transports the packet. +2. Authority originates with a human approval act and is recorded or referenced + by an approved task or authority packet, not by the mechanism that transports + the packet. 3. Manual and automated transport are different layers. Moving a packet does not widen the packet's authority. 4. Closed vocabularies must not silently widen. Profiles may extend them only @@ -363,6 +376,12 @@ The v0.2 public review surface is the draft chain-of-custody packet: - the v0.2 fixtures in [fixtures/happy-path/](fixtures/happy-path/) and [fixtures/risk-cases/](fixtures/risk-cases/). +The v0.3 candidate review surface is source-packet material only: + +- [docs/source-packets/wits-v0/accountable-continuation-v0.3-draft.md](docs/source-packets/wits-v0/accountable-continuation-v0.3-draft.md); +- candidate JSON sketches in + [docs/source-packets/wits-v0/examples/](docs/source-packets/wits-v0/examples/). + Implementation-specific trial artefacts are not required to review this public draft. Future releases may add public evidence bundles, conformance test fixtures, and independent implementation reports. diff --git a/docs/hacp-0.2.md b/docs/hacp-0.2.md index dfdf5ea..67b0cc5 100644 --- a/docs/hacp-0.2.md +++ b/docs/hacp-0.2.md @@ -54,7 +54,8 @@ authority packet form multiple chains that share an authority origin. The owner-approved work unit. It defines scope, authority, allowed surfaces, forbidden surfaces, stop conditions, verification expectations, and the decision -boundary. It is the origin of bounded authority. +boundary. It records or references bounded authority that originates in a +human approval act; the packet is not an authority source by itself. HACP 0.2 renames the v0.1 "task packet" concept to "authority packet" to make the authority origin explicit. v0.1 task packets and v0.2 authority packets are diff --git a/docs/source-packets/README.md b/docs/source-packets/README.md index bf2e848..6b253fb 100644 --- a/docs/source-packets/README.md +++ b/docs/source-packets/README.md @@ -11,6 +11,9 @@ the normal RFC, schema, profile, and fixture process. ## Packets - [WITS v0 HACP source packet](wits-v0-hacp-source-packet.md) +- [WITS v0 accountable continuation source packet](wits-v0/accountable-continuation-v0.3-draft.md) + for HACP v0.3 candidate consumption receipts, successor invocation evidence, + and fail-closed continuation boundaries. ## Boundaries diff --git a/docs/source-packets/wits-v0/accountable-continuation-v0.3-draft.md b/docs/source-packets/wits-v0/accountable-continuation-v0.3-draft.md new file mode 100644 index 0000000..7e384e8 --- /dev/null +++ b/docs/source-packets/wits-v0/accountable-continuation-v0.3-draft.md @@ -0,0 +1,412 @@ +# WITS v0 Accountable Continuation Source Packet + +Status: HACP v0.3 candidate source packet. + +Source material: + +- [WITS v0 HACP source packet](../wits-v0-hacp-source-packet.md); +- public HACP 0.2 chain-of-custody draft records; +- read-only who-decides spike record at commit `af8dbd7`; +- issue follow-ups for fixtures, multi-human policy, and version inventory: + [#9](https://github.com/joefeser/hacp/issues/9), + [#10](https://github.com/joefeser/hacp/issues/10), and + [#11](https://github.com/joefeser/hacp/issues/11). + +This packet translates WITS-derived accountable continuation concepts into +public-safe HACP draft language. It is source material for protocol review, not +a runtime design, product claim, or conformance release. + +## Scope + +HACP v0.3 candidate work should describe how a completed human decision can be +consumed by exactly one bounded successor invocation without changing the +decision record itself. + +The candidate shape separates these concerns: + +1. a task or authority packet states the bounded work and forbidden effects; +2. a review finding or report creates evidence that a human decision is needed; +3. a human decision records the accountable human act; +4. a consumption receipt claims that decision for one successor invocation; +5. the successor returns an agent or adapter report tied to the receipt; +6. a stop response is returned when the continuation boundary cannot be proven; +7. a new human decision on the returned report/evidence is required before + acceptance or completion, using the selected base decision vocabulary. + +The supported artifact set for demos and examples is: + +- task packet; +- review finding; +- human decision; +- consumption receipt; +- agent or adapter report; +- stop response when continuation stops instead of running. +- closing human decision on the returned evidence. + +These are supported artifacts. They are not mandatory in every HACP run. + +## Boundaries + +This source packet does not add: + +- hosted execution; +- hidden model or tool dispatch; +- GitHub mutation authority; +- billing or customer runtime; +- worker launch authority; +- HACP.io product claims; +- a requirement that WITS is present to use HACP. + +WITS is a private/reference implementation. Public HACP consumers should not +need WITS paths, tokens, databases, queues, or product runtime details to +understand or implement the protocol concepts. + +## Authority Origin + +Humans originate HACP authority. Packets carry, record, or reference bounded +authority after a human act has approved the relevant scope. + +Transport, queue delivery, report import, review agreement, and fixture success +do not create authority. A packet without a human-origin approval path is source +context, not active authority. + +## Consumption Receipt Candidate + +A consumption receipt is a separate immutable record that binds one human +decision to one successor invocation. It is not a field appended to a closed +human decision schema, and it does not mutate the approved decision. + +A receipt should bind: + +- the unchanged human decision identifier and digest; +- verified human-origin evidence for that decision: verification source, + authentication context, and an attestation/evidence reference; +- the decision-request or stop-response identifier and digest that asked for + the decision; +- the digest domain and canonicalization basis used for comparison; +- the permitted successor scope, equal to or a subset of the decision's + approved scope under the approved profile's declared scope grammar; +- the required successor invocation id; a claim id may additionally identify + the admission attempt but must not replace the invocation binding; +- the claimant identity or stable role label; +- the admitting role and issuer-side admission evidence, independently + authenticated under the human-approved profile, not a claimant's own + `admissionResult` assertion; +- trusted or profile-defined claim time; +- expiry and revocation ordering rules; +- idempotency and replay handling; +- evidence showing the claim was accepted or rejected. + +Admission verification is a role distinct from merely submitting a claim. The +owner-approved profile must identify the admissible issuer and trust anchor; +these sketches do not select a real authority. An issuer label or matching +digest alone is not authentication. Verify the human-origin evidence and the +scope subset before admission and again when verifying returned evidence. +Missing authority fails with `MISSING_AUTHORITY`; widening scope fails with +`SCOPE_CONFLICT`. Free-text scope labels are illustrative, not a scope grammar. + +The profile must publish a deterministic single-consumer uniqueness tuple, +canonical scope representation if scope participates, and atomic admission and +replay rules. Changing an attempt id, idempotency key, scope spelling/order, or +successor invocation id must not create another consumption slot for the same +approved continuation. Exact retries read back the same receipt; conflicting +replay fails closed. A receipt replay cannot authorize a second start after +execution has begun or become ambiguous. The tuple is an unresolved profile +choice, not defined by the example's opaque idempotency key. No implementation +may claim this invariant until that choice and its concurrent tests exist. + +Digest objects use `sha256` and the [HACP 0.2 canonicalization rules](../../hacp-0.2.md): +omit a record's own top-level `digest` when hashing its JCS representation; +retain embedded reference digests, which bind their referenced records in their +own domains. This applies also to the separately referenced start-evidence +record, not to its display copy inside a report. The `*_v0.3_candidate` domains +are unregistered candidates: consumers must reject them unless an approved +profile declares their coverage and interpretation. All illustrated digest +values are placeholders, not computed integrity evidence. + +Accepting a consumption claim proves only that one successor invocation was +admitted under the profile's concurrency rule. It does not prove provider +execution completed, downstream effects happened exactly once, or external +systems avoided duplicated side effects. + +Claim-before-start means that an accepted claim must be durably recorded and +read back for the successor invocation before that invocation starts work. +The failure case is successor start without durable readback of its accepted +claim; that attempt must fail closed. Claiming before start is the required +ordering, not the condition to reject. Missing accepted-claim readback maps to +`MISSING_AUTHORITY`. + +Durable acceptance is not continuing validity. Before successor start, verify +both decision and receipt expiry/revocation against current, authenticated +status evidence ordered with the start gate by the approved profile. A change +between acceptance and start must be observed: expiry or revocation ordered +before start prevents work with `STALE_PACKET`. If this ordering or freshness +cannot be established, do not start; return `UNVERIFIED_ASSUMPTION` (or +`ENVIRONMENT_BLOCKED` if the status source is unavailable). + +The immutable receipt's `receiptExpiresAt` describes only that receipt's +validity bound. `decisionValidityRef` identifies separate decision-status +evidence; `receiptValidityRef` identifies separate receipt-status evidence. +Neither is a mutable field on the decision or receipt, and neither may be +trusted just because the claimant supplied its URI. The approved profile must +specify the status issuer, integrity binding to the exact decision/receipt, +decision expiry source, revocation ordering, and freshness/start-gate rule. +An old status snapshot cannot prove that no later revocation exists. These +policy choices remain open and block usable continuation; the sketch does not +invent a status endpoint, authoritative store, or revocation algorithm. + +## Extension Processing + +The current v0.1 and v0.2 base decision schemas are closed. A v0.3 continuation +candidate must not append fields through a profile extension and then claim the +result is still a base decision record. + +Use this pattern instead: + +- keep the base human decision unchanged; +- publish a separately versioned extension envelope or receipt; +- bind an extension-required profile/version marker and the base decision and + required receipt identifiers/digests into an integrity-protected outer + continuation context; +- require consumers of the continuation path to validate that context against + their trusted, human-approved profile before interpreting the base decision; +- require extension-aware processing before continuation; +- reject records when required extension data is stripped; +- reject records when the extension profile, version, digest domain, or + processing rule is unknown; +- preserve a canonical base stop reason when extension processing fails. + +Base-only replay of an extension-required continuation must fail closed rather +than treating the old decision as fresh authority. + +The outer context is mandatory input for this continuation path, not optional +metadata inferred from the detached receipt. Removing the context must fail the +path's required-input check; removing the marker or changing its bindings must +fail integrity validation. A consumer that cannot process the required profile +must stop. A bare, unchanged base decision cannot reveal a stripped extension by +itself: it may remain valid for unrelated base processing, but is insufficient +authority to enter this continuation path. Profiles must not permit fallback +from a failed continuation-context check into a base-only successor start. + +## Minimal Consumption Candidate + +A minimum public candidate should prove these behaviors before HACP treats the +receipt as more than source material: + +| Behavior | Expected result | +| --- | --- | +| Two concurrent attempts target one approved continuation under the profile's declared uniqueness tuple | Exactly one claim is accepted; changing an attempt key or equivalent scope representation cannot bypass the rule. The loser returns a stop response or rejection receipt. | +| Restart after decision before successor invocation | The accepted claim remains durable and can be read back. | +| Claim before human decision exists | Claim is rejected with `MISSING_AUTHORITY`. | +| Successor attempts to start without durable readback of its accepted claim | `MISSING_AUTHORITY`; no successor work begins. This is the claim-before-start failure test. | +| Ambiguous execution after accepted claim | System records admitted claim but does not claim provider completion. | +| Expired or revoked decision | Claim is rejected; revocation/expiry ordering is visible in evidence. | +| Decision or receipt becomes expired/revoked after acceptance but before start | `STALE_PACKET`; no work begins under the stale claim. Unprovable ordering also prevents start. | + +An atomic single-consumer admission rule is narrower than exactly-once provider +execution. Profiles should say that plainly. + +## Stop Reasons + +Continuation-specific diagnostics should map back to canonical HACP stop +responses. Candidate mappings: + +| Continuation condition | Canonical stop reason | +| --- | --- | +| No human decision, digest mismatch, or missing receipt profile | `MISSING_AUTHORITY` | +| Required extension data is absent or stripped | `MISSING_AUTHORITY` | +| Continuation request differs from the approved scope | `SCOPE_CONFLICT` | +| Decision or receipt is expired/revoked according to authenticated current status | `STALE_PACKET` | +| No accepted claim can be read back | `MISSING_AUTHORITY` | +| Accepted claim exists but start ordering or current-status freshness is unproven | `UNVERIFIED_ASSUMPTION` | +| Admission/status evidence source is unavailable | `ENVIRONMENT_BLOCKED` | +| Partial readback prevents reconstruction of broader prior context, beyond the specific cases above | `RELIABILITY_LIMIT_REACHED` | +| A human must resolve residual risk or ambiguous authority | `HUMAN_DECISION_REQUIRED` | + +Profile-specific stop codes may add detail, but any base HACP stop response +must preserve the canonical reason and the minimal correction needed to unblock +review. + +Candidate decision/disposition labels are explanatory, not new base enum values: + +| Candidate label | Base projection | +| --- | --- | +| `approve_bounded_successor` | v0.1 `approve_next_packet` or v0.2 `accept_follow_up`, subject to that version's decision matrix and approval evidence. | +| `review_draft_packet` | Advisory request for `request_human_decision`, not a completed human act. | +| Finding `recommendedDisposition: request_human_decision` | v0.1 finding `classification: needs_human_decision` with `requires_human_decision: true`. | + +Base output must use the selected version's actual fields, required evidence, +and permitted transitions; renaming one field does not convert a candidate into +a valid base record. Descriptive forbidden-effect labels in the task sketch +are scope exclusions, not additions to a closed base forbidden-effects enum. + +## Loop Ceilings + +[RFC-0006](../../../rfcs/0006-loop-ceiling-and-bounded-iteration.md) applies: +declare a visible ceiling or single-pass posture before iterative work. Keep +the base increment trigger (another human-approved packet after a prior return) +unless a named profile explicitly changes it. Imports, queue delivery, and +claim retries do not silently increment or reset the base loop counter. +Reports preserve the loop counter and outcome; a ceiling breach routes to +human decision or terminal stop, never automatic reset, expansion, or bypass. + +Profiles must separately bound claim/restart retries with a deterministic +attempt rule and visible limit; a failed or ambiguous attempt cannot create an +unbounded retry path. The owner chooses those bounds. The sketches illustrate +a single-pass session with ceiling/counter zero, one initial claim, and no +automatic retry. This is an example posture, not a default for all consumers. + +## CLI And HTTP Report Return + +CLI and HTTP return paths should treat a consumption receipt as evidence that a +specific decision was claimed, not as proof that execution completed. + +A report-return path should preserve: + +- the report's own identifier and full content digest, including its digest + domain and canonicalization basis; +- packet or handoff reference; +- decision reference and full digest/domain; prefixes are human display only, + never authorization or integrity evidence; +- consumption receipt id and digest; +- decision-request or finding reference and digest when it controlled the + continuation boundary; +- successor invocation id; +- authenticated issuer-side admission evidence and a scope-subset comparison + against the unchanged human decision; +- a digest-bound start-evidence reference tying that invocation and accepted + receipt to durable claim-readback and work-start timestamps, with the + profile-defined time source used to establish their order; +- authenticated decision/receipt validity evidence evaluated at the start gate, + with bindings, freshness, and ordering checked under the approved profile; +- report return time and loop counter/outcome; +- attempted work summary; +- evidence refs and check output; +- residual risk; +- requested next human decision; +- boundary statement that return/import is evidence only. + +CLI and HTTP importers should reject reports that claim completion, merge, +deployment, billing, customer runtime, worker launch, or GitHub mutation +authority without a separate human-approved decision/profile that explicitly +covers that effect. + +The start-evidence fields illustrate an auditable ordering record, not proof +from self-reported timestamps alone. A verifier must read the referenced +evidence and verify its digest, invocation/receipt bindings, and ordering under +the approved profile. Missing or unverifiable evidence cannot establish +claim-before-start. Current expiry/revocation checks remain independently +required; ordering evidence does not establish current authority. + +Inline start-evidence fields are display copies, not an alternative source of +truth. Any disagreement with the verified referenced record fails closed with +`UNVERIFIED_ASSUMPTION`. The referenced start record must bind the separate +validity readback used at start. A report returned after receipt expiry may +still be retained as historical evidence; return time does not re-authorize +work or replace the validity check at start. + +Importers must verify the returned report's content digest under the selected +profile before using its contents as evidence. Matching only digests of records +referenced by the report does not protect the report itself. These sketches use +placeholder digests; they cannot pass real integrity verification unchanged. + +## RabbitMQ Transport Envelope Posture + +RabbitMQ remains source material for transport-envelope design only. + +A RabbitMQ-style transport profile may carry task packets, decision requests, +decision records, consumption receipts, reports, and stop responses. Queue +publish, delivery, claim, ack, retry, and dead-letter events are custody +evidence. They do not approve work, launch workers by themselves, or mark a +decision as consumed unless the profile defines an explicit admission rule and +durable receipt. + +Useful envelope evidence includes: + +- message id and correlation id; +- payload digest and digest domain; +- producer and consumer role labels; +- delivery, claim, ack, retry, and dead-letter timestamps; +- receipt or stop-response reference; +- expiry and revocation readback; +- boundary assertion that transport success is not approval or completion. + +## Example Sketches + +Public-safe candidate sketches live in +[examples/](examples/). They are not schema-valid conformance fixtures yet and +use placeholder ids/digests. + +| Sketch | Purpose | +| --- | --- | +| [task-packet.candidate.json](examples/task-packet.candidate.json) | Bounded source context and forbidden effects. | +| [review-finding.candidate.json](examples/review-finding.candidate.json) | Finding that requests a human decision before continuation. | +| [human-decision.candidate.json](examples/human-decision.candidate.json) | Immutable candidate human-decision sketch, not a schema-valid base record. | +| [consumption-receipt.candidate.json](examples/consumption-receipt.candidate.json) | Separate issuer-evidenced admission receipt with scope bounded by the decision. | +| [continuation-context.candidate.json](examples/continuation-context.candidate.json) | Required outer input binding the extension marker, decision, receipt, and invocation. | +| [agent-report.candidate.json](examples/agent-report.candidate.json) | Evidence return tied to the receipt. | +| [stop-response.candidate.json](examples/stop-response.candidate.json) | Fail-closed response recording that no successor work began, not that forbidden effects occurred. | + +The continuation context is the required input to continuation processing; +the report references its identifier and digest for later audit. The consumer +must validate the context using its independently trusted profile before +interpreting the decision or receipt. No example supplies a trust anchor or +proves current revocation status, and no new base schema is implied. +All `evidence://example/` references are hypothetical, not supplied proof +artifacts. No sketch illustrates the closing human decision yet; that separate +record is still required before marking work complete. + +## Conformance Fixture Candidates + +Future conformance work should promote the candidate sketches only after the +semantics are proven and digest domains are made deterministic. + +Positive candidates: + +- one accepted claim out of two concurrent claim attempts; +- restart readback preserves a previously accepted receipt; +- successor report references the accepted receipt and unchanged decision; +- base-only consumer rejects extension-required continuation; +- expired decision produces a canonical `STALE_PACKET` stop response. + +Negative candidates: + +- two accepted receipts for one continuation under the approved uniqueness tuple, + including attempts with changed idempotency keys or equivalent scope labels; +- consumption fields added directly to a closed base decision record; +- report claims provider exactly-once execution from receipt admission alone; +- stripped extension data treated as base authority; +- queue ack treated as approval, completion, or worker launch authority. + +Issue [#9](https://github.com/joefeser/hacp/issues/9) remains the proper home +for real RFC 8785 JCS digest fixture promotion. + +## External Proof Gate + +The who-decides spike at `af8dbd7` records the public design intent for +consumption receipts, extension processing, and the five-artifact demo set. It +does not, by itself, complete the HACP v0.3 proof gate. + +Before this consumption-contract source packet is merged, maintainers must require +independent readback of pinned code, tests, and receipts showing: + +- concurrent claim attempts admit exactly one successor; +- restart preserves claim/decision evidence; +- the claim-before-start failure test rejects successor start without durable + readback of its accepted claim; +- ambiguous execution is reported without pretending completion; +- expiry and revocation ordering is deterministic and reviewable. + +Until that evidence is accepted by the owner, a clean docs review or ACK +mechanical result is not a merge or release recommendation for this draft. + +## Related Backlog + +This packet intentionally does not close: + +- issue [#9](https://github.com/joefeser/hacp/issues/9), which should add real + JCS digest conformance fixtures; +- issue [#10](https://github.com/joefeser/hacp/issues/10), which should explore + multi-human policy without making multi-human approval a generic prerequisite; +- issue [#11](https://github.com/joefeser/hacp/issues/11), which should add the + reader-friendly v0.1 to v0.2 catch-up guide. diff --git a/docs/source-packets/wits-v0/examples/agent-report.candidate.json b/docs/source-packets/wits-v0/examples/agent-report.candidate.json new file mode 100644 index 0000000..777abd3 --- /dev/null +++ b/docs/source-packets/wits-v0/examples/agent-report.candidate.json @@ -0,0 +1,91 @@ +{ + "recordKind": "hacp.v0_3_candidate.agent_report", + "schemaVersion": "hacp-0.3-candidate", + "reportId": "report_example_successor_001", + "returnedAt": "2026-09-03T18:10:00Z", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "agent_report_v0.3_candidate", + "value": "6666666666666666666666666666666666666666666666666666666666666666" + }, + "continuationContext": { + "id": "context_example_successor_001", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "continuation_context_v0.3_candidate", + "value": "5555555555555555555555555555555555555555555555555555555555555555" + } + }, + "packetId": "taskpkt_example_continue_review_001", + "decision": { + "id": "decision_example_approve_successor_001", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "human_decision_v0.3_candidate", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "decisionRequest": { + "kind": "review_finding", + "id": "finding_example_needs_owner_decision_001", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "review_finding_v0.3_candidate", + "value": "1111111111111111111111111111111111111111111111111111111111111111" + } + }, + "consumptionReceiptId": "receipt_example_claim_successor_001", + "consumptionReceiptDigest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "consumption_receipt_v0.3_candidate", + "value": "2222222222222222222222222222222222222222222222222222222222222222" + }, + "successorInvocationId": "invoke_example_docs_worker_001", + "startEvidence": { + "recordId": "start_evidence_example_001", + "evidenceRef": "evidence://example/successor-start-record", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "successor_start_evidence_v0.3_candidate", + "value": "3333333333333333333333333333333333333333333333333333333333333333" + }, + "successorInvocationId": "invoke_example_docs_worker_001", + "consumptionReceiptId": "receipt_example_claim_successor_001", + "consumptionReceiptDigest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "consumption_receipt_v0.3_candidate", + "value": "2222222222222222222222222222222222222222222222222222222222222222" + }, + "acceptedClaimReadBackAt": "2026-09-03T18:05:01Z", + "workStartedAt": "2026-09-03T18:05:02Z", + "validityReadbackRef": "evidence://example/start-gate-validity-readback", + "timeSource": "profile-defined-owner-ledger" + }, + "attemptedWork": [ + "prepared docs-only v0.3 candidate text", + "ran repository validation" + ], + "evidenceRefs": [ + "evidence://example/successor-start-record", + "evidence://example/issuer-admission-record", + "evidence://example/start-gate-validity-readback", + "evidence://example/git-diff-check", + "evidence://example/hacp-cli-bridge-examples", + "evidence://example/ack-pr-loop" + ], + "residualRisks": [ + "external concurrency and expiry/revocation proof must be accepted before merge of this consumption-contract source packet", + "illustrated issuer, uniqueness, and validity policies remain undefined; hypothetical references do not prove actual admission or current authority" + ], + "loopCounter": 0, + "loopOutcome": "unobserved", + "requestedNextHumanDecision": "review_draft_packet", + "boundaryStatement": "The report is evidence for human review. It does not approve merge, release, or v0.3 conformance." +} diff --git a/docs/source-packets/wits-v0/examples/consumption-receipt.candidate.json b/docs/source-packets/wits-v0/examples/consumption-receipt.candidate.json new file mode 100644 index 0000000..a333b42 --- /dev/null +++ b/docs/source-packets/wits-v0/examples/consumption-receipt.candidate.json @@ -0,0 +1,55 @@ +{ + "recordKind": "hacp.v0_3_candidate.consumption_receipt", + "schemaVersion": "hacp-0.3-candidate", + "receiptId": "receipt_example_claim_successor_001", + "decisionId": "decision_example_approve_successor_001", + "decisionDigest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "human_decision_v0.3_candidate", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + "decisionRequest": { + "kind": "review_finding", + "id": "finding_example_needs_owner_decision_001", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "review_finding_v0.3_candidate", + "value": "1111111111111111111111111111111111111111111111111111111111111111" + } + }, + "claim": { + "claimId": "claim_example_successor_001", + "claimant": "agent:docs-worker@example.invalid", + "claimedAt": "2026-09-03T18:05:00Z", + "successorInvocationId": "invoke_example_docs_worker_001", + "permittedScope": [ + "edit docs/source-packets/", + "run docs/config validation", + "return ACK and review evidence" + ], + "admissionResult": "accepted" + }, + "singleConsumerBasis": { + "profileId": "hacp-accountable-continuation-v0.3-candidate", + "idempotencyKey": "example:decision:successor:001", + "uniquenessRuleStatus": "requires_owner_approved_profile_definition", + "trustedTimeSource": "profile-defined-owner-ledger", + "receiptExpiresAt": "2026-09-03T19:00:00Z", + "decisionValidityRef": "evidence://example/decision-validity", + "receiptValidityRef": "evidence://example/receipt-validity" + }, + "admittedBy": "role:admission-verifier@example.invalid", + "evidenceRefs": [ + "evidence://example/issuer-admission-record", + "evidence://example/human-approval-attestation" + ], + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "consumption_receipt_v0.3_candidate", + "value": "2222222222222222222222222222222222222222222222222222222222222222" + }, + "boundaryStatement": "Illustrative acceptance only: issuer trust, uniqueness, and current-status policy require an independently approved profile. These hypothetical evidence references prove no actual admission. Accepted admission does not prove provider execution, external side effects, merge readiness, or exactly-once downstream completion." +} diff --git a/docs/source-packets/wits-v0/examples/continuation-context.candidate.json b/docs/source-packets/wits-v0/examples/continuation-context.candidate.json new file mode 100644 index 0000000..f4d1e4d --- /dev/null +++ b/docs/source-packets/wits-v0/examples/continuation-context.candidate.json @@ -0,0 +1,36 @@ +{ + "recordKind": "hacp.v0_3_candidate.continuation_context", + "schemaVersion": "hacp-0.3-candidate", + "contextId": "context_example_successor_001", + "requiredExtension": { + "profileId": "hacp-accountable-continuation-v0.3-candidate", + "profileVersion": "hacp-0.3-candidate", + "extensionAwareProcessingRequired": true + }, + "decision": { + "id": "decision_example_approve_successor_001", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "human_decision_v0.3_candidate", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "consumptionReceipt": { + "id": "receipt_example_claim_successor_001", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "consumption_receipt_v0.3_candidate", + "value": "2222222222222222222222222222222222222222222222222222222222222222" + } + }, + "successorInvocationId": "invoke_example_docs_worker_001", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "continuation_context_v0.3_candidate", + "value": "5555555555555555555555555555555555555555555555555555555555555555" + }, + "boundaryStatement": "Illustrative required input, not active authority. The consumer must authenticate the context integrity through its independently trusted human-approved profile; a self-supplied digest is insufficient. Revocation/current-status policy and external proof remain unresolved." +} diff --git a/docs/source-packets/wits-v0/examples/human-decision.candidate.json b/docs/source-packets/wits-v0/examples/human-decision.candidate.json new file mode 100644 index 0000000..b34d230 --- /dev/null +++ b/docs/source-packets/wits-v0/examples/human-decision.candidate.json @@ -0,0 +1,57 @@ +{ + "recordKind": "hacp.v0_3_candidate.human_decision", + "schemaVersion": "hacp-0.3-candidate", + "decisionId": "decision_example_approve_successor_001", + "packetId": "taskpkt_example_continue_review_001", + "packetDigest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "task_packet_v0.3_candidate", + "value": "4444444444444444444444444444444444444444444444444444444444444444" + }, + "decisionRequest": { + "kind": "review_finding", + "id": "finding_example_needs_owner_decision_001", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "review_finding_v0.3_candidate", + "value": "1111111111111111111111111111111111111111111111111111111111111111" + } + }, + "actor": { + "actorId": "human:owner@example.invalid", + "actorKind": "human", + "verificationSource": "signed_human_attestation" + }, + "authenticationContext": { + "interactionChannel": "cli", + "secretMaterialPresent": false, + "authEventRef": "evidence://example/human-approval-event" + }, + "evidenceRefs": [ + "evidence://example/human-approval-attestation" + ], + "decision": "approve_bounded_successor", + "decisionReason": "The follow-up is docs-only and the expected evidence is explicit.", + "approvedSuccessorScope": [ + "edit docs/source-packets/", + "run docs/config validation", + "return ACK and review evidence" + ], + "deniedAuthority": [ + "merge", + "deploy", + "launch_worker", + "mutate_github_without_separate_tool_authority", + "accept_risk" + ], + "createdAt": "2026-09-03T18:00:00Z", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "human_decision_v0.3_candidate", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + "boundaryStatement": "This decision is immutable source evidence. Consumption is recorded in a separate receipt." +} diff --git a/docs/source-packets/wits-v0/examples/review-finding.candidate.json b/docs/source-packets/wits-v0/examples/review-finding.candidate.json new file mode 100644 index 0000000..18e1f31 --- /dev/null +++ b/docs/source-packets/wits-v0/examples/review-finding.candidate.json @@ -0,0 +1,29 @@ +{ + "recordKind": "hacp.v0_3_candidate.review_finding", + "schemaVersion": "hacp-0.3-candidate", + "findingId": "finding_example_needs_owner_decision_001", + "packetId": "taskpkt_example_continue_review_001", + "packetDigest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "task_packet_v0.3_candidate", + "value": "4444444444444444444444444444444444444444444444444444444444444444" + }, + "severity": "medium", + "summary": "Returned evidence is actionable, but continuation would consume a human decision and start a successor invocation.", + "affectedSurfaces": [ + "repo://example/hacp/docs/source-packets/" + ], + "evidenceRefs": [ + "evidence://example/review-output-001" + ], + "recommendedDisposition": "request_human_decision", + "residualRisk": "The successor invocation must be bounded to docs-only work and must not infer merge authority.", + "humanDecisionRequired": true, + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "review_finding_v0.3_candidate", + "value": "1111111111111111111111111111111111111111111111111111111111111111" + } +} diff --git a/docs/source-packets/wits-v0/examples/stop-response.candidate.json b/docs/source-packets/wits-v0/examples/stop-response.candidate.json new file mode 100644 index 0000000..e204e1e --- /dev/null +++ b/docs/source-packets/wits-v0/examples/stop-response.candidate.json @@ -0,0 +1,17 @@ +{ + "recordKind": "hacp.v0_3_candidate.stop_response", + "schemaVersion": "hacp-0.3-candidate", + "stopId": "stop_example_missing_receipt_001", + "packetId": "taskpkt_example_continue_review_001", + "decisionId": "decision_example_approve_successor_001", + "profileId": "hacp-accountable-continuation-v0.3-candidate", + "successorInvocationId": "invoke_example_docs_worker_001", + "stopReason": "MISSING_AUTHORITY", + "whatDoesNotLineUp": "The continuation request requires an accountable-continuation receipt, but no accepted receipt could be read back.", + "evidenceRefs": [ + "evidence://example/receipt-lookup-empty" + ], + "minimalCorrection": "Return to the human decision gate or verify authentic issuer-side admission and current validity under an approved continuation profile; a claimant-created receipt is insufficient.", + "successorWorkBegan": false, + "boundaryStatement": "No work began in this hypothetical stop case. This candidate does not assert that any forbidden effect occurred or extend the base forbidden-effects vocabulary." +} diff --git a/docs/source-packets/wits-v0/examples/task-packet.candidate.json b/docs/source-packets/wits-v0/examples/task-packet.candidate.json new file mode 100644 index 0000000..f236700 --- /dev/null +++ b/docs/source-packets/wits-v0/examples/task-packet.candidate.json @@ -0,0 +1,55 @@ +{ + "recordKind": "hacp.v0_3_candidate.task_packet", + "schemaVersion": "hacp-0.3-candidate", + "packetId": "taskpkt_example_continue_review_001", + "digest": { + "algorithm": "sha256", + "canonicalization": "json-rfc8785-jcs", + "digestDomain": "task_packet_v0.3_candidate", + "value": "4444444444444444444444444444444444444444444444444444444444444444" + }, + "sourceContext": { + "humanRequest": "Review the returned finding and continue only if the owner approves the bounded follow-up.", + "sourceRefs": [ + "repo://example/hacp/issues/39", + "docs/source-packets/wits-v0/accountable-continuation-v0.3-draft.md" + ] + }, + "requestedScope": [ + "edit docs/source-packets/", + "run docs/config validation", + "return ACK and review evidence" + ], + "loopPolicy": { + "mode": "single_pass", + "ceiling": 0, + "counter": 0, + "incrementTrigger": "post_return_human_approval_of_another_packet", + "claimAttemptLimit": 1, + "automaticRetryAllowed": false, + "boundaryStatement": "Illustrative single-pass posture, not a universal profile default or permission to reset the same session." + }, + "forbiddenEffects": [ + "hosted_execution", + "hidden_model_or_tool_dispatch", + "github_mutation_by_protocol", + "billing_or_customer_runtime", + "worker_launch_authority" + ], + "expectedEvidence": [ + "review finding", + "human decision", + "consumption receipt", + "agent report or stop response" + ], + "stopConditions": [ + "missing human decision", + "scope mismatch", + "stale or revoked decision", + "unsupported continuation extension" + ], + "profileRefs": [ + "hacp-accountable-continuation-v0.3-candidate" + ], + "boundaryStatement": "This packet records requested bounded scope only. Authority remains inactive until a human decision records approval, and the packet does not launch a worker or approve a future result." +} diff --git a/schemas/README.md b/schemas/README.md index ad83014..e1b8038 100644 --- a/schemas/README.md +++ b/schemas/README.md @@ -2,9 +2,9 @@ ## Status -These schemas are a **working draft** for HACP v0.1-style artifact shapes. -They are public-safe companion artifacts for documentation and validation. They -are not a final external standard. +These schemas are **working draft** companion artifacts for HACP v0.1 and HACP +0.2 record shapes. They are public-safe documentation and validation aids, not +a final external standard. Need a concise enterprise explainer before schema details? See [../adoption-primer.md](../adoption-primer.md). @@ -17,13 +17,26 @@ Need to choose a concrete stop reason? See ## Versioning -- Profile/version target: `hacp-base-draft` / `v0.1-draft` +- Profile/version targets: + - `hacp-base-draft` / `v0.1-draft` for the original task-packet, + agent-report, human-decision-gate, review-finding, evidence-set, + loop-policy, and stop-response shapes. + - `hacp-base-draft` / `v0.2-draft` for the chain-of-custody authority packet, + handoff package, adapter report, match proof, and human decision record + shapes. - Schema dialect: JSON Schema Draft 2020-12 -- `$id` namespace: `https://hacp.example/schemas/v0.1-draft/` +- `$id` namespaces: + - `https://hacp.example/schemas/v0.1-draft/` + - `https://hacp.example/schemas/v0.2-draft/` Versioning for future phases should preserve backward-readable draft history rather than rewriting old identifiers. +HACP v0.1 and HACP 0.2 records may coexist as public draft artifacts, but they +are not interchangeable inside one custody chain unless a profile publishes an +explicit translation record. HACP v0.3 source-packet examples are candidate +sketches only until a future schema or profile promotes them. + ## Draft Limitations These schemas validate shape and vocabulary only. They do not execute workflow. @@ -46,13 +59,20 @@ They do not: ## Authority Boundary -- Approval is explicit and human-issued through `HumanDecision` records. +- Approval is explicit and human-issued. In v0.1, the + [Human Decision Gate](human-decision.schema.json) records the approval. In + v0.2, originating approval is recorded in + [AuthorityPacket.approval](authority-packet.schema.json); the later + [HumanDecisionRecord](human-decision-record.schema.json) records the human + decision after the adapter report and match proof. - Report verification is custody/integrity evidence, not completion proof. - File and CLI transport can carry schema-valid artifacts without granting approval authority. ## Schema Index +### HACP v0.1 Draft Shapes + - [task-packet.schema.json](task-packet.schema.json) - [agent-report.schema.json](agent-report.schema.json) - [human-decision.schema.json](human-decision.schema.json) @@ -61,6 +81,14 @@ They do not: - [review-finding.schema.json](review-finding.schema.json) - [loop-policy.schema.json](loop-policy.schema.json) +### HACP 0.2 Draft Chain-of-Custody Shapes + +- [authority-packet.schema.json](authority-packet.schema.json) +- [handoff-package.schema.json](handoff-package.schema.json) +- [adapter-report.schema.json](adapter-report.schema.json) +- [match-proof.schema.json](match-proof.schema.json) +- [human-decision-record.schema.json](human-decision-record.schema.json) + ## Evidence Field Compatibility The base RFCs require simple `evidence` arrays so the minimum contract stays