Conversation
chore: back-merge main into develop
std::env::consts::ARCH is a compile-time constant: it names the target the binary was built for, not the machine running it. An Intel build on Apple Silicon runs under Rosetta and reports x86_64 -- uname -m agrees, since the point of the translation is that the process cannot tell -- so the updater kept fetching Intel artifacts and could never move that user to the native build. An x64 build under the arm64 Windows emulation had the same problem. The architecture is now probed from the system: sysctl.proc_translated on macOS, PROCESSOR_ARCHITEW6432 on Windows. The decision is a pure function over the compiled target and that answer, so it is tested directly; only the probe touches the system. skillkeeper-core's key builder now takes os and arch as arguments instead of reading the constants itself. Deciding the real architecture requires asking the system, which that crate deliberately cannot do, so it is told the answer rather than guessing it.
Add `skillkeeper.requires` (strict) with a flat `requires` fallback (lenient), plus the reference validation and skill-path rendering they share with the group rules.
Transitive closure for install and update, reverse closure for what breaks, and the two repository faults: a reference with no skill behind it, and a cycle. Pure, deterministic, cycle-safe.
Persist the declarations in `.skid.yml` (schema 1 -> 2) and in the install ledger, so a skill whose source repository is gone still knows what it needed. `adopt_skill` carries them through reconcile.
Report a reference with no skill behind it, and a cycle, once the repository's skill list is complete. Neither is fatal: hiding the skills involved would cost more than the authoring mistake does.
Ten stable diagnostic codes over one repository: the dependency faults, the conditions that were silent before (a declared hook with no HOOK.md, an executables entry matching no file), and the resolver's own warnings reclassified with a severity.
Expose the lint pass as `skillkeeper repo lint`, with three mutually exclusive targets, JSON output derived from the diagnostic type rather than hand-built, and exit codes a CI gate can rely on: a named target that cannot be linted fails instead of reporting success.
Install and update expand to the transitive closure within the skill's own repository; uninstall never cascades but reports the dependents it broke, judged at each dependent's own target.
Send the declarations to the renderer and expand the install list to its closure at apply time, so the core stays authoritative even if a preview missed something. Grouped per repository, so a reference can never resolve against a namesake elsewhere.
A second implementation so the tree can be drawn without a bridge round trip per click. Ordering, reverse-closure sorting and missing-target handling all match the core, which is the condition the duplication was accepted on.
Store only what the user picked and derive the rest, so no state records why a box is on and no click sequence can desynchronize it. The installed baseline stays out of the seeds, which is what lets a broken dependency be visible instead of silently repaired.
A teal plus for a skill installed because something else needs it, and an orange exclamation for one whose dependency is gone, plus a checkbox tone to match. The interactive badge stops its own click and its own Enter/Space, so the row behind it neither toggles nor expands.
Both tooltips in every catalog, each matching its own `skills.status.*` siblings rather than translating the English in isolation.
Checking a skill selects its dependencies transitively and marks them as such; an installed skill whose dependency is gone gets the orange marker and repairs on click. The install modal derives the closure itself, since the page hands it hand picks only.
Prop-level coverage in the shared kit, and an interactive story built on the real reducer rather than a reimplementation of it.
Reference syntax and the strictness asymmetry, what install, update and uninstall do, the diagnostic table and exit codes, the badge and token meanings, and the derived selection model.
Picks up the dependency fixtures: a chain, a cycle, both declaration forms, a duplicate, a missing target, a malformed strict block, a cross-group reference, a declared hook with no HOOK.md, and an executables entry matching no file.
Drives the real binary against the fixture: every diagnostic code, JSON output, both target-misuse exits, closure install, the dependents warning on uninstall, cycle-install termination and cross-group guidance. Also bounds the CLI call, since a spinning binary would have stalled the whole suite silently rather than failing.
CI treats clippy warnings as errors, which a bare `cargo clippy` run does not surface.
Scope the installed baseline to the shown scopes, so an untracked project's installs cannot become an unclearable pending removal; report a grouped self reference, which the parser cannot see; judge repair per agent; reject a lint path that is not a directory.
Mark the dependents a queued removal will break, rather than only after it is applied, and stop tinting a retained install as a new dependency.
Every user-visible change of the feature gets a bullet under Development. The feature's own `fix` commits are not listed: they corrected unreleased code, so nothing a user could have seen was broken.
A candidate should not linger in the changelog as its own entry. The 0.1.1 candidates fold into 0.1.1; 0.1.2-rc.1 folds into 0.2.0, the release that actually followed it -- 0.1.2 was never cut, so a plain delete would have dropped four entries that shipped.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release v0.6.0. Adds skill-to-skill dependencies end to end -- manifest field,
core graph, repository lint, CLI, and desktop UI -- plus the pre-existing
desktop architecture fix already on
develop.Skill dependencies
A skill can now declare what it needs:
skillkeeper.requiresis validated strictly: a malformed entry warns and skipsthe skill. A bare top-level
requires:is accepted as a lenient fallback andsilently ignored when malformed, so third-party repositories using that key for
their own purposes keep working.
skillkeeper.requireswins when both appear.Installing a skill pulls in its dependencies transitively. Dependencies are
recorded in
.skid.yml(schema 1 -> 2) and in the install manifest, so updatinga dependent skill updates everything it needs in the same run.
Repository lint
New command, ten stable diagnostic codes --
SK001-SK005errors,SK010-SK014warnings:Exit 0 clean, 1 warnings, 2 errors. Missing dependency targets and cycles are
lint errors, but they never block installation: the resolver warns and installs
what it can, so a broken upstream repository degrades instead of failing shut.
Desktop
Selection state is now derived rather than stored: hand-picked skills seed a
transitive closure, and everything the closure adds is shown as a dependency.
Three new badge states on the skills pages:
as such
!-- a dependency is gone or is about to be removed, and the skill maystop working; clicking it re-selects the whole closure to repair
Unchecking a dependency unchecks its dependents and their dependencies, but only
those that were not already installed before the change.
Verification
Full gate green on
2289858:cargo fmt,clippy -D warnings, 1284 Rusttests, eslint, tsc, 999 renderer tests, coverage thresholds, renderer build,
51/51 e2e. Pre-release gate green: licenses, docs, changelog, version
consistency, conventional commits. Fixture repository (
examples/test-repo)gained cases for every resolution path, including cycles and missing targets.
Notes for the reviewer
app::askpass::tests::an_oversized_request_gets_no_answer_instead_of_hangingflakes on roughly half of full
cargo testruns withENOTCONN. It ispre-existing, this branch never touches that file, and the fix is one variant
in the
matches!ataskpass.rs:908-- deliberately left for its own change.by Storybook, unit tests, and e2e only.
sr-cyrl,sr-latn, andthcatalog entries want a native speaker's review.