Skip to content

Sync 3 Inkeep OSS Changes - #1195

Merged
inkeep-oss-sync[bot] merged 3 commits into
mainfrom
copybara/sync
Aug 13, 2026
Merged

Sync 3 Inkeep OSS Changes#1195
inkeep-oss-sync[bot] merged 3 commits into
mainfrom
copybara/sync

Conversation

@inkeep-oss-sync

Copy link
Copy Markdown
Contributor

Copybara-translated 3 Inkeep OSS changes. Rebase-merge this PR so the prepared commits land directly on public main.

Commits:

  • fix(ok): keep OK's own skills out of the fullscreen graph (PRD-7959) (#3440)
  • Avoid architecture guesses in download CTAs (#3459)
  • fix(ok): stop creating agent host folders without consent (PRD-7984) (#3443)

tim-inkeep and others added 3 commits August 13, 2026 18:48
…(#3440)

* fix(ok): keep OK's own skills out of the fullscreen graph (PRD-7959)

The link index treats skill bundles as graph nodes deliberately, but a global
skill can never link to a document: the index registers it node-only and
resolves its refs same-scope. OK force-installs two of its own bundles into
every project, so every graph carried four nodes that were structurally
incapable of participating in it.

Those bundles are now excluded from the fullscreen graph unless another skill
links them directly by name. A toggle beside the external-URL control governs
the user's own skills, project and global, and shows them by default. The
docked local graph is untouched, so a skill's own neighborhood stays
inspectable there.

Which bundles are OK's own is decided server-side and travels on the payload as
a managed flag. The reserved names live in the server package, which core and
the app cannot import, and the release version-sync imports that module through
a bare tsx eval that cannot resolve workspace packages, so the list cannot move.
Flagging server-side leaves exactly one copy of it.

Also extracts the graph's yes/no preference helpers into lib/bool-pref.ts with
tests, including the backward-compatibility case the external-URL toggle relies
on. Storage now holds only the deviation from a preference's default, so a
default-on preference survives a storage clear.

* fix(ok): enforce graph skill reference invariant (PRD-7959)

* docs(ok): qualify the built-in graph exception as same-scope (PRD-7959)

R3b and D-K said a built-in surfaces when another skill links it directly by
name, without noting that ref resolution never crosses the scope boundary. A
live probe against a running server confirmed the narrower behavior: a
project-scope skill referencing /open-knowledge-write-skill draws no edge at
all, so it cannot surface a user-global built-in. Only another global skill can.

Behavior is unchanged; the spec described the exception as broader than it is.

* docs(ok): scope bool-pref to its encoding and name the migration barrier (PRD-7959)

Review flagged bool-pref.ts as a parallel to follow-file.ts with a different
boolean encoding. The concern is real but the framing was narrower than the
facts: the split is pre-existing and codebase-wide, not two files. Roughly a
dozen prefs already encode 'true'/'false' and about five encode '1'/'0'.
bool-pref.ts joined the majority encoding; it did not create the divide.

Documents what this helper owns, why adopting it for a '1'/'0' pref would
misread stored values, and that migrating one needs a per-key
read-both-write-new shim rather than a call-site swap. Steers new prefs here so
the codebase does not gain a third encoding.

* fix(ok): record skill refs on the cold rebuild (PRD-7959)

A project skill's `/skill-name` references drew no graph edges. Two defects
compounded.

The cold rebuild builds its state inline and never called recordSkillRefs, so
refs were recorded only by the live-edit path. And skillRefs was added to the
persisted cache as an optional field without bumping SNAPSHOT_VERSION, so v1
caches stayed loadable and deserialized it to empty. With mtimes matching disk
the reconcile re-parses nothing, leaving refs permanently absent for every
untouched file.

Global bundles hid it: ingestGlobalSkillBundles re-reads them on every boot, so
their refs looked healthy while project skills had none. One real project shows
7540 indexed docs with 7 skillRefs entries, all global — 156 project skills, zero.

Extracts recordSkillRefsInto so the rebuild and the live path share one
implementation rather than a second copy of the rule, and bumps the version so
existing caches rebuild once. Either fix alone is inert: the rebuild has to
record refs, and stale caches have to be discarded for it to run.

* fix(ok): index one canonical copy of a skill, not one per editor root (PRD-7959)

A skill projected into several editor host dirs reached the content index once
per projection, so the graph drew a separate node for each copy of the same
skill.

The content filter carried its own hardcoded list of editor dotdirs to skip,
and that list had drifted from the registry: every host was listed except
`.github`. Copilot's projection was therefore not recognized as an editor
artifact at all and was swept in as ordinary content, bypassing the canonical
election that admits exactly one bundle per skill.

Derives the skill roots from knownSkillRootsFor — the same registry the scanner
uses — so newly supported hosts and user-configured custom roots are covered
without a second list to maintain. A file under a known root is excluded unless
the election admitted it.

Scoped to the root path (`.github/skills`), never the host dotdir (`.github`):
the skip set is segment-matched, so listing the dotdir would also bury real
content beside the projection — one project has nine such docs, including
`.github/CI_RUNBOOK`.

Admission itself is unchanged. Election is per skill, so one skill can be
canonical in `.github` while the next is canonical in `.claude`; a skill that
exists only under one root is still admitted there.

GitOrigin-RevId: ce6e6ba5e50b5cb62a87ed719b18bc880fe2e5b3
* fix(site): avoid architecture guesses in download CTAs

* fix(site): preserve download picker context

* fix(site): keep share attribution through picker

* Use architecture hints for download defaults

* Give Playwright CI setup more headroom

GitOrigin-RevId: ea66345dad32c69785dacbad92f53f29916fa3cd
…(#3443)

* fix(ok): stop creating agent host folders without consent (PRD-7984)

OpenKnowledge created coding-agent config directories for tools the user
does not have, then read those directories back as evidence the tool was
installed. Project creation, launch-time skill reclaim, store migration,
import, pack seeding and repair all fanned out across the full editor
registry with no detection gate.

The rule is now uniform: never create a harness home, only write into one
that already exists. `.agents` is treated as an ordinary host under the
same rule rather than an always-written central store.

- New projects start with no agent integrations selected
- Omitted CLI skill options install nothing
- Global writes target explicitly selected or already-existing hosts
- Migration, repair, import and pack seeding skip when no host exists
- USER_SKILL_HOSTS addresses Pi and Copilot at their real global roots

* fix(ok): address review on agent-host consent fixes (PRD-7984)

Follow-up to the consent fix, from automated review plus CI.

- `.github` is not a harness home. The first-segment probe resolved any repo
  with a `.github/` directory to Copilot's `.github/skills`, reintroducing the
  unconsented write this change closes. Both `resolveDefaultSkillHomeRel` and
  `skill-migrate`'s target picker now route through `skillRootActivationPath`.
- The default global target set no longer emits an editor id outside the
  install-target vocabulary, so a projected copy is always visible in the
  picker and removable by a set-exact install.
- The repair gate is evaluated per bundle instead of over a pooled entries
  array, so a bundle that lands nowhere reports `failed` rather than
  `skip-current`. Applied to both the CLI sweep and the desktop reclaim, which
  are documented as applying the identical gate.
- Create-project seeds its editor selection from detection instead of an empty
  set. The checkboxes sit inside a collapsed Advanced section, so an empty
  default silently wired nothing at all, including for editors the user has.
  The default-vs-customized variant is now set-equality against that baseline.
- `resolveInitSkillEnablement` is back to `undefined | true` enabling every
  bundle. Enabling is not writing: `installUserSkill` still refuses every
  destination whose host root is absent.
- The integration harness seeds a `.claude/skills` host root alongside the
  `.ok/config.yml` seed it already writes, since skill create now refuses when
  no harness home exists.

* fix(ok): stop the boot watcher conjuring agent homes (PRD-7984)

The managed-artifact watcher `mkdir -p`s every root it is handed, and the
root list was the full vocabulary rather than the roots that exist. So every
server boot fabricated `~/.cursor/skills`, `~/.codex/skills`,
`~/.copilot/skills`, `~/.opencode/skills` and `~/.pi/agent/skills` on a
machine with none of those tools, and detection then read them back as
evidence the tools were installed. The call site already documented this gate
("never CONJURE a vendor tree"); no code implemented it.

`managedArtifactSkillsRoots` now filters to roots whose activation path
exists, at the single chokepoint both the watcher and `getGlobalSkillRoots`
read from. The predicate is `skillRootActivationPath`, not the install-target
set, because this is a watch list: it must still admit `.gemini/skills` and
ledger-recorded custom roots, and it handles Pi's nested `.pi/agent/skills`.

The gate exposed four integration fixtures that only ever resolved a global
skill home because boot had conjured one; they now adopt a host explicitly.

Also from review:

- `applySeed`'s post-install reconciliation turned the deliberate no-host
  refusal into one user-facing error per pack skill, so `ok seed` in a project
  with no adopted harness reported "skill source could not be authored"
  through the CLI, the HTTP route and desktop IPC. Gated on the same
  predicate; genuine partial installs still report.
- The changeset text no longer claims new projects start with nothing
  selected, which stopped being true when create-project moved to detection.
- The migrate skip assertion pins `target-occupied` rather than matching only
  the skill name, so it cannot pass for the wrong reason.

* fix(ok): make seed and the create dialog honest about agent folders (PRD-7984)

Follow-up to the boot-watcher fix, from CI.

`ok seed` claimed work it would never do. The plan marked pack skills pending
whenever they were absent, but apply refuses to author them when the project
has no agent folder, so a re-run reported `applied` every time while writing
nothing. Plan and apply now branch on one resolver, `resolvePackSkillHome`,
which also folds in the symlink-escape case so that path can no longer produce
phantom "skill source could not be authored" errors either. The CLI now says
which folders it would accept and what to do, on the first run as well as
re-runs.

The create-project dialog could discard a user's choice. Its editor selection
is seeded asynchronously from `bridge.integrations.status()` on open, and a
user who expanded Advanced and ticked a box before that resolved had the
selection overwritten. The prior comment argued this was not reachable because
Create stays disabled until the cascade probe settles, but that covers submit,
not checkbox state. A touched flag now lets the visible state win.

Tests updated for the retired all-editors-pre-checked default:

- The three `qa-create-new-extended` smoke tests assert the detection-seeded
  baseline, and QA-005 now proves both directions on disk rather than only the
  negative half.
- The Playwright fixture seeder adopts a host, since project skill authoring
  refuses without one.
- The seed test that deleted every agent folder and still demanded pending
  work had an obsolete premise; it now keeps a host and removes only the skill,
  and additionally asserts the re-run re-authors it.

* fix(ok): close out review recommendations (PRD-7984)

- The `home-escapes-project` refusal now has coverage through `planSeed` and
  `runSeed`. Its symlink-specific guidance was unreachable by any test, so the
  two refusal branches could have been swapped without failing anything. Both
  layers now pin the verdict, and the CLI test asserts the symlink wording is
  present and the no-agent-folder wording is not.
- The skill-import no-host error says what to do. It names the folders it would
  accept and states that OpenKnowledge never creates one, matching the seed
  refusal note. The list comes from a new scope-aware `skillHomeCandidateFolders`
  reading the same root tables `resolveDefaultSkillHomeRel` consults, so it
  cannot drift. The urn and detail codes are unchanged.
- `detectedEditors` becomes `detectedEditorIds` on the integrations status. It
  is a flat id array and was reusing the name of a pre-existing rich-object
  field on the wiring payload. That field and its consumers are untouched.
- The multi-host occupied-slot migration case is pinned: a free lower-precedence
  host does not rescue an occupied higher one. The comment records why the
  inversion is deliberate, since scattering a skill to whichever host happened
  to be free lands it somewhere the user never chose.

GitOrigin-RevId: 56a4092e7d83518e5baa83d40b267412ee5d27ef
@inkeep-oss-sync
inkeep-oss-sync Bot merged commit 2c01b7d into main Aug 13, 2026
@inkeep-oss-sync
inkeep-oss-sync Bot deleted the copybara/sync branch August 13, 2026 18:50
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.

2 participants