Skip to content
Closed
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
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,7 @@ T2C_EXAMPLE_ROOT=examples/backend
T2C_COMPARE_WORKSPACE=false
T2C_COMPARE_BASE=origin/main
T2C_TYPESCRIPT_CLI=

# GitHub context used by CI event-log acquisition scripts.
GITHUB_EVENT_PATH=
GITHUB_REPOSITORY=
35 changes: 35 additions & 0 deletions docs/EVENT_LOG_DSL.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,38 @@ 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)

This repository now defines a dedicated, bounded boundary:

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

Input:

* one GitHub Actions JSON payload (`--event-path`)
* one event name (`push|pull_request|pull_request_review|workflow_run`)
* explicit `--output` path for the produced `logs.dsl.txt`

Behavior:

* no payload is committed to `main` from this script,
* only allowlisted fields are normalized and projected into evidence,
* unsupported events/actions fail closed,
* 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.

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"
```
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.
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.
101 changes: 101 additions & 0 deletions project/ticket-047/intent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
{
"schema": "new-project.intent/v2",
"ticket": "ticket-047",
"summary": "Collect bounded GitHub evidence into event logs",
"workstream": "integration",
"allowedPaths": [
"project/ticket-047/**",
"TODO.md",
"project/TICKETS.md",
"scripts/github-event-log.mjs",
"test/workflow-validation.test.ts",
"test/fixtures/event-log/v1/github-event-payloads.json",
"docs/EVENT_LOG_DSL.md"
],
"forbiddenPaths": [
"project/ticket-*/user-*.md",
".github/workflows/**",
".governance/**",
"src/**",
"package.json",
"package-lock.json",
"sdk/**"
],
"stacks": ["node", "docker"],
"dependsOn": ["ticket-046"],
"conflictsWith": [],
"integrationTicket": null,
"delivery": {
"acceptedBaseSha": "b8392f76592138e006ca5dff9af52082208acee5",
"targetBranch": "main",
"outcome": "Convert one bounded GitHub Actions event payload into one canonical immutable workflow logs.dsl.txt artifact",
"nonGoals": [
"No GitHub workflow or repository-setting change",
"No GitHub API polling or historical reconstruction",
"No mutation or commit of a completed event log",
"No new DSL, public interface, dependency or LLM-derived approval"
],
"complexity": "S",
"estimatedMinutes": 30,
"budgets": {
"maxImplementationFiles": 4,
"maxAffectedComponents": 2,
"maxPublicInterfaceChanges": 0,
"maxRuntimeDependencies": 0
},
"architecture": {
"status": "accepted",
"decision": "A dependency-free integration script allowlists one GitHub event payload into canonical evidence and delegates all DSL rendering, validation, hashing and atomic publication to the ticket-046 runtime codec; a later governance ticket only wires this stable command into Actions",
"components": [
{
"name": "github-event-acquisition-adapter",
"paths": ["scripts/github-event-log.mjs"]
},
{
"name": "github-event-acquisition-evidence",
"paths": [
"test/workflow-validation.test.ts",
"test/fixtures/event-log/v1/github-event-payloads.json",
"docs/EVENT_LOG_DSL.md"
]
}
],
"responsibilityChanges": false,
"interfaceChanges": [],
"dataChanges": [
"Each supported GitHub Actions event can produce a separate immutable workflow-run logs.dsl.txt",
"Evidence digests cover only event-specific allowlisted canonical JSON fields"
],
"ui": {"impact": "none", "states": [], "evidence": []},
"rollback": "Remove the standalone acquisition script, fixture and its workflow-validation cases; the ticket-046 codec and pipeline logs remain unchanged"
},
"runtimeDependencies": [],
"validation": [
{
"criterion": "AC-02",
"commands": ["npm run build", "node --test dist/test/workflow-validation.test.js"],
"evidence": "Supported event/action mappings and unsupported cases are exercised from bounded fixtures"
},
{
"criterion": "AC-03",
"commands": ["node --test dist/test/workflow-validation.test.js"],
"evidence": "Canonical allowlisting, unsafe values and non-leakage of raw payload fields are tested"
},
{
"criterion": "AC-04",
"commands": ["node --test dist/test/workflow-validation.test.js"],
"evidence": "Output is parsed by the existing codec and immutable atomic publication is verified"
},
{
"criterion": "AC-05",
"commands": ["node --test dist/test/workflow-validation.test.js"],
"evidence": "Review payloads remain SYSTEM_FACT and cannot synthesize an approval attestation"
},
{
"criterion": "AC-06",
"commands": ["make governance", "make verify", "make docker-smoke", "git diff --check"],
"evidence": "Deterministic, repository-wide and container gates pass"
}
]
}
}
Loading
Loading