Skip to content

♻️ Share one <Git.Push /> and <Issue> between the REPL and every other command - #951

Merged
taras merged 9 commits into
mainfrom
agent/repository-component-boundary-a
Oct 19, 2026
Merged

taras merged 9 commits into
mainfrom
agent/repository-component-boundary-a

Conversation

@taras

@taras taras commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Part of #181.

Why

A document writes the operation it wants:

<Repository name="project" url="https://github.com/octo/project">
  <Git.Add paths="notes.md" />
  <Git.Commit message="Prepare notes" as="commit" />
  <Git.Push />
</Repository>

<IssueTracker url="https://github.com/octo/project">
  <Issue title="Filed" as="filed">a described issue</Issue>
</IssueTracker>

Until now that fragment reached two different implementations. xmd run reached
the bundled component. A REPL entry reached a second authored body the retained
provider installed over it, with its own identity behind it — and that body, not the
bundled one, decided what publishing and filing meant. The REPL's needs had been
written into the component instead of underneath it:

We have special code for the repl in implementation of a component. That should
never happen.

What changes

Before: <Git.Push /> and <Issue> each existed twice. The retained entry's copy
owned the slot, the lock, the admission and the acknowledgement; the bundled copy owned
the ordinary path. A behavior fixed in one was absent from the other, and the only way
to learn which one a document had reached was to know which command ran it.

After: each operation has one authored body. What changes between an ordinary run
and a retained REPL entry is which policy performs the operation that body asks for,
never the component. Authored behavior, refusals, records and coroutine order are
unchanged in both; every existing history continues to replay, and no key, fingerprint
or journal was rewritten.

How it works

<Git.Push /> → one shared body → the operation it asks → ordinary Api | entry's envelope → outcome

The Git Plugin registers all twelve names for every command it declares for, repl
included. That registry is what says which names exist — to a run, to xmd syntax, to
<Plan> validation and to a REPL entry's preflight alike. An execution that owns a
retained boundary above one of these operations, authenticated per invocation, declares
that same name again from inside its own scope with its own policy under it, through the
ordinary trusted installation and the same component module, where a nearer declaration
shadows the registered default.

Four of the six external operations — <PullRequest> and its three evidence reads — ask
their feature Api directly, the way every other component in the repository does. A
workflow run does retain all four: the upsert through the Git-host reconciliation beneath
it, and each read as policy on PullRequestReadExecution. But that retention is installed
under the feature operation rather than owned above it, and no REPL entry owns one
either, so none of the four needs a binding of its own in this delivery. The two that a
REPL entry does retain take the operation as an argument: boundComponent authenticates the invocation core issued, once, in the engine
frame the component was entered in and before the body projects any content, and hands
that site to feature-owned policy. The site stays private to the policy: no operation
answers with it, no public request carries it and no Context holds it.

That argument is not decoration. An entry's durable boundary has to enclose the public
IssueOperations / Git chain — a public handler that answers a read is retained as the
entry's answer, and a completed replay enters no handler at all — and a body that reached
the Api itself could not be enclosed by anything above it. The same fact is why neither
retained policy can move to the Api seam: a document's own component calling
Git.operations.push(...) inside an entry must reach the ordinary missing-provider refusal
and retain nothing.

The two paths are not redundant either. A declaration is registered inside the execution's
own scope, so it cannot be shadowed by an enclosing host's registerComponents();
registration is what makes a bundled component a default a host may replace. That is why
git-push.test.ts and pull-request.test.ts still replace these components and still see
their own bodies run, unmodified.

Review guide

Start with: packages/git/src/composition/invocation-binding.ts — 49 lines, one
function and two types.

Then review:

  1. packages/git/src/composition/components/ — the shared bodies; GitPush.ts and
    Issue.ts carry a registration and a declaration constructor over one body,
    PullRequest.ts and PullRequestReads.ts carry a registration alone.
  2. packages/git/src/composition/installation.ts — the twelve registrations, in
    unchanged catalog order, over the feature Apis' own operations.
  3. packages/git/src/deno/retained-repository/ — what is left of the entry's old
    component bodies: replPushPolicy and replIssuePolicy, policy only, holding the
    slot, lock, admission and acknowledgement they always held.
  4. packages/git/src/issue/owned.ts — the durable envelope, the live transport call and
    the idempotency key both retaining profiles share.
  5. packages/cli/src/ and packages/git/src/plugin.ts — how a command's registry reaches
    its profile, session, Syntax and preflight.

Look carefully at: the ordering in replIssuePolicy. The envelope is outside the
public chain and the chain is composed per live attempt, which is the opposite of the
workflow profile's min-band installation. Both orderings are deliberate and both are
tested.

What must stay true

  • A REPL entry keeps its own identity, admission and acknowledgement. Enforced by the
    policy that replaced its component, not by the component; a regression that publishes
    without a slot or admits twice is caught by the retained Push and Issue suites.
  • Durable identity cannot be supplied from outside. The owner is a closure built for
    one entry and the site is the authenticated invocation; neither reaches a prop, a
    tracker, a Context, a middleware answer or a public request field. A dispatch made
    outside the authenticated invocation reaches the ordinary missing-provider refusal.
  • Histories written before this change still continue. Enforced by keeping every key,
    fingerprint, record shape and coroutine order; checked by continuing four journals
    captured from the unchanged merged implementation.

How to verify it

  • The composition and retained suites (deno task test packages/git packages/cli)
    prove the shared bodies behave identically under both policies, and fail if the retained
    entry stops holding its slot or starts admitting an operation twice.
  • The binding suite (packages/git/tests/composition-component-binding.test.ts) proves
    one registry carries all twelve names, that an owned declaration describes the same
    component as the registration it shadows, that building a declaration calls no factory,
    and that concurrent invocations keep their own authenticated sites.
  • The owned-issue suite (packages/git/tests/issue-owned.test.ts) proves both
    retaining profiles over one envelope, including a workflow fork inheriting an upsert's
    identity so it does not file a second issue.
  • The historical suite (packages/git/tests/retained-repository-history.test.ts) holds
    seven journals captured from the merged implementation before any production edit to
    their recorded bytes — fourteen hashes against a provenance receipt — and continues four
    of them on this code: a failed publication, a completed filing, a failed filing and an
    unacknowledged filing adopted without a second POST, two of them concurrently with
    independent document state. It fails if this change alters a record, a key or the order
    they are written in.

One command for all of it:

deno task test

Scope

This PR repairs the two operations that are already merged — Push and Issue — and the
installation and command wiring they need. <PullRequest> and its three evidence reads
share the one-body shape here but gain no entry-owned binding: REPL-owned pull-request work
is an open delivery, and it stays unavailable from a REPL entry exactly as it is today. What
a workflow run retains beneath their Api is untouched.
Converting its construction, and fixing the swallowed pre-attempt authentication refusal it
carries, belongs to that delivery and is deliberately not started here. No migration, alias
or journal rewrite is included, because nothing written by the old implementations needs
one.

New abstractions

  • invocation-binding.ts (boundComponent, and the two types it is written in) exists
    because <Git.Push /> and <Issue> both need the invocation authenticated in the
    engine's own frame before their body projects content, and stating that constraint twice
    is how one of the two loses it. Two production constructors and two retained policies
    consume it.
  • Each new abstraction has multiple concrete uses or a clear justification.
  • No speculative functionality is included.

Generated or mechanical changes

  • packages/git/tests/fixtures/retained-repository-history/** is captured output, not
    authored: fourteen files written by a harness run against the unchanged merged
    implementation, plus receipt.json recording the revision, tree, capture command and the
    harness's own SHA-256. They are bytes under test and must not be reformatted, which is
    why .oxfmtrc.json excludes them — oxfmt formats JSON.
  • scripts/runtime-test-exclusions.ts marks the historical suite Deno-only; it drives a
    real loopback Issue server and native entry policy.

Risks and limitations

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

taras added 9 commits October 19, 2026 08:24
`<Git.Push />`, `<PullRequest>`, its three evidence reads and `<Issue>` had two
implementations each: the bundled one every document command registered, and a
second authored body a REPL entry installed over it with its own identity
behind it. Typing the same element meant different code depending on which host
was running, which is the boundary violation this repairs.

Each of those six now has one implementation, in the provider-neutral half of
`@executablemd/git`. A body interprets its props and forms, expands its own
content, normalizes what the document wrote, asks a semantic feature
operation — `GitApi["push"]`, `IssueOperationsApi` or
`PullRequestOperationsApi` — and projects what came back. None of them receives
an authenticator, an owner, a site, native access, a policy object, a record
codec or any publication state, and none names a journal record.

Between the component and the host is one feature-owned binding. For a host
that retains work named after an invocation it authenticates the invocation
canonical core issued — once, in the engine frame the component was entered in,
before any content is projected — then builds that invocation's own operation
facade from the host's policy and runs the one body against it. Revocation is
armed before the facade can be used and runs on success, failure and
cancellation, so a facade kept past its invocation performs nothing, and one
authored element performs one external operation.

A host that retains nothing named after an invocation registers those six
ordinarily over the same bodies with no identity authenticated, because there
is nothing for one to name — so they stay ordinary defaults a nearer
registration shadows. A `repl` command registers the other six and receives
these as declarations carrying the entry's policy, so no executable default is
registered for a declaration to shadow. `deno/retained-repository/{push,issues}`
are policy now: `replPushPolicy` and `replIssuePolicy` replace
`replPushComponent` and `ownedIssueComponent`, and the retention, dispatch,
reconciliation, envelope and transport beneath them are unchanged.

Retained-entry `<PullRequest>` stays unavailable: its declaration uses the
common construction with the ordinary policy, which is its own
missing-provider refusal.

Nothing observable moves. The owner is still
`canonicalJson(["executablemd.repl.issue-owner",1,execution.id,entryKey])`, the
site is still the authenticated `expansion.id`, and the Push v1 request, its
digest domain, `git_host_effect`, `issue_effect`, the fingerprints, the
idempotency keys, the coroutine order and `COMPOSITION_ORIGIN`'s bytes are
untouched. There is no migration, alias or journal rewrite.

Seven histories the merged implementation wrote are the evidence for that.
`packages/git/tests/fixtures/retained-repository-history/` holds their exact
sources and journal bytes, captured from old main
`7ee526665dcadd9ec79dca9f8b6a4726903d9a4f` before production was edited, with a
receipt naming the revision, the command, the owner, the paths each record
addresses, where each history was cut and what service state the capture left
behind. Each is cut while its root is unfinished, so continuing one re-enters
the component rather than replaying a settled root, and the new suite continues
all seven through the shared components without regenerating a byte.
Three gaps in delivery A's historical evidence, found in review of
`6166fffc189585779c2536a49477de825e630d5e`.

**The journals were not the bytes the capture emitted.** `deno task fmt` runs
`oxfmt --write packages scripts`, and oxfmt formats JSON, so the pass that
followed the capture reserialized five of the seven committed journals. Their
parsed values never changed, but the bytes are the evidence: A3 preserves the
old representation, not an equal reading of it. Each journal is restored with
the capture harness's own serializer, which reproduces the SHA-256 its receipt
already recorded, and the fixtures directory is excluded from oxfmt so a later
format pass cannot rewrite them again. The provenance row now verifies all
fourteen file hashes against that receipt, so this drift fails here rather than
in a reviewer's audit.

**The continuation depended on the capture machine and wrote shared paths.** It
wrote each source back to a fixed capture path with no cleanup and ran the
suffix against the real host filesystem there. Now every invocation owns
everything physical it needs: the root source is supplied by value at the path
its own record holds, so nothing is written to disk; the document filesystem is
this invocation's own, keyed by the recorded logical paths, so the retained
middleware records what it always recorded and two continuations cannot see each
other's work; and the component search path is an owned empty directory rather
than the capture's, which is what made an `<Elicit>` import read a directory
only this machine has. A new row continues two histories at once and shows their
written paths are disjoint.

With every capture directory denied for the four issue and failure fixtures, and
the clone, bare origin, seed and entry document denied for the three publication
fixtures, all nine rows pass. What remains is one directory: the managed
placement's own durable location. Denying just that fails exactly the three rows
whose continuation performs new covered file work or a pending publication,
because production takes that placement's slot lock there and proves that
checkout's object database there, through `@effectionx/fs`, `node:fs` and the
advisory-lock file rather than through a contextual Api. That consumer is stated
in the suite's own prose and returned for architecture resolution rather than
worked around with a new production seam.

**H5 compared the inherited records with themselves.** The old source binds
`filed` and `found` and consumes neither, so the row read the retained events
out of the output stream and compared them with those same events. It now states
what the components must restore — the upsert's URL, and the complete answer the
public middleware composed for the read — as values of its own, parses the
restored records through the production parsers and asserts against those, so a
schema-valid value that is not this one fails. Both public Issue chains are
installed to fail if entered, and the row shows neither is.
The accepted A3 amendment narrows the historical continuation contract. H1, H2
and H3 — a completed publication, a pending one, and one the remote accepted
before the journal could record it — are no longer continued here. Continuing
any of them performs new covered file work or resumes a pending publication,
which takes the recorded placement's slot lock and proves that checkout's object
database at the absolute paths the journal holds. Both belong to the real native
host and stay there, so no invocation-owned substitute reaches them, and the
proposed native-host seam was withdrawn rather than built.

Their three cases and the helpers only they used are deleted rather than
skipped: a skipped test reads as a gate somebody means to reopen, and this is a
decision instead. Their fixtures, hashes, receipt and the capture harness are
untouched, so a later continuation has unchanged bytes to work from.

What remains is six steps. All seven captured histories are still held to the
fourteen source and journal hashes their receipt records, to their event counts,
to their unfinished roots and to their recorded owners. Four are continued: the
definitive publication failure restores provider-free; the completed Issue read
and upsert restore their exact composed answer and URL with neither public chain
entered; the unacknowledged upsert presents its original key and adopts the
issue already at the tracker without a second create; the definitive Issue
failure restores without a transport. Two continuations still run at once and
own separate state.

The suite now says what it does not prove. It does not show that the three old
publication histories continue through the extraction, and it names the
current-code replay and reconciliation evidence that remains required without
standing in for that.
A REPL entry no longer carries a component catalog of its own. The Git Plugin
registers all twelve names for every command it declares for, `repl` included,
and that registry is what says which names exist: an execution that retains one
of the external operations declares that same name again in its own scope with
its own policy under it, where a nearer declaration shadows the registered
default.

So the entry declares what it owns and nothing more — `<Git.Push />` and
`<Issue>` for the repository installation, `<Issue>` alone for the issue-only
one. `<PullRequest>` and its three evidence reads keep the registered defaults
and their own missing-provider refusals, until the delivery that retains them
owns their policy too.

Gone with it: `entryComponents` on the REPL profile and session, the preflight
parameter and component merge, the no-host fallback that turned that catalog
into an installation, `profileComponents`, `CommandPlugins.components`, the
`plugins.components` reads in Syntax and Plan validation, the Plugin's
`RETAINING_COMMANDS` vocabulary split and its root export, and the bulk
six-operation policy and declaration catalog the split needed. Syntax
inspection, Plan validation and REPL preflight read the installed registry they
already stood in.
The five modules the component boundary changed had grown a comment above
almost every declaration, a module opening that reproduced the specification
and an architecture paragraph at each constructor. Repeating the canonical
form-dispatch rule four times per file made the one constraint that matters
harder to find, not stronger.

What stays is what a routine-looking refactor would break: authenticating the
invocation in the engine's own frame before the body projects content, arming
revocation before the facade can be used, finishing child content before the
parent operation or retained envelope, and the pinned initial branch a base
falls back to. Each form-dispatch boundary explains itself once, where the
dispatch is.

Comments only, with one exception: `FacadeRefusal`'s two members no longer
carry a doc comment each, so the union fits on one line. Same type, same
members. Every `documented()` value, description, prop schema, return schema and
refusal sentence is untouched — those are program data that Syntax and the
documentation read, not commentary.
The binding had grown a facade framework around the one thing it is for. It
built a gate per invocation, tracked `open` and `used` on it, armed an `ensure`
to close it, and refused a late or second call with its own error type — and
every ordinary registration, which retains nothing and has no identity to
name, was wrapped in the same machinery.

None of that was guarding a real escape. An operation runs in the scope of the
invocation that asked for it, and Effection already ends it there; the
single-use rule was marked before the work ran, so it never said an external
effect had been acknowledged. What it did do was make the interesting line —
authenticate the invocation core issued, in the engine's own frame, before the
body projects content — one of thirty.

So the binding is now that line plus the handoff: authenticate, ask the
feature-owned policy for this invocation's operations, run the shared body.
Ordinary registrations call the public feature operations directly, through a
three-line adapter that supplies the body's second argument. Gone:
`InvocationGate`, `FacadeRefusal`, `BoundOperationError`, `performed()`, the
`open`/`used` state, `unboundComponent` and the four retired exports.

The two rows that manufactured a saved facade to watch it refuse are gone with
them — they established the guard's implementation, not a production escape.
The cancellation row keeps the part that is about the product: the halt stops
the suspended upsert, joins it, and nothing performs twice. Real retention,
delegation, reconciliation and native cancellation stay where they are proved,
in the owned-worker and native suites.

Owners, sites, record bytes, keys, fingerprints and coroutine positions are
unchanged, and so is every `documented()` value, schema and refusal sentence.
Four of the six external operations were being handed an operations object that
was only ever the feature Api's own. `ORDINARY` built forwarding arrows for it,
`registeredComponent` adapted the body to it, and `PullRequest` and its three
evidence reads took it as a parameter — all so that a host could substitute
policy underneath. No host does: A retains publication and filing, and nothing
else.

So those four now ask their Api the way every other component in the repository
does. `pullRequestRegistration` is a value rather than a constructor,
`pullRequestReadRegistration` takes the kind alone, their bodies are
module-private again, and `ORDINARY` and `registeredComponent` are gone —
`Git.operations.push` and `IssueOperations.operations` are passed where the
registration still needs one, because a contextual Api's operations resolve
their chain from the scope at call time, not from where the reference was taken.

`<Git.Push />` and `<Issue>` keep the argument, and the reason is the one thing
worth a comment: a REPL entry's durable boundary has to *enclose* the public
chain, and a body that reached the Api itself could not be enclosed by anything
above it. That is also why neither retained policy can move to the Api seam —
`retained-repository-push.test.ts` P18 proves a document's own component calling
`Git.operations.push(...)` inside an entry reaches the ordinary
missing-provider refusal and retains nothing, and `repl-issues.test.ts` proves a
public handler that answers a read is retained as the entry's answer while a
completed replay enters no handler at all. Installing either lifecycle as Api
middleware inverts both.

Retained Issue construction is consolidated into the envelope the two profiles
already shared. `issue/owned.ts` now owns the live transport call and the
idempotency-key derivation — identical in both profiles all along — so
`effect.ts` calls them directly beneath the public chain, the entry composes the
chain over them, and `transportRead`/`transportUpsert`, their duplicate parses
and the entry's own key derivation are deleted. What is left of
`replIssuePolicy` is the owner it closes over, the authenticated site it is
handed, and which side of the public chain its envelope sits on.

`replPushPolicy` keeps its ten lines for the same reason, and `publish()` beneath
it stays entry-specific: it resolves this entry's placement, slot and saved
request, none of which a workflow run has.
…oes (#181, A)

A workflow run does retain `<PullRequest>` and its three evidence reads — the
upsert through the Git-host reconciliation beneath it, each read as policy on
`PullRequestReadExecution`. Saying they "retain nothing" was wrong about the
profile that does. What is true of them is narrower: no host owns a retained
boundary *above* their feature Api, so none of the four needs a binding of its
own and each asks its Api directly.
The registry is sixteen names now, not twelve, and `<Git.Files>`,
`<Git.Changes>`, `<Git.Diff>` and `<Git.File>` join the half a selected checkout
answers for. Every count, every catalog sentence and the binding suite's A1 row
say sixteen.

`publish()` takes the shared `nativeGitTurn` that arrived with those reads, so
one entry still serializes its native work through one turn.

They also settle the question this delivery kept answering about `<PullRequest>`
from the other side: a REPL entry retains every page those four answer with, as
`GitQuery` middleware under the component, and declares none of their names.
Retaining an operation is not what makes a body take its operation as an
argument — owning a boundary that has to enclose the public chain is, and that
is still `<Git.Push />` and `<Issue>` alone.
@taras
taras force-pushed the agent/repository-component-boundary-a branch from ca5a107 to 218b5e1 Compare October 19, 2026 12:44

@github-actions github-actions 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.

Found 3 redundant comments. Inline suggestions to remove them below.

Comment thread .oxfmtrc.json
// The retained-repository history fixtures are journals an older revision
// emitted, held to the SHA-256 their own receipt records: reserializing one
// changes the bytes the evidence is, and the suite that continues them
// verifies those hashes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// verifies those hashes.

title: typeof props.title === "string" ? props.title : "",
// Verbatim. What a document wrote is the pull request's body, and
// trimming or reflowing it here would publish something nobody authored.
// Verbatim: trimming or reflowing it would publish something nobody wrote.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// Verbatim: trimming or reflowing it would publish something nobody wrote.

yield* local.operations.push({
// What a handler answers with is not read as evidence. A synthetic answer
// has answered the document; it is not a receipt, and this operation
// retains nothing for it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// retains nothing for it.

@github-actions

Copy link
Copy Markdown

PR #951: ♻️ Share one <Git.Push /> and <Issue> between the REPL and every other command

43 files, +4628 / -686

Scope

🔴 PR has 5314 lines changed. Split into focused PRs.

🟡 5314 lines changed. PRs under 400 receive more thorough review.

🟡 43 files changed. Are all changes related?

🟡 Changes span 7 directories.

🟡 PR mixes config and source changes.

Structural

Oxlint structural signals:

  • no-unused-vars ×3: packages/git/src/deno/retained-repository/issues.ts, packages/cli/src/plugin-host.ts, packages/cli/src/repl/session.ts
  • no-unnecessary-type-arguments ×2: packages/cli/src/repl/session.ts

Slop

  • .oxfmtrc.json:10 — // verifies those hashes.
  • packages/git/src/composition/components/PullRequest.ts:138 — // Verbatim: trimming or reflowing it would publish something nobody wrote.
  • packages/git/src/deno/retained-repository/push.ts:260 — // retains nothing for it.

Static Analysis

Oxlint: 36 diagnostics across 10 files (7 rules)
Density: 0.008 violations/added-line

no-shadow (23): packages/git/src/composition/components/PullRequestReads.ts, packages/git/src/composition/components/PullRequest.ts, packages/git/src/composition/components/GitPush.ts (+4)
no-floating-promises (4): packages/cli/src/repl/session.ts
no-unused-vars (3): packages/git/src/deno/retained-repository/issues.ts, packages/cli/src/plugin-host.ts, packages/cli/src/repl/session.ts
unbound-method (2): packages/cli/src/plugin-host.ts, packages/cli/src/repl/session.ts
no-unnecessary-type-arguments (2): packages/cli/src/repl/session.ts
no-useless-spread (1): packages/git/src/issue/owned.ts
consistent-function-scoping (1): packages/cli/src/repl/session.ts

Correctness

  1. Signal cluster in cli/src/repl/session.ts

    • Pattern: Multiple Oxlint violations (no-floating-promises, no-unused-vars, unbound-method, no-unnecessary-type-arguments)
    • Concern: Indicates potential unreviewed or low-quality code in a file critical to REPL session handling.
    • Question: Are these violations intentional, or do they signal unaddressed technical debt?
  2. Unused variables in git/src/deno/retained-repository/issues.ts

    • Pattern: no-unused-vars violation
    • Concern: Declared variables not referenced in the file.
    • Question: Are these remnants of previous implementations or placeholder code?
  3. Shadowed variables in git/src/composition/components/GitPush.ts

    • Pattern: no-shadow violation
    • Concern: Local variables may unintentionally override outer scope variables.
    • Question: Is the shadowing deliberate, or does it risk subtle bugs?
  4. Unused function in cli/src/plugin-host.ts

    • Pattern: no-unused-vars violation
    • Concern: Function not used in the diff.
    • Question: Was this function removed intentionally, or is it a leftover?
  5. Unbound method in cli/src/repl/session.ts

    • Pattern: unbound-method violation
    • Concern: Method may lose this context when passed as a callback.
    • Question: Is bind() applied appropriately elsewhere, or is this a bug?
  6. Redundant type arguments in cli/src/repl/session.ts

    • Pattern: no-unnecessary-type-arguments violation
    • Concern: Explicit type arguments may be inferred automatically.
    • Question: Are these type arguments simplifying or complicating the code?

No extraneous code patterns detected.

@taras
taras enabled auto-merge October 19, 2026 12:46
@taras
taras disabled auto-merge October 19, 2026 12:54
@taras
taras merged commit 27655fa into main Oct 19, 2026
44 checks passed
@taras
taras deleted the agent/repository-component-boundary-a branch October 19, 2026 12:55
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