Skip to content

Deepen Launch directory discovery into one captured inventory #2014

Closed

Description

@JacobStephens2

What to build

Deepen Launch directory discovery so one owning-machine operation obtains its Cron jobs, known repositories and Console start choices from one captured inventory. Today a start-options response reads the crontab three times: once directly, once through the repository form and once through Pass choices. A crontab edit between those reads can give the form and its choices different repositories. The local Cron jobs page also resolves its displayed entries against a newly read inventory when building “Run now”.

Put captured input, checkout resolution, per-entry association and configured-directory merging behind the Launch directory module's interface. Keep the existing steady-state results and scope rules. This follows #2008's shared Cron job interpretation work and fits one standalone Ticket.

Acceptance criteria

  • A start-options response, a local Cron jobs page and each Launch directory discovery operation read the account crontab at most once. All projections within that operation use the same captured configuration, Cron job interpretations and checkout facts. A later operation captures fresh facts.
  • The Launch directory module owns canonical-path resolution, GitHub-origin validation, association of each Cron job with its resolved Launch directory, canonical-path deduplication, configured-directory merging and their error rules. Console callers consume associated facts without reinterpreting shell text, canonicalizing paths or joining against another inventory.
  • Resolve each distinct literal directory path at most once per capture and read its origin at most once per resulting canonical directory, reusing failed observations as well as successful ones. Aliases and repeated Cron jobs share checkout facts; independent entries retain their original command, parsed candidate and output-log facts.
  • Known directories remain ordered by canonical path. The first Cron entry for a canonical directory supplies its output-log choice, including an absent choice; configured entries come after Cron entries and do not replace that choice. Preserve lexical output-log paths rather than rebasing them onto the canonical checkout. Repository selection at submission remains ASCII-case-insensitive and takes the first directory in canonical-path order.
  • Preserve the error matrix below. In particular, a bad configured directory does not hide the Cron inventory; the local page can render it with a start-choice error. A stale or non-GitHub Cron directory stays unresolved. Permission failures and malformed crontab output never become an empty inventory.
  • Cron jobs CLI/JSON, Launch directories CLI/JSON, owning-machine Console responses, Fleet inventory data and start-options keep their field shapes, ordering and independent recognition rules. “Shown”, Command kind, resolved Launch directory and offered start choice remain separate facts. Preserve stable repository grouping, Other-last ordering and duplicate Cron entries.
  • The existing supported-Pass selection and structured request validation still decide whether an associated command offers a start choice. Read-only Cron inventory does not acquire start data or configured-directory validation; run-only start-options does not expose the raw crontab or Pass last-fired times. Remote inventories are interpreted by their owning machines.
  • Starting a Command obtains a fresh inventory and validates its chosen Launch directory again. It does not reuse the observation that rendered the form. Existing origin checks, output-log selection, scope checks, CSRF checks and detached execution continue to apply.
  • Add regressions with a counted, changing fake crontab: one start-options response has matching repository choices and Pass requests from one read; the next response sees the edit; a local Cron jobs page derives displayed entries and “Run now” from one read. Cover alias/duplicate resolution, first-entry log precedence, strict versus missing-tool errors, invalid configured directories and fresh submission validation through the captured interface and existing command fixtures.
  • Retain the existing cross-projection behavior table, CLI/HTTP parity checks, inert shell-text checks and relevant Console browser regressions. Update the domain-to-code index to locate the captured inventory and its tests. Run the repository's required affected-test selection against main, including its selected Console checks.

Error matrix, with configuration syntax and home-path acquisition otherwise valid:

Observation Cron jobs CLI / JSON Launch directory listing and repository form Start-options Local Cron jobs page with run scope
Empty crontab, including the tool's recognized “no crontab” exit Empty jobs Configured directories remain available Configured repositories, no Cron Pass choices Empty inventory
Crontab executable absent Error Treat Cron input as empty Configured repositories, no Cron Pass choices Inventory error
Other crontab read failure or non-UTF-8 output Error Listing fails; form records error Error Inventory error
Cron checkout missing or not a GitHub checkout Entry remains unresolved Omit that directory Omit its Pass choice Entry remains visible without a start choice
Configured directory cannot resolve Cron inventory remains readable Listing fails; form records error Error Inventory renders; start choices report an error

