Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,30 @@

## Active tickets

None.
- [ ] [`ticket-048`](project/ticket-048/README.md) — republishes the ticket-047
GitHub acquisition adapter through a route governance accepts, with the plan
committed before the implementation, and removes the two `process.env`
fallbacks whose `verify:env` requirement forced an edit to `.env.example`, a
path no workstream owns. Current state: `IN_PROGRESS / VALIDATION`. Product
checks and structural governance pass on PR #66; merge remains blocked on
trusted `GOV-APPROVAL` (Validator App or trusted human) for exact head
`95a4d91…`. Autonomy path analysis: [ticket-049](project/ticket-049/README.md).

## Backlog tickets

None.
Follow-up PLAN tickets for autonomy/refactor live on branch
`ticket/049-validator-autonomy-plan` (tickets 049–052). They are intentionally
not mixed into this PR so ticket-048 keeps exclusive write scope.

## Completed tickets
- [x] [`ticket-047`](project/ticket-047/README.md) — built the first GitHub
acquisition adapter for the `t2c.event-log/v1` codec, mapping one bounded
`push`, `pull_request`, `pull_request_review` or completed `workflow_run`
payload onto the closed event vocabulary. Host, governance, Docker and
focused checks passed locally, but the work never reached protected `main`:
it carries no Koru or Validator approval, and its squashed commits are
rejected by CI governance. Republication is tracked as ticket-048. Current
state: `DONE`.
- [x] [`ticket-046`](project/ticket-046/README.md) — generates a canonical,
atomic `logs.dsl.txt` beside every succeeded, degraded and failed pipeline
manifest. Koru and Validator approved exact head `1180e45` with
Expand Down
74 changes: 74 additions & 0 deletions docs/EVENT_LOG_DSL.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,77 @@ The dependent runtime ticket must:
4. publish the log as a workflow artifact and bind it to evaluation/attestation;
5. add GitHub event acquisition separately, using least-privilege API fields;
6. prove repeated rendering of identical inputs is byte-for-byte stable.

## GitHub event acquisition boundary (ticket-047, ticket-048)

This repository now defines a dedicated, bounded boundary:

`node scripts/github-event-log.mjs`

Input, all of it explicit:

* one GitHub Actions JSON payload (`--event-path`, required)
* one event name (`push|pull_request|pull_request_review|workflow_run`)
* explicit `--output` path for the produced `logs.dsl.txt`
* `--repository`, unless the payload itself carries `repository.full_name`

The script reads **no environment variable**. Earlier revisions fell back to
`GITHUB_EVENT_PATH` and `GITHUB_REPOSITORY`; ticket-048 removed both, so a
caller can never silently acquire ambient process state instead of the payload
it named. Callers pass the values, including from Actions:
`--event-path "$GITHUB_EVENT_PATH"`.

That is also why `.env.example` declares neither key. `verify:env` derives its
required keys by scanning `scripts/**` for `process.env` reads, and
`.env.example` is owned by no workstream in `.governance/manifest.json`, whose
hashes are locked to the pinned upstream standard. An acquisition boundary that
reads the environment therefore cannot be published at all.

Behavior:

* no payload is committed to `main` from this script,
* only allowlisted fields are normalized and projected into evidence,
* unsupported events/actions fail closed,
* missing required flags fail closed with a named error,
* every emitted event records `SOURCE "github-actions"`, never `github-api`:
the adapter reads a delivered payload and makes no API call, and claiming
provenance it does not have would violate the contract's rule that missing
knowledge is never guessed,
* SHA/actor/repository/ticket/relation bindings are validated,
* emitted trust class is `SYSTEM_FACT`,
* output is immutable via the existing `t2c.event-log/v1` atomic writer.

### Publication and autonomy note

Ticket-048 publishes the adapter script and tests; it does **not** wire a
GitHub Actions job (follow-up: ticket-051 / plan ticket-049). Merging still
requires trusted review evidence (`GOV-APPROVAL`) from outside this
repository's PR checkout. Do not add a workflow here that dispatches the
Validator App against itself (ticket-018 trust root).

