Skip to content

Latest commit

 

History

History
61 lines (51 loc) · 13.6 KB

README.md

File metadata and controls

61 lines (51 loc) · 13.6 KB

src/tools

Overview

Maintainer tools that run with tsx outside the agent-tty CLI. They build and validate dogfood/ proof bundles, record and publish the Hero Demo videos, and run release-please in CI. Each runnable file guards its main with isDirectExecution(import.meta.url) (src/util/isDirectExecution.ts) and sets process.exitCode instead of calling process.exit. The callers are package.json scripts (review-bundle, validate-bundle, validate-bundle:canonical), mise tasks (validate-bundles, demo:agent-uses-agent-tty, demo:agent-uses-agent-tty:upload-assets, demo:agent-uses-agent-tty:apply-video-urls) and .github/workflows/release-please.yml.

Interface

  • index.ts: empty scaffold (export {}). Its comment names this directory as the home for standalone CLI tools. [index.ts]
  • runReviewBundleCli(args, io?): review-bundle <bundle-dir> or review-bundle --all <parent-dir>. Returns 0 on success, 1 on bad arguments or any failed build. [review-bundle.ts:runReviewBundleCli]
  • buildReviewBundle(bundleRoot): scans a bundle and writes an index.html review page. The page links images, videos and files by relative path, so it needs the bundle files beside it. Returns the page path. [review-bundle.ts:buildReviewBundle]
  • scanBundleArtifacts, classifyBundlePath, normalizeBundleManifest, renderTinyMarkdown, generateReviewBundleHtml: the review page steps. ArtifactKind is 'screenshot' | 'video' | 'recording' | 'json' | 'notes' | 'script' | 'support' | 'other'. [review-bundle.ts:scanBundleArtifacts] [review-bundle.ts:classifyBundlePath] [review-bundle.ts:ArtifactKind]
  • BundleManifestSchema, BundleArtifact, ReviewBundleIo, NormalizedBundleMetadata, ReviewBundlePageModel: the permissive manifest schema for historical bundles and the review page types. [review-bundle.ts:BundleManifestSchema] [review-bundle.ts:ReviewBundlePageModel]
  • runValidateBundleCli(args, io?): validate-bundle <bundle-dir> [--profile <profile>]. Profiles are contract-reporting (default), interactive-renderer and canonical. Returns 0 when every check passes, else 1. [validate-bundle.ts:runValidateBundleCli] [validate-bundle.ts:BundleValidationProfile]
  • validateBundle(bundleDir, profile): runs the named checks for a profile and returns { bundleDir, profile, ok, checks[] }. The canonical profile checks the manifest, each artifact's presence, byte size and SHA-256, a commands.sh or reproduce.sh, command-status.tsv on pass results, and a notes file. [validate-bundle.ts:validateBundle]
  • checkCatalogParity(catalogPath, dogfoodRoot): checks that each dogfood/<dir>/ entry in the catalog is a directory. [validate-bundle.ts:checkCatalogParity]
  • BundleValidationResult, BundleValidationCheck, BundleValidationIo, CatalogParityResult, MAX_JSON_FILE_BYTES: validation types and the JSON size limit. [validate-bundle.ts:BundleValidationResult] [validate-bundle.ts:MAX_JSON_FILE_BYTES]
  • validateCanonicalBundles(): validates the four bundles in CANONICAL_BUNDLES with the canonical profile, then checks dogfood/CATALOG.md parity. Returns 0 or 1. [validate-canonical-bundles.ts:validateCanonicalBundles]
  • CanonicalBundleManifestSchema, CanonicalBundleArtifactSchema and their types: the strict manifest schema for canonical bundles. [bundleManifestSchema.ts:CanonicalBundleManifestSchema] [bundleManifestSchema.ts:CanonicalBundleArtifactSchema]
  • sha256File, canonicalBundleArtifactEntry, readCanonicalBundleManifest, writeCanonicalBundleManifest: hash files, build artifact entries, and read or write a canonical manifest. [canonicalBundleArtifacts.ts:canonicalBundleArtifactEntry] [canonicalBundleArtifacts.ts:writeCanonicalBundleManifest]
  • runHeroDemo(options) and parseHeroDemoArgs(argv): record Codex and Claude using agent-tty in a VHS tape with a tmux split (agent left, agent-tty dashboard --all right), then promote one passing run per agent into dogfood/agent-uses-agent-tty. Flags include --agent, --runs, --promote/--no-promote, --concurrency, --record-seconds, --bundle-dir and --keep-debug. [hero-demo.ts:runHeroDemo] [hero-demo.ts:parseHeroDemoArgs]
  • generateTape, generateRunner, generateDashboardRunner, selectPromotionRuns, promote, buildLeakFindings, sanitizePromotedText, renderReadme, selectedAgents, mapWithConcurrency, and the input types (HeroDemoOptions, GeneratedTapeInput, GeneratedRunnerInput, GeneratedDashboardRunnerInput, PromotionRunInput, PromotionSelection, RunRecord): Hero Demo building blocks. [hero-demo.ts:generateTape] [hero-demo.ts:sanitizePromotedText] [hero-demo.ts:promote] [hero-demo.ts:HeroDemoOptions]
  • prepareHeroVideoUploadAssets(options?): subcommand prepare-upload-assets [--bundle-dir] [--upload-dir]. Converts each agent's WebM and thumbnail into an H.264 MP4 with a poster intro. [hero-video-playback.ts:prepareHeroVideoUploadAssets]
  • applyHeroVideoUrls(options): subcommand apply-video-urls --codex-url URL --claude-url URL [--bundle-dir] [--root-readme]. Writes the uploaded video URLs into the root README.md and the bundle README.md. [hero-video-playback.ts:applyHeroVideoUrls]
  • posterConcatFilter, replaceVideoSrcs, PrepareHeroVideoUploadAssetsOptions, ApplyHeroVideoUrlsOptions: ffmpeg filter and <video src> rewrite helpers. [hero-video-playback.ts:posterConcatFilter] [hero-video-playback.ts:replaceVideoSrcs]
  • main in release-please-runner.ts (flag --dry-run): runs release-please as a library with the CommuniqueNodeStrategy release type and Communique changelog notes. [release-please-runner.ts:main] [release-please-runner.ts:CommuniqueNodeStrategy] [release-please-runner.ts:createCommuniqueChangelogNotes]
  • UnreleasedAwareChangelog, formatChangelogSection, normalizeCommuniqueBody, buildCommuniqueArgs, describeCommuniqueFailure, assertLlmCredentials, formatReleaseOutputs, formatPullRequestOutputs, todayIsoDate, and the types CommuniqueInvocation, CommuniqueRunner, RunnerOutputs: changelog and workflow-output helpers. [release-please-runner.ts:UnreleasedAwareChangelog] [release-please-runner.ts:formatChangelogSection] [release-please-runner.ts:RunnerOutputs] [release-please-runner.ts:describeCommuniqueFailure]