Blocked by

None (can start immediately). No release, deployment, credentials or host step is needed.

Decisions

The design tree is settled in three rounds. Scope and ownership determine capture lifetime and dependencies; those determine projections, error handling and caller migration; the settled behavior determines verification and documentation. Every branch below is settled.

Round 1 — scope, ownership and dependencies

  1. One standalone Ticket. Capture, directory resolution and the four consuming paths form one behavior-preserving refactor that fits a fresh context window. The observable improvement is agreement within one response and less repeated acquisition; adding commands, supporting additional Cron syntax or changing start eligibility is outside this Ticket. No work needs an earlier release.
  2. Deepen the existing Launch directory module. It owns the captured per-entry association and known-directory projection. Cron jobs retains its text interpretation, crontab syntax and display projection; Console start choices retain supported-Command selection and structured request construction. This puts checkout knowledge in one place while preserving the depth already supplied by Cron job interpretation.
  3. Use the existing local command and filesystem seams. Production resolves real checkouts and invokes the existing crontab/Git adapters; tests use temporary Git checkouts and fixture executables at those same seams. These two adapters already justify the seam. Add no new public resolver trait, filesystem port or configurable acquisition policy: none is needed to exercise this behavior.
  4. Keep one request-owned observation, with fresh submission. Construct it once per owning-machine operation from the configuration already loaded for that operation and one captured crontab outcome. Convenience CLI entry points may load their configuration once before construction. The observation owns its inputs and memoizes requested projections internally; it exposes associated read-only facts, not indices or a caller-maintained path join. No global cache or cross-request lifetime is introduced, because edits must appear on the next operation and a form must confer no later permission to start work.

Round 2 — captured facts, errors and caller migration

  1. Retain one interpretation per included Cron entry. Carry its recognition, Command kind and optional literal Launch facts into the capture without reparsing in each consumer. Keep parsing in the existing interpretation module. Original schedule/command text and duplicate entries remain available independently of successful resolution or start validation, because a displayed Cron job need not be startable.
  2. Resolve paths inside the capture. Cache canonicalization by supplied literal path and origin lookup by canonical checkout path, including unavailable observations. Keep each entry associated with its own parsed command and literal output-log facts. Do not move repository identity checks into the text interpreter: they require local facts and must remain replaceable by the existing test adapter.
  3. Separate entry association from directory deduplication. Each Cron entry retains its resolved checkout association, while the known-directory projection folds entries in crontab order into a canonical-path-ordered collection. The first entry wins the directory's output-log choice even when it has no stdout redirect; configured entries follow without overwriting it. Preserve output paths as expanded from the literal directory before canonicalization, because rebasing them would change where started Commands append output.
  4. Preserve projection-specific errors. Retain the original crontab outcome so the Cron projection remains strict while Launch discovery and start-options treat only an underlying executable-not-found error as empty Cron input. Build and memoize configured-directory validation only when a directory/start projection asks for it, keeping a bad configured checkout from failing a read-only Cron projection. Validate every configured entry even when it aliases an already-known directory, reusing checkout observations rather than skipping validation. Preserve contextual error diagnostics and form/start-choice error presentation; configuration parse and home failures still propagate through their existing callers.
  5. Migrate combined consumers together. Start-options builds its repository form and Pass choices from the same observation. The local Cron jobs page builds its displayed inventory first and obtains its optional start projection from that same observation, retaining display when only configured-directory validation fails. Standalone directory listing, repository forms and command-directory selection use the same module through their convenience entry points. No consumer re-reads the crontab to repair an association.
  6. Keep transport projections narrow. Captured parsed commands, local paths and errors are internal facts, not additions to serialized Cron jobs or Fleet data. Preserve the existing run/read scope split and raw-text redaction. Remote Cron jobs and remote start-options remain separate owning-machine requests; this change promises consistency within one local operation, not an atomic snapshot across Fleet requests. Remote rows are never resolved against the reading machine's filesystem.
  7. Retain submission authority and ordering. Command submission takes a new observation, selects the first canonical-path-ordered matching repository with the existing ASCII-case-insensitive comparison, and runs all existing validation. A captured start choice describes what could be offered when read; it neither authorizes a later action nor keeps a stale checkout alive.