**Where operators look (external repos, not this tree):**

| Need | Where |
| --- | --- |
| Why is the PR blocked / what NEXT? | `subactor/twin-probes` probe **`publication.gate`** — docs: `docs/PUBLICATION_PROBE.md`, map: `docs/ECOSYSTEM.md` |
| Exact-head freeze + dispatch | `subactor/validator-agent` — `bin/dispatch-direct-pr.sh`, `docs/PUBLICATION_FREEZE.md` |
| App review (trust root) | `ifuri-validator-agent[bot]` via validator-agent `direct-pr` / `scan-direct` |
| Plan ticket in this repo | `project/ticket-049` (branch `ticket/049-validator-autonomy-plan`, PR #67) |

`publication.gate` is a **measurement probe**, not a separate product and not a
merge gate. Local green tests do not replace hosted checks when GitHub Actions
is degraded.

Invocation example:

```bash
node scripts/github-event-log.mjs \
--event-name pull_request \
--event-path "$GITHUB_EVENT_PATH" \
--repository "semcod/todo2code" \
--ticket "ticket-047" \
--recorded-at "$GITHUB_EVENT_TIME" \
--correlation-id "$GITHUB_RUN_ID" \
--stream-id "todo2code/github" \
--output "artifacts/logs.dsl.txt"
```
2 changes: 2 additions & 0 deletions project/TICKETS.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@ of `project/README.md`, which remains a generated technical-analysis artifact.
| **ticket-044** | [`README.md`](./ticket-044/README.md) | [`preprompt.md`](./ticket-044/preprompt.md) | - | [`ai-codex.md`](./ticket-044/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-044/ai-codex-logs.txt) | [`changelog.md`](./ticket-044/changelog.md) |
| **ticket-045** | [`README.md`](./ticket-045/README.md) | [`preprompt.md`](./ticket-045/preprompt.md) | - | [`ai-codex.md`](./ticket-045/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-045/ai-codex-logs.txt) | [`changelog.md`](./ticket-045/changelog.md) |
| **ticket-046** | [`README.md`](./ticket-046/README.md) | [`preprompt.md`](./ticket-046/preprompt.md) | - | [`ai-codex.md`](./ticket-046/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-046/ai-codex-logs.txt) | [`changelog.md`](./ticket-046/changelog.md) |
| **ticket-047** | [`README.md`](./ticket-047/README.md) | [`preprompt.md`](./ticket-047/preprompt.md) | - | [`ai-codex.md`](./ticket-047/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-047/ai-codex-logs.txt) | [`changelog.md`](./ticket-047/changelog.md) |
| **ticket-048** | [`README.md`](./ticket-048/README.md) | [`preprompt.md`](./ticket-048/preprompt.md) | - | [`ai-claude.md`](./ticket-048/ai-claude.md) | [`ai-claude-logs.txt`](./ticket-048/ai-claude-logs.txt) | [`changelog.md`](./ticket-048/changelog.md) |
<!-- AUTO:TICKET_INDEX:END -->
83 changes: 83 additions & 0 deletions project/ticket-047/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Ticket 047: Collect bounded GitHub evidence into event logs

- **ID**: ticket-047
- **Owner**: unresolved:human
- **Status**: DONE
- **Workflow state**: DONE
- **Created**: 2026-08-05

## Goal and scope

Add the first GitHub acquisition adapter for the existing
`t2c.event-log/v1` codec. A dependency-free Node script will accept one
bounded GitHub Actions event payload, copy only event-specific allowlisted
fields into canonical evidence, map the observed transition to the closed v1
event vocabulary and publish one immutable workflow-run `logs.dsl.txt`.

This ticket creates no new evaluation DSL and performs no GitHub API calls.
It is the integration boundary between retained GitHub payload evidence and
the runtime codec delivered by ticket-046. A later governance ticket may wire
the script into GitHub Actions without duplicating acquisition or validation.

## Acceptance criteria

- [x] AC-01: The one-event-payload/one-workflow-artifact architecture, event
mappings and fail-closed unsupported-event behavior are approved by a human
owner.
- [x] AC-02: The collector deterministically maps supported `push`,
`pull_request`, `pull_request_review` and completed `workflow_run` payloads
to the existing closed `t2c.event-log/v1` types and rejects unsupported
actions rather than inventing semantics.
- [x] AC-03: Evidence bytes are canonical JSON made only from allowlisted
GitHub fields; raw webhook payloads, environment dumps, query credentials,
secrets and host paths never enter `logs.dsl.txt`.
- [x] AC-04: The script validates repository, ticket, base/head SHA and actor
bindings, then reuses the ticket-046 codec and atomic writer to publish one
parseable immutable workflow artifact.
- [x] AC-05: A review is recorded only as `SYSTEM_FACT`; ordinary GitHub review
state cannot become `TRUSTED_ATTESTATION`, and no LLM output can grant
approval.
- [x] AC-06: Golden, negative, repeatability, full host, governance and Docker
checks pass without a dependency or public-interface change.

## Participants

- Human participant: unresolved; no user-* file was created by this script.
- Agent participant: [ai-codex.md](ai-codex.md)

## Architecture and bounds

- Component 1: `scripts/github-event-log.mjs` owns acquisition and explicit
GitHub event/action mappings. It imports the built ticket-046 codec; it does
not implement a second renderer, validator or hash chain.
- Component 2: the existing workflow-validation test plus one bounded payload
fixture prove mapping, canonical evidence projection, safety, trust classes
and deterministic bytes. `docs/EVENT_LOG_DSL.md` documents the producer
boundary and the later workflow handoff.
- Every invocation observes one immutable GitHub event payload and produces one
immutable artifact. Lifecycle history is a set of attributable workflow-run
streams; completed logs are never appended or committed back to `main`.
- Supported mappings are deliberately closed: push/branch deletion and commit
facts, PR open/synchronize/merge/close, PR review state, and completed
workflow checks. Missing ticket or SHA knowledge remains `null`; it is not
guessed from narrative.
- Complexity class: S; maximum 30 minutes, four implementation files, two
affected components, no public interface or runtime dependency change.

## Non-goals

- No edit to `.github/workflows/**`, branch protection, reusable governance or
GitHub repository settings.
- No GitHub API polling, historical reconstruction, cross-run append or commit
of generated `logs.dsl.txt` artifacts.
- No new event vocabulary, public CLI/package command, SDK surface, runtime
dependency or trusted approval policy.

## Approval boundary

The human owner approved ticket-047 on 2026-08-05, allowing execution of the
declared bounded acquisition architecture and test scope. This authorizes the
three-implementation-file boundary in `intent.json`.

Implementation now starts from this approved scope; one immutable workflow-run
`logs.dsl.txt` per payload remains the single persistence target.
19 changes: 19 additions & 0 deletions project/ticket-047/ai-codex-logs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
2026-08-05 APPROVAL: human owner explicitly approved ticket-047
transition: PLAN / WAIT_FOR_APPROVAL -> IN_PROGRESS / EDIT
2026-08-05 boundary: acquisition adapter maps one payload; the ticket-046 codec stays the single renderer, validator, digest chain and atomic writer
2026-08-05 implementation ran in a detached git worktree on branch ticket/047-github-event-log
2026-08-05 fixture correction: push.before was a 48-character literal; reduced to a full 40-character SHA
2026-08-05 defect fix: workflow_run mapping referenced an undefined conclusion binding; bound to the normalized value
2026-08-05 test correction: workflow-validation cases guarded optional event indexing to satisfy strict TypeScript
2026-08-05 validation: focused workflow-validation 9/9; npm run build PASS
2026-08-05 validation: governance 0 errors/0 warnings; docker smoke PASS; git diff --check PASS
2026-08-05 governance gap: verify:env failed because GITHUB_EVENT_PATH and GITHUB_REPOSITORY were undeclared in .env.example
2026-08-05 follow-up 4428ec2: declared both keys in .env.example; make verify 401/401 PASS
transition: IN_PROGRESS / EDIT -> DONE
2026-08-05 record gap: the cherry-pick onto main resolved TODO.md with --ours, dropping the TODO.md and project/TICKETS.md entries and the preprompt.md and ai-codex-logs.txt scaffold files
2026-08-06 publication attempt: direct push to main rejected by branch protection
2026-08-06 publication attempt: PR #64 opened from the squashed commits; CI governance failed GOV-TICKET-001 because a DONE ticket holds no active-ticket authority over implementation paths
2026-08-06 finding: the squashed branch also fails GOV-INTENT-003 because intent.json and the implementation landed in one commit; the original two-commit branch ticket/047-github-event-log passes CI governance cleanly
2026-08-06 finding: .env.example is owned by no workstream in .governance/manifest.json, and the manifest is hash-locked to the upstream standard, so the 4428ec2 change cannot be claimed by any ticket; its cause is the two process.env fallbacks in scripts/github-event-log.mjs
2026-08-06 PR #64 and PR #65 closed and their branches deleted; the record was restored on main instead
2026-08-06 NOT PERFORMED: no Koru review, no Validator App attestation, no protected-check run and no merge to main were recorded for this ticket
50 changes: 50 additions & 0 deletions project/ticket-047/ai-codex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
participant-id: agent:codex
participant: codex
role: agent
ticket: ticket-047
---
# Participant: codex (AI agent)

## Understanding

Ticket-046 intentionally stopped before GitHub acquisition. The existing codec
already owns the DSL grammar, evidence/event hashes, strict validation and
atomic publication, so this ticket needs only an adapter at the integration
boundary. Editing a workflow in the same ticket would overlap the governance
workstream and make the change harder to review and finish within 30 minutes.

## Execution plan

1. Obtain explicit approval for the closed mappings and workflow-artifact
boundary.
2. Implement one dependency-free GitHub payload adapter that allowlists fields
before creating runtime event inputs.
3. Delegate rendering, validation, chain construction and atomic writing to the
built ticket-046 codec.
4. Add bounded fixtures and focused tests for supported mappings, rejection,
evidence safety, trust class and byte stability.
5. Document how a later governance ticket invokes the collector without
committing or appending generated artifacts.
6. Run focused, full host, governance and Docker checks before exact-head
independent review.

## Actual changes

- Human approval received; ticket transitioned from
`PLAN / WAIT_FOR_APPROVAL` to `IN_PROGRESS / EDIT`.
- Declared implementation boundary remains `project/ticket-047`, with no public
interface changes and no workflow or API polling.
- Implementing a bounded GitHub event acquisition adapter that emits one
canonical stream per payload and reuses the ticket-046 `t2c.event-log/v1`
codec and atomic writer.
- Added deterministic mapping for supported event/action combinations
(`push`, `pull_request`, `pull_request_review`, `workflow_run`), explicit
rejection of unsupported transitions, and canonicalized allowlisted evidence
projections.
- Added focused integration tests proving deterministic replay, SYSTEM_FACT review
recording and fail-closed unsupported actions.

## Blockers

- Implementation is complete in the approved scope; no blockers remain.
23 changes: 23 additions & 0 deletions project/ticket-047/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Ticket Changelog (ticket-047)

## [0.2.0] - 2026-08-05

- Ticket-047 was explicitly approved and moved to `IN_PROGRESS / EDIT`.
- Declared one-event-payload acquisition adapter boundary for push, PR, PR review
and completed workflow_run payloads.
- Reused the ticket-046 codec and atomic publication contract for
`t2c.event-log/v1` streams.
- Added deterministic GitHub→event mapping with strict allowlisted evidence
projections and repository/ticket/sha/actor validation.
- Added bounded integration tests for mapping, repeatability, review trust class,
unsupported-event fail-closed behavior and evidence sanitization.

## [0.1.0] - 2026-08-05

- Initial governance scaffold created.
- No human participant identity or content was generated.
- Defined a bounded GitHub payload acquisition plan dependent on ticket-046.
- Split acquisition from later workflow wiring so integration and governance
paths do not overlap in one ticket.
- Kept the existing `t2c.event-log/v1` codec as the single renderer, validator,
digest-chain and atomic-publication authority.
Loading
Loading