Invariants

  • CanonicalBundleManifestSchema and CanonicalBundleArtifactSchema use .strict(). sha256 must match /^[0-9a-f]{64}$/, bytes is a non-negative integer, commands and artifacts need at least one entry, and result is 'pass' | 'fail' | 'partial'. [bundleManifestSchema.ts:CanonicalBundleManifestSchema]
  • BundleManifestSchema uses .passthrough() on purpose. A comment says this keeps legacy dogfood bundles readable. A manifest that fails the schema but is an object falls back to legacy normalization. loadManifest adds a warning for that case. [review-bundle.ts:BundleManifestSchema] [review-bundle.ts:normalizeBundleManifest] [review-bundle.ts:loadManifest]
  • Manifest artifact paths must be non-empty, relative, and resolve inside the bundle root (isWithinRoot), or invariant() throws bundle artifact path escapes bundle root. The realpath symlink check in the same function ignores only a missing path (ENOENT). When the real path leaves the bundle root, invariant() throws bundle artifact path escapes bundle root via symlink. [review-bundle.ts:validateBundleRelativePath]
  • The directory scan throws when a directory or a symlink target resolves outside the bundle root, and it skips directories it has already visited. [review-bundle.ts:collectArtifactsFromDirectory]
  • validate-bundle fails the JSON check for files larger than MAX_JSON_FILE_BYTES (50 MiB). Canonical artifact paths outside the bundle root fail artifacts-present, and so do paths whose realpath leaves the root through a symlink. [validate-bundle.ts:MAX_JSON_FILE_BYTES] [validate-bundle.ts:runCanonicalChecks]
  • readCanonicalBundleManifest and writeCanonicalBundleManifest validate with CanonicalBundleManifestSchema.parse through readValidatedJsonFile and writeValidatedJsonFile (src/storage/manifests.ts). [canonicalBundleArtifacts.ts:readCanonicalBundleManifest] [canonicalBundleArtifacts.ts:writeCanonicalBundleManifest]
  • parseHeroDemoArgs rejects unknown flags and requires positive integers. Promotion requires --runs >= 3 and --agent both. selectPromotionRuns requires 3 passing runs per agent. [hero-demo.ts:parseHeroDemoArgs] [hero-demo.ts:selectPromotionRuns]
  • A Hero Demo run passes only when the proof files are non-empty, the transcript shows the dashboard header Sessions ·, and the final file equals the expected text. [hero-demo.ts:runOne]
  • Promotion validates the manifest with CanonicalBundleManifestSchema.parse through writeCanonicalBundleManifest. It throws leak check failed when buildLeakFindings finds account-sensitive patterns in the promoted text files: home paths, emails, the ANTHROPIC_AUTH_TOKEN, ANTHROPIC_API_KEY and OPENAI_API_KEY names, API Usage Billing, Auth conflict and Welcome back lines, and token-like strings. The check runs on the sanitized texts before promotion clears or writes --bundle-dir, so a failure leaves the bundle unchanged. [hero-demo.ts:promote] [hero-demo.ts:buildLeakFindings]
  • applyHeroVideoUrls asserts that each URL starts with https://github.com/user-attachments/assets/ and that exactly two <video src> tags match. [hero-video-playback.ts:applyHeroVideoUrls] [hero-video-playback.ts:replaceVideoSrcs]
  • assertLlmCredentials requires ANTHROPIC_API_KEY or OPENAI_API_KEY, plus COMMUNIQUE_MODEL when only the OpenAI key is set. main requires GITHUB_TOKEN and GITHUB_REPOSITORY through requireEnv. [release-please-runner.ts:assertLlmCredentials] [release-please-runner.ts:requireEnv]
  • describeCommuniqueFailure appends a hint that names max_tokens when Communique reports communique::malformed_submission. communique.toml sets [defaults].max_tokens = 16384 because Communique 1.1.3 cuts each response at 4096 tokens otherwise. [release-please-runner.ts:describeCommuniqueFailure]
  • A comment on formatChangelogSection states that the heading must not contain a v after [, because release-please then cannot parse the merged PR. [release-please-runner.ts:formatChangelogSection]

Side Effects

  • buildReviewBundle reads the bundle tree and overwrites <bundle>/index.html with fs/promises.writeFile. [review-bundle.ts:buildReviewBundle]
  • validate-bundle.ts and validate-canonical-bundles.ts only read files (readFile, stat, realpath, hashing with createReadStream). runValidateBundleCli prints the JSON result to stdout and a PASS/FAIL summary to stderr. validateCanonicalBundles writes PASS/FAIL lines to stderr only. [validate-bundle.ts:runValidateBundleCli] [validate-canonical-bundles.ts:validateCanonicalBundles]
  • runHeroDemo deletes and recreates a debug root under <tmpdir>/agent-tty-hero-demo/. After promotion it deletes the debug root again unless --keep-debug is set. [hero-demo.ts:runHeroDemo] [hero-demo.ts:mkDebugRoot]
  • installLocalAgentTty runs npm run build and npm pack in the repo root, so it writes dist/ and a .tgz tarball into the checkout. It then runs npm install -g --prefix into the debug root and deletes the tarball. [hero-demo.ts:installLocalAgentTty]
  • runHeroDemo spawns git init in each run workspace, vhs (which starts tmux, codex or claude, and agent-tty dashboard), tmux -L <socket> kill-server, ffmpeg and agent-tty doctor --json. It probes vhs, tmux, ttyd, ffmpeg, codex and claude for their versions. It reads the AGENT_TTY_HERO_* environment variables. [hero-demo.ts:runHeroDemo] [hero-demo.ts:killTmuxServer] [hero-demo.ts:collectToolVersions] [hero-demo.ts:parseHeroDemoArgs]
  • After the leak check passes, promotion clears --bundle-dir (except .gitignore and VIDEO_PLAYBACK.md), then writes the artifacts, promoted-run-summary.md, README.md, reproduce.sh, .gitignore, manifest.json and artifacts/.gitkeep. Only manifest.json goes through a src/storage/ helper. writeCanonicalBundleManifest writes it atomically with writeValidatedJsonFile. It writes sanitized text artifacts with fs/promises.writeFile and copies binary artifacts with copyFile. [hero-demo.ts:cleanBundle] [hero-demo.ts:promote] [hero-demo.ts:copyPromotedArtifact] [canonicalBundleArtifacts.ts:writeCanonicalBundleManifest]
  • prepareHeroVideoUploadAssets deletes and recreates the upload directory (default <bundle>/.debug/video-upload), runs ffmpeg and ffprobe with execFileSync (overridable with HERO_VIDEO_FFMPEG and HERO_VIDEO_FFPROBE), and writes MP4, ffprobe JSON and SHA256SUMS files. [hero-video-playback.ts:prepareHeroVideoUploadAssets]
  • applyHeroVideoUrls overwrites the root README.md and the bundle README.md and rewrites the bundle manifest.json through writeCanonicalBundleManifest. [hero-video-playback.ts:applyHeroVideoUrls]
  • release-please-runner.ts calls the GitHub API through the release-please library (creates releases and the release PR, or only builds them with --dry-run). It runs the communique binary with execFile in the inherited working directory. Communique writes its notes file into a mkdtemp directory, which the code removes in a finally block. The runner appends releases_created, release_tags, prs_created and pr_branches to $GITHUB_OUTPUT (stdout when unset). [release-please-runner.ts:main] [release-please-runner.ts:createCommuniqueChangelogNotes] [release-please-runner.ts:runCommuniqueBinary] [release-please-runner.ts:writeGithubOutputs]

Verification

  • Run: npx vitest run test/unit/tools
  • Run: npm run validate-bundle:canonical
  • Run: npm run typecheck