Round 3 — verification and documentation

  1. The interface is the test surface. Exercise related job/directory/start projections through the captured module with real temporary checkouts, and retain end-to-end CLI/HTTP checks through the current fixture adapters. Assert resulting associations, errors, ordering and external acquisition counts. Do not test private memo-table shapes or introduce a separate resolver-only test surface, because that would miss caller coordination.
  2. Prove one capture and fresh subsequent captures. A fixture crontab counts invocations and returns different repository entries on successive reads. Check consistent form/Pass results and local page/start results within an operation, then fresh results on the next operation. Count origin queries for repeated paths and aliases through the fixture Git adapter. Use event/file polling with generous bounds where a running Console is needed; no short wall-clock success requirement is necessary.
  3. Preserve tests with distinct leverage. Keep the existing Cron interpretation behavior table, CLI/HTTP parity, inert-shell, output-log, invalid-request and browser regressions. Move any assertions tied to removed association helpers to the captured interface rather than retaining parallel tests of the same implementation. Cover the error matrix and precedence cases explicitly, because source sharing alone would not protect those intentional differences.
  4. Update navigation, with no new domain term or ADR. The deepened module still implements the existing Launch directory and Cron job concepts. Record its ownership and testing seam in the domain-to-code index. No Glossary change or ADR is warranted: no concept changes meaning, and the internal capture choice is reversible without a data migration or product-policy change. Check the manual and hand-written site descriptions of discovery/starts while implementing and correct any affected statement in the same pull request.

Architecture review

Strength: Strong · Dependencies: local-substitutable

Files: src/launch_directories.rs, src/cronjobs.rs, src/cronjobs/command.rs, src/console/start_controls.rs, src/console/cronjobs.rs, src/console/commands.rs, tests/console/cronjobs.rs, tests/console/start.rs, docs/code-navigation.md

Before

flowchart LR
  C[Cron jobs] --> I[Cron job interpretation]
  L[Launch directory discovery] --> I
  O[Console start choices] --> I
  C -.repeated resolution.-> F[Checkout facts]
  L --> F
  O -.canonical path join.-> L
  O -.independent capture.-> R[Account crontab]
  L --> R
  C --> R
  classDef leak stroke:#dc2626,stroke-width:2px;
  class C,O leak
Loading

After

flowchart LR
  C[Cron jobs] --> L[Launch directory discovery]
  O[Console start choices] --> L
  L --> I[Cron job interpretation]
  L --> F[Checkout facts]
  L --> R[Account crontab]
  classDef deep stroke-width:3px;
  class L deep
Loading

Problem: The Launch directory module's interface is shallow for combined callers: acquisition, resolution and per-entry joins leak across the seam, so one response can combine three crontab observations.

Solution: Deepen the module with a captured inventory whose implementation owns acquisition, resolution, association and merging behind one interface, using the existing local adapters.

Wins

  • Locality: checkout rules stay together
  • Leverage: one capture, multiple projections
  • Depth: callers consume associated facts
  • Tests cross the shared seam

Deletion test: Deleting the deep module would redistribute capture, resolution, association, merging and error rules across the Cron jobs and Console callers.

Covered by: No open issue proposes this deepening; all 165 open issue titles and bodies were checked and the list was refreshed before publication.

Activity

  1. added
    needs-triageMaintainer needs to evaluate this issue
    ready-for-agentFully specified, ready for an AFK agent
    architect-planAn Architect plan: the Spec or Ticket an Architecture review published
    in-progressA Claim: thirdshift has taken this issue
    and removed
    needs-triageMaintainer needs to evaluate this issue
    ready-for-agentFully specified, ready for an AFK agent
    on Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    architect-planAn Architect plan: the Spec or Ticket an Architecture review published

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions