Repository navigation
Conversation
One check script, run by a factory-ci workflow and by the factory gate
…ker exports A whitespace run followed by other text made the `[...]+$` trim backtrack quadratically on untrusted session output (200k spaces ran past a minute). Trim with index loops over the same Rust White_Space set instead. DONE_MARKER, NEEDS_INFO_LINE and STUCK_LINE had no importer, which fails knip:check; they are module-private until a caller needs them.
…rrupt and drain tests - spawn's synchronous throws (a NUL byte in env or args) now fail with RunSpawnError instead of dying - RunSpawnError keeps the command only in cause; its attributes are shell and cwd - the env allowlist and defaults are no longer exported (knip) - RunResult.exitCode doc: a timed-out command can still exit 0, check timedOut first - the post-run kill comment says a process that left the group escapes - tests: an interrupted run kills the group, a stray outside the group does not hold run past the drain wait, a tail cut inside a UTF-8 character - design.md Shape diagram: gate commands go through node:child_process in factory/process.ts, not ProcessRunner
…ough a pull request Red: factory/scripts/sync.sh does not exist yet, so every case fails on reading it. Covers the tag choice by version order, the up-to-date exit, a clean merge that records UPSTREAM and merges the pull request, a route tree conflict that regenerates, another conflict that aborts and files or comments on an issue, and failing checks that open a draft and an issue. Issue: #4
…h a pull request sync.sh picks the newest v*-nightly.* tag by version order, stops with "up to date" when factory/UPSTREAM names it, and otherwise merges it on sync/<tag> with --no-ff, regenerating the route tree with regenerate-routes.sh when only that file conflicts. Any other conflict aborts and files or comments on `Sync to <tag> conflicts`. Green checks push, open `sync: <tag>` and merge it; red checks open it as a draft and file `Sync to <tag> fails checks` with the failing step's last 200 lines. factory-sync.yml runs it daily at 03:17 UTC and on dispatch. The test's gh stub answers `issue list` by title so the comment-or-create decision is covered; the conflicts body may mention the route tree in its hint, so the test checks the list line only. Issue: #4
status is polled per session, so it now reads the runs and assistant messages through getThreadRecords instead of loading the whole thread projection. Adds tests for blank project and provider instance ids, thread read errors and project store failures failing as sessions errors.
…n a failed merge or push Red: a merge that fails without a conflict falls through as a route tree conflict, a refused push dies without saying why, a tag with a quote is accepted, vp i and check.sh see GH_TOKEN, and failing checks exit 0. Issue: #4
…token from upstream code A merge that failed without unmerged paths was taken for a route tree conflict and went on to commit the UPSTREAM bump alone; it now prints git's output and exits 1. A refused push says which branch and tag. The tag must match the nightly pattern before it reaches gh, git or jq. vp i, the generator and check.sh run without GH_TOKEN; the workflow stops persisting the checkout token and routes git push through gh's credential helper instead. Failing checks exit 1 after filing the issue, so the scheduled run is red on both failure paths. Issue: #4
…dirty builds - build.sh smoke-tests the archive in its stage dir and moves it to release/ only after the smoke passes, so a failed smoke leaves no archive install.sh would take. T3FAC_SMOKE_TIMEOUT sets the deadline (60 s). - Uncommitted changes to tracked files add `.dirty` to the version, so a rebuild of the same commit never replaces the clean build on install. - install.sh and rollback.sh source factory/scripts/lib/t3fac.sh for the install root, the LaunchAgent label and plist, and restart_job. T3FAC_UNLOAD_WAIT sets the unload wait (10 s). - Tests: the whole of build.sh with stubbed vp and cargo (pass, early exit, no 200, no "factory started"), a dangling `previous`, and a job that never unloads.
Adapter: find a project, launch a thread and read its status in-process
… every directory Review round 1 of PR 35. - An append first reads the lines written since its last one, by any handle, so a `finished` or `gate_command` line another handle wrote counts (f14), and Ledger.open reads through the fd it appends to, closing the gap between the read and the open. - A write starts with a newline whenever the file does not end in one, so another handle's cut-off line cannot swallow this handle's event (f4). - Ledger.create and MachineLog.open sync the file's directory, the data dir and its parent every time, so a retry after a failed sync still makes them durable (f13, f7). - A cause attempt that is not a u32 is left out, so the cause still reads back (f3). - The RunEvent doc names the fields that hold text sent elsewhere (f2). - Tests: open counts a whole last line left without its newline (f5); gate attempts outside u32 do not count (f6). - An issue number above 2^53 is written digit for digit (f1). - Shared limits in one module, a reason on every diagnostics directive, no barrel, no re-export shims, enum arrays as union types (f10, f11, f12).
…ed changes Two builds of one commit with different uncommitted edits used to share the `.dirty` version, so installing the second deleted the first. The suffix is now `.dirty.<8 hex>` from `git diff HEAD --binary`, so only identical contents share a name.
FactoryPaths keeps the adapter's shape from main (the service and its layer in factory/t3/paths.ts) and gains machineConfigPath, which the config loader reads. factory/paths.ts goes.
…fy/delete conflicts abort Red: the gh stub now prints every open issue as number and title rows, so the comment-or-create decision is the script's own match; a fuzzy search hit listed first must not win. The modify/delete case passes already and pins --diff-filter=U. Issue: #4
… in jq The tag no longer reaches a jq program, and the exact-title match is the script's own, so a fuzzy search hit cannot receive the comment. The token comments say what env -u does and does not do. Issue: #4
Config: the factory's machine config and a repo's factory block
…finished Review round 2 of PR 35. - A finished line cut off just before its newline was not seen by a live handle's catch-up, which only reads whole lines; the next append's leading newline then completed it and landed after it. An append now ends a cut-off last line first, as a reopen does, then catches up, so that line counts and the append is refused (f15). - openForAppend returns the file alone, and its doc names O_RDWR and why read access is needed (f16).
Cases for the stream of thread ids whose latest run changed status, and the real-orchestration harness extracted from sessions.contract.test.ts into contract.testkit.ts so both contract tests share it. Fails now: events.ts does not exist yet, so events.test.ts, events.contract.test.ts and sessions.contract.test.ts (through the testkit) fail to import it. Issue: #7
Callers depend on the FactoryProcess tag, so their tests can swap in a fake layer instead of starting real processes. The two process-group tests now use withTempDir and waitForDeath, so a failed assertion no longer leaks the temp dir, and their wall-clock bound is 5 s instead of 1 s; the grandchild death check still proves the kill.
…r goes through the io seam Review round 3 of PR 35. - LedgerError is a Data.TaggedError tagged `LedgerError`, so an Effect caller can catch it with Effect.catchTags and branch on `kind`. The messages stay softfac's; an Io error keeps the file system's error as its `cause` (f9). - The newline that ends a cut-off last line is written and synced through AppendIo, so a test can make it fail: the append then throws Io and writes no event, and the next append repairs the line (f17).
Unit tests for send, archive and removeWorktree, and a contract test that sends a second message, archives and removes the worktree against T3's real orchestration layers. Fails now: FactorySessions has no send, archive or removeWorktree, and Sessions.layer does not yet take ThreadManagementService, GitVcsDriver or FileSystem. 21 tests red. Issue: #6
Run commands with a cleared environment, a time limit and a bounded output tail
…ter open repairs it Review round 4 of PR 35: covers the repair at open with a write that throws and one that writes nothing (f18).
FactoryEvents.runStatusChanges emits a thread's id each time its latest run changes status, built on EventSinkV2.stream from the live position, with no history replayed. The latest-run selection is shared with `status` through an exported latestRun in sessions.ts. The contract test now drives one thread (the replay transcript serves a single turn) and checks the live path and no replay. Issue: #7
send dispatches message.dispatch with automatic delivery through ThreadManagementService. archive reads the thread, dispatches thread.archive under a fresh command id per attempt, and counts an archived or unknown thread as done. removeWorktree runs git worktree remove --force from the worktree, finishes a 'Directory not empty' leftover after a wait, and keeps the branch. Tests: fixes to the test harness only (typed ids, a tagged dispatch error, the removal test's temp directory, the findProject layer's new dependencies). Issue: #6
… worktree on disk Issue: #6
transition threw a plain Error, so an Effect caller saw a stale or duplicate webhook's event as an untyped defect. It now returns a Result whose failure is a tagged InvalidTransition, as softfac's transition returns Result.
Follow-up to f9 of PR 35, as asked: the single tagged LedgerError becomes six Schema.TaggedError classes (InvalidRunIdError, LedgerAlreadyExistsError, LedgerAlreadyFinishedError, LedgerNotFoundError, LedgerUnknownEventError, LedgerIoError), so an Effect caller picks them apart with Effect.catchTags instead of branching on a `kind`. Messages are built from each class's attributes and stay softfac's; LedgerIoError keeps softfac's `<path>: <file system error>` text, pinned by a test, with the error itself as its `cause`. The ioError and invalid mappers are gone.
… with a second launch F1: assert thread A's run ends completed (terminal event and sessions.status), not any terminal status. F2: replace the 1 s negative timeout with a consumer started before launch B that must emit B's id, not A's. Issue: #7
End of a run: merge, close, abandon and stop by hand
… provider Red: the testkit's layerRuntime only takes a transcript URL, so building the e2e transcripts in memory fails to decode (Path.fromFileUrl, Invalid URL), and factoryRuntime has no gateRemoteBase option yet to point the gate at the file:// remote. Both cases fail before the first pass. Issue: #21
… and a file:// gate remote layerRuntime takes a transcript as ndjson text as well as a fixture URL, and factoryRuntime takes a test-only gateRemoteBase for the gate's fetch. The e2e test now passes: ready, triage, building, pr-open, with the ledger in softfac's order and the thread archived; and a gate that fails once is sent back into the same session and passes the second time. Issue: #21
…own clone Red: factory/config.example.yml does not exist yet, so loadMachineConfig reports no config and the test fails. Issue: #21
Watches original-solutions/t3code-factory from the clone ~/EA/projects/t3code-factory-fac, with the fork's own gh login directory. Issue: #21
The plist sets GH_CONFIG_DIR to ~/.config/t3fac/gh, so the server, the gate and its agent sessions act as the factory's own login, and appends the directory the vp that the gate runs lives in to PATH. Issue: #21
Moves the hand-back and move-back steps from the README into factory/docs/handover.md, with the build, install, config, clone and project, Rust factory removal, restart and first-run check that lead up to them. Issue: #21
Only factory/t3/ may import T3 packages; the test took ThreadId from @t3tools/contracts only to brand a string it never used as one. Issue: #21
The hand-back and move-back runbook now has the factory that lets go of the repo restart before the other one takes it, so both never watch it at once. Also drops an unused type in the e2e test, a repeated heading in the runbook, and notes that gh_config_dir must match the plist's GH_CONFIG_DIR.
Handover: the fork's factory is ready to build this repo
…can remove its HOME
…tory-config fix(factory): build.sh smoke test passes on a clean build
The tests need forward, activitySince, the new Seen fields, the two message builders and the forward actions of applyActions, none of which exist yet: they do not compile and fail until the next commit. Issue: #22
forward sends the instructors' new comments and their edit of the issue body into a building run's session, once each, under softfac's message wording, command ids and forward-wait steps. The pass runs it between watch and advance and holds the gate in a pass where it sent something. activitySince reads the activity from GitHub. Issue: #22
Fails: a running, reminded or paused run with a pending gate send does not start the gate, a pending send does not win over the gate waiting for a sent comment, and a ledger read error for the pending check is not recorded. Issue: #22
Port softfac's dropped-comment notice into `forward`: after the sends, each comment `activitySince` drops gets one comment on the issue in softfac's fixed words and a `comment-dropped <id>` step, and a comment told about as dropped is never forwarded later (f10). Look up the editors of edited comments in one GraphQL call per 100 ids instead of one per comment (f5). Rename `GatePayload` to `ActionPayload`, since forwards carry their message on it too (f7). Pin the live `hasPendingGateSend` wiring (f3) and a failed pending-send read for a finished session (f4) with tests. Fixes f3, f4, f5, f7, f10.
Forward instructor comments and edits into a running session
|
Opened against the wrong repo by mistake, sorry. |
|
Macroscope skipped reviewing this pull request. Per-review cost limit exceeded (workspace setting). This review would cost an estimated $26.42, which exceeds your per-review limit of $15.00. The top 3 files driving up this estimate:
Tip To get this pull request reviewed, you can:
|
ApprovabilityVerdict: Needs Human Approval Macroscope's review found this PR requires human approval — This change adds a substantial production factory capability, authenticated server integration, automated publishing/synchronization workflows, and installation infrastructure alongside the runner edits. It also introduces product defaults and static-analysis diagnostic suppressions, so the breadth and operational impact require human review. Needs human approval because:
Review your spending limits in Billing settings, or comment |
|
Factory catalog cross-reference — 2026-10-26. Prior-work history: this PR is cataloged for its work on Linux CI runner configuration in the public original-solutions factory, acknowledged in our catalog. No code from that effort was copied into this derivative. This historical cross-reference requests no reopening and implies neither quality rejection nor an installation dependency. Factory Ideas · Pinned fork source/guide · Source release. Version-pinned community experimental source preview; full lifecycle acceptance remains open. No upstream endorsement or current-PR-head test acceptance is claimed. Prepared with GPT-6.1 Sol through Codex in T3 Code. |
Switches GitHub-hosted Linux jobs (
ubuntu-latest/ubuntu-24.04) toruns-on: jog, matching livepane/replymate/do-work.io/original-solutions-site.Changed jobs:
Blacksmith runners (incl. blacksmith-*-ubuntu-2404), macOS and Windows jobs are unchanged.