Skip to content

INTB-279: identify Tabellio v0.6.0 runners - #44

Open
hudsonaikins wants to merge 17 commits into
mainfrom
codex/intb-279-v060-release
Open

INTB-279: identify Tabellio v0.6.0 runners#44
hudsonaikins wants to merge 17 commits into
mainfrom
codex/intb-279-v060-release

Conversation

@hudsonaikins

@hudsonaikins hudsonaikins commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • identify the Tabellio package version and exact runner source in machine-readable output
  • emit validation-result v0.4 runner provenance while retaining v0.1-v0.3 readers
  • require exact annotated remote-tag and published GitHub Release evidence before reporting released
  • add v0.6.0 release notes and exact six-type product validation

Acceptance

Plane: INTB-279
Contract: docs/intb-279-v060-execution-contract.md
Candidate: 4b87fe5
Entire checkpoint: 00cd873c5d9a

Evidence

  • npm test: passed, 344 tests
  • focused v0.6.0 product validation: passed on candidate, run validation-67f80c48-36b4-4303-8b33-d9f813f9b088, six required validator types, zero cost
  • full Tabellio product validation: passed on candidate, run validation-50f19084-f35e-4e2e-9cb6-bb30b950852d, ten validators, zero cost
  • Fallow changed-code audit: passed, zero introduced dead-code, complexity, or duplication issues
  • npm pack dry run: version 0.6.0 and all required identity/release files present

Boundaries

No merge, tag, GitHub Release, deployment, billing, DNS, infrastructure, production-data, or consumer-repository mutation is authorized by this PR.

Entire-Checkpoint: 29c1c7c761ec
@makeplane

makeplane Bot commented Jul 29, 2026

Copy link
Copy Markdown

Linked to Plane Work Item(s)

References

This comment was auto-generated by Plane

Entire-Checkpoint: 29c1c7c761ec
@hudsonaikins
hudsonaikins marked this pull request as ready for review July 29, 2026 05:25
Entire-Checkpoint: 1a7858ccb0d6
Entire-Checkpoint: 29c1c7c761ec

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 27e8475655

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread scripts/lib/runner-identity.mjs Outdated
}

async function readGitSourceIdentity(root, packageVersion) {
const revision = await runGit({ args: ["rev-parse", "HEAD"], cwd: root });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop binding packaged installs to the consumer repo

When Tabellio is installed under another Git checkout, such as a consumer project's node_modules, this git rev-parse HEAD walks up to the consuming repository because the package directory has no .git. tabellio-version and v0.4 validation results then record the consumer commit/status/tag as the runner source instead of reporting unavailable source identity, so provenance can falsely validate an unrelated project commit. Please fence Git discovery to the package checkout or return null unless the package root is itself a Git worktree.

Useful? React with 👍 / 👎.

Comment thread scripts/lib/validation-runner.mjs Outdated
Comment on lines +450 to +451
requiredString(value.packageName, "validation result.runner.packageName");
requiredString(value.packageVersion, "validation result.runner.packageVersion");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce package identity in the runtime reader

For v0.4 results validated through the repository's runtime path (check-tabellio-validation --result or latestValidationResult), any non-empty runner.packageName and arbitrary package version currently pass even though the v0.4 schema pins packageName to @intelip/tabellio and the release contract is about Tabellio's package identity. This lets mispackaged or forged runner evidence satisfy the new identity checks whenever consumers use the built-in validator instead of an external JSON Schema validator.

Useful? React with 👍 / 👎.

}
},
"revision": {
"$ref": "validation-result.v0.3.schema.json#/$defs/revision"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use resolvable refs in the v0.4 schema

Because this schema declares an absolute URN $id, this relative $ref is resolved under that URN rather than to the packaged validation-result.v0.3.schema.json file. External JSON Schema validators that load v0.4 by id or from the file can therefore fail to resolve the shared definitions for every v0.4 result; use internal definitions or refs keyed to the v0.3 schema id.

Useful? React with 👍 / 👎.

assert.equal(result.result.runner.packageVersion, "0.6.0");
assert.match(result.result.runner.sourceCommit, /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/);
assert.equal(typeof result.result.runner.sourceDirty, "boolean");
assert.equal(result.result.runner.releaseTag, null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow release tags in the runner identity test

Once the approved v0.6.0 tag exists on the release commit, tabellioRunnerIdentity() returns that tag for this checkout, so this assertion makes npm test fail on the released source even though that is the desired post-release identity. Avoid pinning null here, or use a no-tag fixture, so checks keep passing after the release tag is created.

Useful? React with 👍 / 👎.

Entire-Checkpoint: d123a88b9899
Entire-Checkpoint: 29c1c7c761ec

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c20ba5467f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread scripts/tabellio-version.mjs Outdated
const expectedCommit = options.expectRef
? verifiedCommit((await runGit({
args: ["rev-parse", "--verify", "--end-of-options", `${options.expectRef}^{commit}`],
cwd: process.cwd(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve expected refs in the runner checkout

Although the identity lookup is now fenced to the package root, this expectation check still resolves --expect-ref in the caller's current directory. When tabellio-version is invoked via an installed bin or absolute script path from outside the Tabellio checkout, HEAD is looked up in the caller repo (or fails outside any repo) while identity.sourceCommit comes from the runner package, producing a false source_commit_mismatch/blocked result for the same runner; resolve the expected ref against the runner checkout or compare full OIDs without using the caller cwd.

Useful? React with 👍 / 👎.

Comment on lines +81 to +85
"releaseTag": {
"oneOf": [
{
"type": "string",
"pattern": "^v(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?$"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Tie releaseTag to packageVersion in the schema

Because the v0.4 schema only checks that releaseTag looks like some version tag, an external JSON Schema validator will accept a runner such as packageVersion: "0.6.0" with releaseTag: "v9.9.9"; the runtime reader rejects that mismatch, but consumers relying on the published schema can still treat forged or stale release identity as structurally valid. Pin the tag to the package version for this schema version, or otherwise make mismatches invalid in the schema contract.

Useful? React with 👍 / 👎.

Comment thread scripts/lib/runner-identity.mjs Outdated
}

async function readGitSourceIdentity(root, packageVersion) {
const worktree = await runGit({ args: ["rev-parse", "--show-toplevel"], cwd: root });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Sanitize ambient Git environment before reading identity

This call still inherits GIT_DIR/GIT_WORK_TREE through runGit, so an environment that sets GIT_WORK_TREE to the package directory and GIT_DIR to some other repository makes the realpath fence pass while rev-parse HEAD, status, and tag --points-at report the unrelated Git dir as a clean released Tabellio source. Fresh evidence is that this bypass works even for a non-Git package directory, so clear ambient Git repository variables or otherwise bind the .git directory to the package checkout before recording runner provenance.

Useful? React with 👍 / 👎.

Entire-Checkpoint: 80c483965edd
Entire-Checkpoint: 29c1c7c761ec
Entire-Checkpoint: 8648bed8c3f0
Entire-Checkpoint: 29c1c7c761ec

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff12eca263

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread scripts/lib/runner-identity.mjs Outdated
Comment on lines +56 to +58
dirty: status.stdout.length > 0,
releaseTag: matchingReleaseTag(tags.stdout),
fingerprint: await worktreeFingerprint(root, commit, status.stdout),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Check index bits before declaring clean source

This clean check can be bypassed in checkouts where a tracked runner file has Git's assume-unchanged or skip-worktree bit set: git status and the later git diff HEAD used for the fingerprint both ignore the modified contents. I reproduced this by marking scripts/lib/runner-identity.mjs with each bit, editing it, and tabellioRunnerIdentity() still returned sourceDirty: false, so release/validation provenance can claim a clean tagged commit while executing different local code; clear or detect these index bits, or hash tracked worktree contents, before marking the runner clean.

Useful? React with 👍 / 👎.

"requiredValidatorTypes": ["static", "schema", "semantic", "workflow", "operational", "security"]
},
"validators": [
{"id": "v060-identity-static", "type": "static", "argv": ["node", "scripts/tabellio-validator.mjs", "--profile", "v060-identity-static", "--validator-id", "v060-identity-static", "--out", ".artifacts/tabellio/v060-identity-static.json"], "cwd": ".", "timeoutMs": 300000, "required": true, "evidence": {"path": ".artifacts/tabellio/v060-identity-static.json"}, "policy": {"metricThresholds": [{"metric": "runner_identity_static_pass", "operator": "eq", "value": 1}], "maxCostUsd": 0, "requireCostTelemetry": true}},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ship the validator registry with the focused manifest

When this new packaged manifest is run from an npm install, these validators invoke scripts/tabellio-validator.mjs without --config, so the CLI looks for the default .tabellio/validators.json; I checked npm pack --dry-run --json, and that file is absent from the published file list because the package allow-list only includes the validation JSONs and scripts. The shipped tabellio.v060-identity.validation.json therefore blocks immediately with a missing registry instead of producing the promised v0.6.0 identity evidence, so either include .tabellio/validators.json in the package or make the manifest reference a packaged config.

Useful? React with 👍 / 👎.

Comment thread scripts/lib/runner-identity.mjs Outdated
}

async function worktreeFingerprint(root, commit, status) {
const diff = await runGit({ args: ["diff", "--no-ext-diff", "--binary", "HEAD", "--"], cwd: root });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid buffering dirty source diffs for identity

For dirty runner checkouts with a large tracked text change, this full git diff --binary is captured through runGit's fixed output buffer before identity can be returned. I reproduced a checkout with a ~12 MB text diff where tabellioRunnerIdentity() failed with a git diff max-buffer error instead of emitting sourceDirty: true, so version checks and validation runs can block exactly when the contract says dirty source should remain visible; stream/hash the diff or fall back to a dirty fingerprint without requiring the entire patch in memory.

Useful? React with 👍 / 👎.

@hudsonaikins
hudsonaikins force-pushed the codex/intb-279-v060-release branch 4 times, most recently from 33ff5f7 to 642c078 Compare July 29, 2026 15:07
Entire-Checkpoint: 5f2b26ae1e15
@hudsonaikins
hudsonaikins force-pushed the codex/intb-279-v060-release branch from 642c078 to 620e49f Compare July 29, 2026 15:19
Entire-Checkpoint: 79aed0fa931c

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8f57e196f4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread scripts/lib/runner-release.mjs Outdated
});
const refs = new Map(result.stdout.trim().split(/\r?\n/)
.filter(Boolean)
.map((row) => row.split(/\s+/)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fix remote tag parsing for release verification

When --require-release-tag reaches a real annotated origin tag, this parse stores the git ls-remote rows as [oid, ref] entries. I checked a local annotated-tag remote and git ls-remote --tags printed the object ID first and refs/tags/v0.6.0 second, so the later refs.get(directRef)/refs.get(peeledRef) lookups are keyed by ref and always miss. That makes verifyPublishedRunnerRelease return false before querying GitHub, so the documented release gate can never pass even after the annotated tag and release exist; swap the tuple to [ref, oid] before constructing the Map.

Useful? React with 👍 / 👎.

Entire-Checkpoint: a91d97f163c9
Entire-Checkpoint: 4370fb5a4f45
Entire-Checkpoint: d43fbf86bed8
Entire-Checkpoint: 7044872f4085
Entire-Checkpoint: 0c3674f381c8
Entire-Checkpoint: 00cd873c5d9a

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4b87fe5642

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread .tabellio/validators.json
"summary": "Packaged artifact completeness and private-evidence boundaries"
},
"v060-identity-static": {
"commands": [["node", "--test", "tests/runner-identity.test.mjs", "tests/validation-runner.test.mjs"]],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ship tests used by identity validators

Fresh evidence after the registry was added: npm pack --dry-run --json now includes .tabellio/validators.json, but it still includes no tests/** files, while this packaged profile invokes tests/runner-identity.test.mjs and tests/validation-runner.test.mjs. Extracting the package and running this profile produces failed evidence (Could not find 'tests/runner-identity.test.mjs, tests/validation-runner.test.mjs'), so the focused v0.6 identity validation shipped in the npm package cannot pass from a packaged install unless the tests are shipped or these profiles are changed to use packaged checks.

Useful? React with 👍 / 👎.

Comment thread CHANGELOG.md

## Unreleased

## 0.6.0 - release candidate

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Date the v0.6.0 changelog heading

When tabellio-release plan is used for this 0.6.0 candidate, the existing release planner rejects the current changelog because it specifically requires a heading matching ## 0.6.0 - YYYY-MM-DD before creating the release intent. Leaving this as release candidate means the documented release gates cannot pass for the version introduced here until this heading is converted to the dated release format.

Useful? React with 👍 / 👎.

@hudsonaikins

Copy link
Copy Markdown
Contributor Author

Buildkite gate update for exact candidate 4b87fe564243175683c24b49630233f0f5b2547a:

  • Build #145 reproduced the immediate pre-agent cancellation.
  • Hosted queue configuration is valid; Buildkite status is operational.
  • Authenticated billing shows the Evaluation Plan at 4,012 / 4,000 Linux AMD64 vCPU minutes (100% consumed). This is the blocking cause.
  • Local validation, 344 tests, terminal review, and all GitHub Actions checks remain passed on this exact SHA.

No subscription change or merge performed. Next gate: increase Buildkite quota or activate Pro, rerun required exact-head Buildkite CI, then request separate merge approval.

Entire-Checkpoint: 0bdb97273214
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant