quickchr targets (#134): Tier-1 resolution refactor + provider core (Phases 1–2) - #181
Conversation
…oint (#134 Tier 1) Axis-B (connection-fact origin) generalization for the resolution-provider refactor (#174 Tier 1), ahead of the quickchr named-live-provider. No behavior change. - Rename the CDB-shaped selection surface to source-neutral names while it is tiny: expandCdbSelection->expandSelection, CdbSelectionMember->SelectionMember, CdbSelectionExpansion/...ResolveInput. Mechanical across the four fan-out callers (api/execute/retrieve/transfer), the resolver, and unit tests. - Add src/resolver/service-endpoint.ts: the neutral, first-class per-service endpoint map (ServiceEndpoint/SshServiceEndpoint/ServiceEndpointMap, keyed by --via). Mirrors quickchr's published descriptor contract but provider-neutral; CDB is the degenerate single-endpoint case, a live provider populates the map. Providers are never flattened to a single host/port -- the refactor #174 exists to prevent. - CONSTITUTION.md: normative "Resolution providers" subsection (Axis A/B, selector-source vs named-live-provider, per-service map first-class). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve `--quickchr <name>` into the neutral per-service connection facts, against the published @tikoci/quickchr 0.4.4 descriptor v1. No CLI wiring yet (that is Phase 3); this is the connection-fact origin only. - src/resolver/quickchr-provider.ts: resolveQuickchrTarget(name) dynamic-imports @tikoci/quickchr via a runtime specifier (keeps its raw .ts out of strict tsc, matching scripts/qa-active-channels.ts), reads QuickCHR.get(name).descriptor() through quickchr's public API only, and maps the descriptor's services onto the neutral ServiceEndpointMap. Unknown future service keys are ignored (additive forward-compat); auth values are treated as secret (never logged). - Typed quickchr/* errors, never a silent fallback: package-unavailable (optional dep missing), unsupported (old API / newer descriptorVersion), machine-not-found (get() -> null/undefined or MACHINE_NOT_FOUND), machine-stopped (MACHINE_STOPPED). Registered in the CentrsErrorCode union, the error catalog, docs/errors pages, and the drift-guard KNOWN_FAMILIES. - Move @tikoci/quickchr devDependency -> optionalDependency ^0.4.4 so `bunx @tikoci/centrs --quickchr` works when installed, with runtime capability checks rather than a hard import. - Unit tests mock the load seam: descriptor->map, unknown-key drop, and every typed-error path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThe PR adds quickchr as an optional named-live provider, defines provider-neutral per-service endpoints and typed errors, and renames CDB-specific selection expansion APIs to generalized selection APIs across fan-out orchestration and tests. ChangesQuickchr resolution provider
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant resolveQuickchrTarget
participant QuickCHR
participant Descriptor
participant ServiceEndpointMap
Caller->>resolveQuickchrTarget: resolveQuickchrTarget(name)
resolveQuickchrTarget->>QuickCHR: dynamically load and call QuickCHR.get()
QuickCHR->>Descriptor: resolve machine and request descriptor()
Descriptor-->>resolveQuickchrTarget: descriptor metadata and services
resolveQuickchrTarget->>ServiceEndpointMap: map supported service keys
ServiceEndpointMap-->>Caller: QuickchrResolution
Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR implements phases 1–2 of the --quickchr <name> targets work by refactoring the existing CDB-shaped selection types into source-neutral selection types, introducing a first-class per---via ServiceEndpointMap model, and adding the (not-yet-wired) quickchr provider resolution core plus its typed error surface.
Changes:
- Rename the selection expansion surface from
CdbSelection*/expandCdbSelectionto neutralSelection*/expandSelectionacross fan-out callers and unit tests. - Add
src/resolver/service-endpoint.ts(neutral per-service endpoint map + type guard) andsrc/resolver/quickchr-provider.ts(dynamic-import + descriptor→endpoint-map mapping + typedquickchr/*errors). - Register the new
quickchr/*error family in the catalog/docs and move@tikoci/quickchrto anoptionalDependencypinned to^0.4.4.
Reviewed changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/unit/transfer-fanout.test.ts | Update selection type names used by transfer fan-out unit tests. |
| test/unit/service-endpoint.test.ts | Add unit tests anchoring the new ServiceEndpointMap contract and availability guard behavior. |
| test/unit/selection.test.ts | Update selection expansion tests to use expandSelection and SelectionMember. |
| test/unit/retrieve-fanout.test.ts | Update retrieve fan-out tests to use SelectionExpansion. |
| test/unit/quickchr-provider.test.ts | Add unit tests for descriptor mapping and quickchr/* error mapping via a load seam. |
| test/unit/execute-fanout.test.ts | Update execute fan-out tests to use neutral selection types. |
| test/unit/error-catalog.test.ts | Register quickchr as a known error family in tests. |
| test/unit/api-fanout.test.ts | Update api fan-out tests to use neutral selection types. |
| src/transfer.ts | Rename comment reference from expandCdbSelection to expandSelection. |
| src/transfer-fanout.ts | Replace CDB-shaped selection types with neutral selection types in transfer fan-out plumbing. |
| src/retrieve-fanout.ts | Replace CDB-shaped selection types with neutral selection types in retrieve fan-out plumbing. |
| src/resolver/service-endpoint.ts | Introduce neutral per---via endpoint model (ServiceEndpointMap) and isEndpointAvailable guard. |
| src/resolver/selection.ts | Rename and document selection expansion surface (expandSelection, SelectionMember, etc.). |
| src/resolver/quickchr-provider.ts | Add quickchr provider core: dynamic import, descriptor mapping, typed quickchr/* errors. |
| src/resolver/index.ts | Re-export new quickchr/service-endpoint/selection symbols from resolver barrel. |
| src/resolver/facts.ts | Update resolver doc reference from expandCdbSelection to expandSelection. |
| src/index.ts | Update public exports to use expandSelection / Selection* instead of expandCdbSelection / CdbSelection*. |
| src/execute.ts | Rename comment reference from expandCdbSelection to expandSelection. |
| src/execute-fanout.ts | Replace CDB-shaped selection types with neutral selection types in execute fan-out plumbing. |
| src/errors.ts | Extend CentrsErrorCode union with quickchr/*. |
| src/core/error-catalog.ts | Add catalog entries for quickchr/package-unavailable, quickchr/unsupported, quickchr/machine-not-found, quickchr/machine-stopped. |
| src/api-fanout.ts | Replace CDB-shaped selection types with neutral selection types in api fan-out plumbing. |
| package.json | Move @tikoci/quickchr from devDependencies to optionalDependencies and bump to ^0.4.4. |
| docs/errors/README.md | Document the new quickchr/* error family. |
| docs/errors/quickchr/unsupported.md | Add quickchr/unsupported error page stub. |
| docs/errors/quickchr/package-unavailable.md | Add quickchr/package-unavailable error page stub. |
| docs/errors/quickchr/machine-stopped.md | Add quickchr/machine-stopped error page stub. |
| docs/errors/quickchr/machine-not-found.md | Add quickchr/machine-not-found error page stub. |
| docs/CONSTITUTION.md | Add the normative “Resolution providers” subsection (Axis A/B + provider taxonomy + per-service map). |
| bun.lock | Lockfile update to reflect @tikoci/quickchr@0.4.4 as optional dependency. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/resolver/quickchr-provider.ts`:
- Around line 113-116: Update mapServices to validate that services is present
before calling Object.entries. When it is missing, throw an actionable error
that identifies the malformed descriptor and provides guidance to supply the
required services mapping, allowing the existing error wrappers to handle it.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 392a7536-6bd2-49e3-88c6-09c045e7697f
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (29)
docs/CONSTITUTION.mddocs/errors/README.mddocs/errors/quickchr/machine-not-found.mddocs/errors/quickchr/machine-stopped.mddocs/errors/quickchr/package-unavailable.mddocs/errors/quickchr/unsupported.mdpackage.jsonsrc/api-fanout.tssrc/core/error-catalog.tssrc/errors.tssrc/execute-fanout.tssrc/execute.tssrc/index.tssrc/resolver/facts.tssrc/resolver/index.tssrc/resolver/quickchr-provider.tssrc/resolver/selection.tssrc/resolver/service-endpoint.tssrc/retrieve-fanout.tssrc/transfer-fanout.tssrc/transfer.tstest/unit/api-fanout.test.tstest/unit/error-catalog.test.tstest/unit/execute-fanout.test.tstest/unit/quickchr-provider.test.tstest/unit/retrieve-fanout.test.tstest/unit/selection.test.tstest/unit/service-endpoint.test.tstest/unit/transfer-fanout.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: CHR smoke (stable)
- GitHub Check: copilot-pull-request-reviewer
- GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/AGENTS.md)
src/**/*.{ts,tsx}: Use Bun-native TypeScript and Web APIs where possible
Errors must be actionable for humans and agents, with next-step guidance when a dependency, protocol, credential, or validation source is missing
Files:
src/resolver/facts.tssrc/errors.tssrc/transfer.tssrc/core/error-catalog.tssrc/resolver/index.tssrc/index.tssrc/api-fanout.tssrc/resolver/quickchr-provider.tssrc/resolver/selection.tssrc/retrieve-fanout.tssrc/execute.tssrc/resolver/service-endpoint.tssrc/execute-fanout.tssrc/transfer-fanout.ts
docs/CONSTITUTION.md
📄 CodeRabbit inference engine (AGENTS.md)
docs/CONSTITUTION.mdis the load-bearing source of truth for validation, envelope, errors, settings, identity, protocol selection, and done definition.
Files:
docs/CONSTITUTION.md
🪛 LanguageTool
docs/errors/quickchr/package-unavailable.md
[grammar] ~7-~7: Ensure spelling is correct
Context: ...ION.md`](../../CONSTITUTION.md) for the centrs error contract. This stub will be expan...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
docs/errors/quickchr/unsupported.md
[grammar] ~3-~3: Ensure spelling is correct
Context: ... speaks a newer descriptor version than centrs understands. ## Fix See [`docs/CONSTI...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~7-~7: Ensure spelling is correct
Context: ...ION.md`](../../CONSTITUTION.md) for the centrs error contract. This stub will be expan...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
docs/errors/quickchr/machine-stopped.md
[grammar] ~7-~7: Ensure spelling is correct
Context: ...ION.md`](../../CONSTITUTION.md) for the centrs error contract. This stub will be expan...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
docs/errors/quickchr/machine-not-found.md
[grammar] ~7-~7: Ensure spelling is correct
Context: ...ION.md`](../../CONSTITUTION.md) for the centrs error contract. This stub will be expan...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
docs/CONSTITUTION.md
[grammar] ~265-~265: Ensure spelling is correct
Context: ...ution has two independent axes, and centrs keeps them separate so the resolver is genera...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🔇 Additional comments (29)
src/resolver/selection.ts (1)
57-57: LGTM!Also applies to: 75-98, 125-130, 236-236, 267-267
src/resolver/facts.ts (1)
3-3: LGTM!src/index.ts (1)
341-341: LGTM!Also applies to: 369-371
test/unit/selection.test.ts (1)
14-16: LGTM!Also applies to: 77-89, 130-130, 211-211, 249-249, 267-272, 293-307, 308-314, 322-336
src/retrieve-fanout.ts (1)
15-15: LGTM!Also applies to: 52-57, 110-115, 138-138, 162-162, 197-197, 237-237, 376-376
test/unit/retrieve-fanout.test.ts (1)
5-8: LGTM!Also applies to: 32-32
src/api-fanout.ts (1)
10-10: LGTM!Also applies to: 56-61, 95-98, 123-123, 142-142, 166-166, 212-212, 246-246, 305-305, 332-332
src/execute-fanout.ts (1)
12-12: LGTM!Also applies to: 55-60, 94-97, 127-127, 142-142, 166-166, 198-198, 233-233, 295-295, 326-326
src/execute.ts (1)
290-290: LGTM!src/transfer-fanout.ts (1)
11-11: LGTM!Also applies to: 45-50, 104-110, 133-137, 168-172, 200-200, 220-220, 271-271, 311-323, 380-380, 410-410
src/transfer.ts (1)
822-822: LGTM!test/unit/api-fanout.test.ts (1)
18-23: LGTM!Also applies to: 66-68
test/unit/execute-fanout.test.ts (1)
16-21: LGTM!Also applies to: 21-33, 69-71
test/unit/transfer-fanout.test.ts (1)
7-11: LGTM!Also applies to: 25-25, 80-80
docs/CONSTITUTION.md (1)
263-296: LGTM!src/resolver/quickchr-provider.ts (1)
1-112: LGTM!Also applies to: 117-223
src/resolver/service-endpoint.ts (1)
1-140: LGTM!src/resolver/index.ts (1)
91-114: LGTM!package.json (1)
14-26: LGTM!docs/errors/README.md (1)
50-52: LGTM!docs/errors/quickchr/machine-not-found.md (1)
1-10: LGTM!test/unit/service-endpoint.test.ts (1)
1-98: LGTM!src/errors.ts (1)
16-16: LGTM!src/core/error-catalog.ts (1)
237-256: LGTM!docs/errors/quickchr/machine-stopped.md (1)
1-10: LGTM!docs/errors/quickchr/package-unavailable.md (1)
1-10: LGTM!docs/errors/quickchr/unsupported.md (1)
1-10: LGTM!test/unit/error-catalog.test.ts (1)
25-25: LGTM!test/unit/quickchr-provider.test.ts (1)
1-164: LGTM!
mobileskyfi
left a comment
There was a problem hiding this comment.
Findings from a separate pass, focused on the provider seam and docs alignment. I would treat the first item as blocking before merge.
-
src/resolver/quickchr-provider.ts:201only rejects descriptor versions greater thanSUPPORTED_DESCRIPTOR_VERSION, so an old-shaped descriptor with nodescriptorVersionis accepted (undefined > 1is false) and thensrc/resolver/quickchr-provider.ts:216callsmapServices(descriptor.services). If that old descriptor also lacksservices(the exact pre-v1 compatibility case this PR says it handles), centrs throws a rawTypeError: Object.entries requires that input parameter not be null or undefinedinstead of the promised typedquickchr/unsupportederror. I reproduced this locally with an injected loader returning{ name, version, arch }. The fix should validate the descriptor shape before mapping:descriptorVersionmust be a supported number/version,servicesmust be an object, and missing/old/malformed v1 fields should become an actionableCentrsError(quickchr/unsupported) with a unit test. I would not silently convert missingservicesto an empty map; the quickchr contract makesservicesrequired, so empty would hide a provider contract violation and defer the failure to a later--vialookup. -
src/resolver/service-endpoint.ts:128makes every key inServiceEndpointMapanAnyServiceEndpoint, soservices.sshloses the SSH-specific guarantee that an available SSH endpoint hasauth: SshEndpointAuthwithbatchModes. That weakens the exact Phase 4 contract that will gate--via ssh/transfer --via sftp. I would shape the map by service key ("rest-api"?: ServiceEndpoint,"native-api"?: ServiceEndpoint,ssh?: SshServiceEndpoint, with unsupported/future protocol keys absent or intentionally broad if needed) and makeisEndpointAvailablepreserve the input union viaExtract<T, { available: true }>. -
The new
docs/errors/quickchr/*.mdpages are still generated stubs (This stub will be expanded...). The path-scoped actionable-error instruction says new error pages should be enriched with the typical trigger and remediation afterbun run docs:errors. Sincedocs/errors/README.mdnow advertises thequickchr/*family, these pages should carry the actual user/agent guidance in this PR: missing optional package install/workaround, unsupported old/malformed/newer descriptor, machine name not found, and stopped machine/start command.
Non-findings: the no-alias decision for the expandCdbSelection rename is fine given the repo's current consumer posture; I do not see a docs/MATRIX.md or per-command README change required yet because this PR deliberately stops before wiring a user-visible --quickchr flag.
Verification I ran: bun run lint, bun test, bun run build, plus the old-shaped descriptor repro described above. GitHub checks are also green at PR head 3e458884b3c4e7fb6ef1d50d40d46fba80157ad2.
…, load-error split (#134 review) Address PR #181 review findings (Copilot, CodeRabbit, Codex): - Descriptor shape validation before mapping (Codex #1 / CodeRabbit): an old/pre-v1 descriptor with no `descriptorVersion` and no `services` now raises a typed `quickchr/unsupported` instead of a raw `TypeError: Object.entries(undefined)`. Missing `services` is rejected, not silently mapped to `{}`, so a provider contract violation surfaces at resolve time rather than a later `--via` lookup. Descriptor now crosses the optional-dependency boundary as `unknown` until `validateDescriptor()`. - Per-key `ServiceEndpointMap` + generic `isEndpointAvailable` (Codex #2 / Copilot #1): `map.ssh` keeps its `SshServiceEndpoint` type, so narrowing preserves the `auth: SshEndpointAuth`/`batchModes` guarantee Phase 4 gates `--via ssh`/`transfer --via sftp` on — no cast/`"batchModes" in` probe. - Load-error split (Copilot #2): only a genuine module-not-found maps to `quickchr/package-unavailable`; an installed package that throws on load is a real fault → `quickchr/unsupported` preserving the cause. - Enrich the four `docs/errors/quickchr/*.md` pages with typical trigger and remediation (Codex #3 / actionable-errors instruction). No-alias decisions for the `expandCdbSelection`/`CdbSelection*` rename (Copilot #3/#4) declined by the maintainer — nothing depends on centrs as a library. New unit tests cover every added error path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks all — three reviews (Copilot, CodeRabbit, and a Codex pass) triaged. Fixes pushed in Fixed
Declined (maintainer call)
Notes
Scope is unchanged — this still lands Phases 1–2 only and does not close #134; Phase 3+ tracked there. |
mobileskyfi
left a comment
There was a problem hiding this comment.
Re-review after 2298e5f: the original three Codex findings look addressed. Descriptor shape validation now fails closed with quickchr/unsupported, the ssh service keeps its SSH-specific endpoint type after narrowing, and the quickchr error pages are no longer stubs.
One new follow-up from the load-error split:
src/resolver/quickchr-provider.ts:128-134still treats anyERR_MODULE_NOT_FOUND/MODULE_NOT_FOUND(or any "cannot find module/package" message) asquickchr/package-unavailable. That can misclassify an installed@tikoci/quickchrpackage whose own module evaluation fails because a transitive import is missing. I reproduced this through the existing load seam by throwingObject.assign(new Error("Cannot find package 'left-pad' imported from /node_modules/@tikoci/quickchr/src/index.ts"), { code: "ERR_MODULE_NOT_FOUND" });resolveQuickchrTarget()reportsquickchr/package-unavailablewith the summary saying@tikoci/quickchris not installed. That contradicts the new docs' "only when the module is genuinely not found" distinction and sends the user to reinstall/add the wrong package. The classifier should check that the missing specifier is actually@tikoci/quickchr(or otherwise only map the top-level import target to package-unavailable); transitive/module-evaluation not-found errors should remainquickchr/unsupportedwith the original cause.
Verification I ran on head 2298e5feaa9e37fb6e3ec57b6c42cfcd76462873: bun run lint, targeted quickchr/service-endpoint tests, bun run build, bun test (1175 pass / 34 skip), and bun run lint:ci. GitHub checks are also green.
…ode alone (#134 review) Follow-up Codex finding on the load-error split: `isModuleNotFound` mapped any ERR_MODULE_NOT_FOUND / "cannot find module|package" to `quickchr/package-unavailable`. An installed `@tikoci/quickchr` whose own transitive import is missing carries the same code but names a different specifier — mislabeling it "not installed" sends the user to reinstall the wrong package. Now parse the quoted specifier the loader could not resolve and only treat a failure to find `@tikoci/quickchr` *itself* as package-unavailable; a transitive/module-evaluation not-found stays `quickchr/unsupported` with the cause preserved. Tests cover both the transitive repro and the genuine package-missing case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Re-review follow-up (Codex, 22:24) addressed in Module-not-found misclassification — All five inline review threads (Copilot ×4, CodeRabbit ×1) are resolved. Verification on |
What this is
The first two phases of #134 (
--quickchr <name>targets), landed as the Tier 1 resolution-provider refactor from #174. This is an incremental PR — it does not close #134. It deliberately stops before any user-visible--quickchrCLI surface so the load-bearing architecture can be reviewed on its own.Full phase breakdown and remaining work: #134 (updated).
Phase 1 — neutralize selection types + scaffold
ServiceEndpoint(eaf6e78)Axis-B (connection-fact origin) generalization. No behavior change.
expandCdbSelection→expandSelection,CdbSelectionMember→SelectionMember,CdbSelectionExpansion/…ResolveInput. Mechanical across the four fan-out callers (api/execute/retrieve/transfer), the resolver, and unit tests.src/resolver/service-endpoint.ts: the neutral, first-class per-service endpoint map (ServiceEndpoint/SshServiceEndpoint/ServiceEndpointMap, keyed by--via). Mirrors quickchr's published descriptor contract but provider-neutral. CDB stays the degenerate single-endpoint case; a live provider populates the map — nothing is flattened to a single host/port, the refactor Resolution providers: phased plan for quickchr (now) → TikTOML (next) #174 exists to prevent.docs/CONSTITUTION.md: normative Resolution providers subsection (Axis A/B, selector-source vs named-live-provider, per-service map first-class).Phase 2 — quickchr provider resolution core (
3e45888)Resolve
--quickchr <name>into the neutral connection facts, against the published@tikoci/quickchr0.4.4 descriptor v1. Not wired to any command yet (that is Phase 3) — this is the connection-fact origin only, soresolveQuickchrTargetcurrently has no production caller by design.src/resolver/quickchr-provider.ts:resolveQuickchrTarget(name)dynamic-imports quickchr via a runtime specifier (keeps its raw.tsout of stricttsc, matchingscripts/qa-active-channels.ts), readsQuickCHR.get(name).descriptor()through quickchr's public API only (nevermachine.json/quickchr.env/creds), and maps the descriptor's services ontoServiceEndpointMap. Unknown future service keys are ignored (additive forward-compat); auth values are treated as secret.quickchr/*errors, never a silent fallback:package-unavailable,unsupported,machine-not-found,machine-stopped. Registered in theCentrsErrorCodeunion, the error catalog,docs/errors/pages, and the drift-guard families.@tikoci/quickchrdevDependency→optionalDependency^0.4.4sobunx @tikoci/centrs --quickchrworks when installed, with runtime capability checks rather than a hard import.Decisions locked (for the remaining phases)
--quickchris exclusive in v1: a command targets quickchr machines or CDB/literals, not both (mixing with--group/--where/positionals is a usage error). Mixing can be added later additively.kind:"quickchr"member short-circuits the CDB/--host/resolveTarget/resolveAuthblock and substitutes the endpoint's host/port/tls→targetand auth (incl.privateKeyPath→sshKey), while keepingvalidate/timeout/formaton the normal path. A chosen--viawith no available service → typedquickchr/unsupported-via.Not in this PR (tracked on #134)
--quickchr <name>CLI flag +kind:"quickchr"selection member + exclusivity +__default__-ladder bypass + override-conflict, acrossretrieve/execute/api/transfer.--viaservice-map consumption;transfer --via sftpbatchModesgate.examples.mdacceptance (the "done" bar).Verification
bun run lint(biome + tsc),bun test(1171 pass / 0 fail), andbun run buildall green. cspell/markdownlint clean.🤖 Generated with Claude Code
Summary by CodeRabbit