| name | debundle_lane_worker |
| description | Apply one scoped debundle module-assignment or reorganization task in a worktree. Use for confirming atomic-DAG unit coverage, reading binding context, choosing honest module boundaries, editing debundle YAML (directly or via `debundle bindings assign` / `bindings rename` / `modules merge`), running the adapter-provided gate and regen commands, and committing one reviewable worker branch. |
Debundle Lane Worker
Use this role for one scoped implementation assignment: a seed cluster from
intake, a binding-patch/residual cohort, or a firm reorganization task from
the architect.
Shared CLI workflows land here for binding moves, renames, module merges, and
atom-split recovery:
@references/cli_basics.md
@references/selectors.md
@references/spec_editing.md
Read other bundled references as needed:
references/workflow.md for role boundaries and failure routing
references/cli.md for the full debundle command surface
references/README.md for the crate pitch + Comments
references/module_shape.md for seam and layer-ownership heuristics
Inputs
The orchestrator or project adapter provides:
- worktree root and expected base SHA
- assignment with owner IDs, binding IDs, proposed destination, and notes
<graph>, <modules-dir>, <emitted-js-root>, and optional source root
- project conventions/taxonomy docs
- exact gate, regen, uniqueness-check, and commit expectations
Procedure
-
Confirm the worktree is at the expected base before editing.
-
Check the assignment against the current graph with debundle describe
and debundle show-source; if needed, scan with debundle atoms,
coverage, or cluster <sym> (see references/cli.md).
-
Read each binding's surrounding code: consumers, dependencies, and nearby
implementation details.
-
Choose a module boundary that looks like a real JavaScript seam under the
project conventions.
-
Apply the assignment using the shared guide's CLI workflows. Prefer
bindings assign, bindings rename, and modules merge over
hand-editing module YAML. Proposals with landable_today: true can
be batch-assigned directly via bindings assign --batch;
blocked_residual_dependency proposals cannot — grow the closure so
the referenced residual cells land in the same batch, or co-locate
the owners manually, before assigning.
For selector-stabilization assignments, do not start by hand-authoring YAML.
First run debundle spec selector-debt --group-module-depth N --format json
to confirm the assigned bucket, then run
debundle spec synthesize-selectors in dry-run JSON mode scoped with
--item, --module, --module-prefix, or --file. Apply with --apply
only when the candidate count, skipped reasons, file scope, and selector
shape look reviewable. A synthesized selector that copies an exact long
function body, object literal, argument list, class body, or nested
expression is not done merely because it resolves against the current chunk.
It must also avoid overpinning incidental implementation detail. Minimize it
with holes/stable anchors first, or route the shape to Ducktape
minimization/tooling before scaling the pattern. After applying, run
git diff --check, the adapter's gate/regen command, and another
selector-debt summary to report the debt delta.
When hand-editing selectors is still necessary, follow
references/selectors.md: avoid
name-only selectors for autogenerated/minified bindings, prefer structural
source_matches[] claims with anonymous ANYTHING holes for
throwaway expression, statement, pattern, object-property-list,
declarator-list, and class-rest positions. In object literal or
destructuring-heavy selectors, pin only enough stable anchors to identify the
target uniquely, and no more; put ANYTHING or OBJECT_PROPS_* between them
instead of spelling unrelated generated structure. Use typed holes or readability labels
(EXPR, STMT, ARGS, STMT_LIST, OBJECT_PROPS, CLASS_REST, or
DECLARATORS) when the role, list behavior, or label makes
diagnostics/readability better. For one selected declarator inside a wider
comma-list declaration, write a single-declarator source_matches[] entry
with an explicit claim and optional adjacent top-level context
instead of spelling unrelated sibling declarators. Keep ambiguous structural matches rejecting
rather than source-order selected. Do not turn an oververbose generated
selector into a manual maintenance burden by preserving exact incidental
bodies or generated object values; either minimize it or leave the binding as
explicit selector debt with a generic tooling blocker. Do not modify the
upstream/source bundle.
After touching selectors, sanity-check the debt you added with
; if
your new members show up as high-score name-only selectors, reach for a
structural AST-shaped entry instead. If a binding cannot
yet be stabilized because Ducktape lacks a concise matcher, leave
(inert YAML-only, never emitted to JS —
unlike , which emits and churns the byte-identical snapshot) naming
the concrete blocker and desired feature, and route that blocker back to
Ducktape tooling. Do not leave blocker notes for one-declarator-in-comma-list
selectors or object literal property gaps; use the supported ,
, and patterns above.
-
Remove now-owned entries from the non-emitting rename/annotation patch
stream when the project uses one.
-
Run the adapter-provided uniqueness check, gate, and regen commands.
-
Commit one reviewable branch and report the result.
Boundary Heuristics
A good module has a coherent reason to exist: stable public surface, internal
references dominating external references, clear layer ownership, or multiple
meaningful consumers. Member count alone is not the rule.
Tiny modules are a smell — try to fold them. The chunker over-splits when it
emits a separate module for what a developer would have written inline in a
larger file. Judge by LINES OF CODE, not member count: a one-binding module that
is a 500-line React component is idiomatic and must be left alone; the smell is
small-LOC standalone files (a 1-3 line accessor, predicate, constant, or
wrapper). Fold a small-LOC module into its single real consumer (excluding
non-semantic re-export catalogs / bundle barrels), or into a sibling that was
clearly the same original source file (use source_location adjacency / shared
CSS-module class prefixes as evidence). Do NOT fold widely-consumed shared
primitives (a shared constant, a React context, a public predicate), real
public-API/service/class boundaries, or anything whose fold would cross a layer
boundary or break the gate. See references/module_shape.md.
Usually avoid standalone modules for:
- primitive constants with one consumer
- one-line helpers with one consumer
- enum-like values that only parametrize a larger owner
- local style/config/data artifacts with no public contract
Do not co-locate solely by consumer count when that would violate layer
ownership. Policy, domain, persistence, infra, and integration logic keep
their own homes even when a presenter is currently the only caller.
You may expand the batch when the assigned peel would split an atomic unit or
create a worse module shape. You may also skip assigned items when their
natural owner still belongs to a larger atomic unit that should move together.
Failure Handling
- If the graph is stale, rerun the adapter-provided graph refresh or report
the stale evidence.
- If
bindings assign refuses with an atom-split diagnostic, follow the
shared guide's atom-split workflow before changing the assignment shape.
- If the gate rejects via
debundle run, read the structured cycle/report
output (cycles.json, atomic_unit_conflicts.json) first. Use the
cut/evidence if present.
- If broad minified-source analysis is needed, stop and ask for intake
grounding.
- If the destination is architecturally unclear, stop and route to the
architect instead of inventing a dump bucket.
Report
Keep the report short:
- branch and commit hash
- gate and regen result
- destinations changed and bindings moved
- skipped proposals or units and why
- architecture or intake follow-ups discovered