- The oracle harness masks the climb to the root a /-prefixed target
produces (<UP_TO_ROOT>/): the number of `../` is the staged tmpdir's depth
(7 on macOS, 2 on Linux), not the verb's behavior. surface-brief-path-slash
re-recorded.
- Two context test helpers canonicalized their temp dir, which on Windows
yields a \\?\ verbatim path that takes `/` literally; they strip the prefix
like Node's realpathSync. The critique-storage identity test compares
against the platform's own resolved path.
- Every job that drives the binary end to end (live-e2e smoke and full,
accept-cleanup, the DeepSeek sweep, the remote CLI smoke) builds it from
the checkout first; before, they looked for a release that does not exist.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
Upstream sha 482368511a.
Codex's validator rejects unknown top-level keys, so the Codex and `.agents`
skills now carry `version` under the spec-defined `metadata:` map. Both
version readers learn the same parser: `parse_skill_frontmatter_version` in
`crates/context` (the boot update check) and `extract_version` in
`crates/skills` (`getSkillsVersion`). A metadata version wins, a legacy
top-level one still reads, only the map's own indent level counts, tabs count
as two spaces, and a comment line is skipped.
The build-tooling half (`versionInMetadata` on the two providers, the YAML
emitter's nested-object branch) came in with the merge.
Fourteen frontmatter shapes were recorded from origin/main's
`parseSkillFrontmatterVersion` and pinned as unit tests in both crates.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
Upstream sha 9736a9f6e9.
OpenCode does not honor `user-invocable: true` on SKILL.md frontmatter, so a
pinned skill never reaches its slash menu. `pin` now writes
`commands/impeccable-<cmd>.md` on the OpenCode command schema instead, and
skips `.opencode` in the SKILL.md loop so no unreachable
`.opencode/skills/<cmd>` is left behind. `unpin` mirrors it, marker-guarded,
and reaches both scopes even when the skill itself is gone.
`find_opencode_commands_dirs` covers the project-local dir when the project
has the skill and the user config dir when Impeccable is installed globally,
resolving that dir the way the CLI does (`OPENCODE_CONFIG_DIR` ->
`XDG_CONFIG_HOME/opencode` -> `~/.config/opencode`).
The build-tooling half of the upstream change (transformers, the OpenCode
command the build generates, `root-commands-sync`) came in with the merge and
needed no port.
Verified against origin/main's pin.mjs across seven scenarios (no harness,
project scope, user scope, a foreign command file, pin then unpin, unpin over
a foreign file, unpin with nothing pinned): identical stdout, identical file
sets, identical file contents apart from the one deliberate difference.
Oracle: five `pin-opencode-*` cases, with a DELTAS entry for the bridge body
naming the launcher rather than `node .../context.mjs`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
Upstream sha 672ca29642.
CSP. `detect-csp` recognizes Next.js 16's `proxy.{ts,js,mjs}` request hook
beside `middleware.*`, but only where it sits at a project root or its `src/`
directory: the scan root itself, or a nested directory carrying a Next
project marker (a `next.config.*`, an `app` / `pages` dir, or a `next`
dependency). A same-named helper elsewhere in the tree is not the framework
hook.
Context. `find_git_boundary_root` gives `resolve_project` a git-boundary
notion: an explicit target inside its own repository resolves against that
repository, and an external target resolves against its own root, so caller
context never leaks across the boundary. `hook_manifest_search_roots`
replaces the cwd/projectRoot/repoRoot triple with a walk up from the
project root that stops at the first git boundary, and each root's own hook
lifecycle config is honored before its manifest counts as coverage.
Verified against origin/main's JS: nine `detect-csp` placements and five
hook-discovery scenarios (enclosing harness root, that root disabled,
sibling target, nested git target, markerless nested git target) produce
identical output.
Oracle: five `csp-proxy-*` cases and five `context-hook-*` /
`context-markerless-nested-git-target` cases. Four route-target goldens were
re-recorded because #710 resolves a `/`-prefixed target outside the
workspace; each was cross-checked against origin/main, and
`surface-brief-write-route` has a DELTAS entry for the one wording
difference (an unwritable filesystem root).
`tests/framework-fixtures.test.mjs`'s new proxy-placement block came in from
the merge importing the deleted `detectCsp`; it now drives `detect-csp`
through the binary like the rest of that file.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
Upstream sha 8b326fc81e.
`resolve_target_path` / `find_unique_bare_target` in `crates/context`: a
`--target` that does not exist and reduces to a single path segment under
cwd resolves to the one workspace candidate with that name, so `--target a`
selects `apps/a`. A caller that already absolutized the name against cwd
(live and the other helpers do) takes the same route. Ambiguous or unknown
names still report the miss.
The context CLI resolves the target once and hands the resolved path to
`load_context`, replacing `path_exists_for_target`.
Oracle: four new `context-monorepo-target-bare-*` cases (bare name,
absolutized bare name, unknown name, bare name from a child cwd).
`context-monorepo-target-b-inherits` was re-recorded: resolving the target
before `load_context` changes its `surfaceBriefReason` from `not-found` to
`invalid-target`, which is what origin/main's `context.mjs` prints for the
same run.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
The engine no longer lives in a separate repo. `crates/` is a snapshot of the
open crates (foundation, core, common, context, live, hook, skills, comp,
comp-verbs, html, browser, detect, cli) plus `Cargo.lock`, taken as a git
archive of the engine repo at the commit that finished the boundary split.
None of that repo's history comes with it, and none of it should: the closed
half stays private.
The closed half is the rule engine. It ships as a prebuilt native archive per
target, `libimpeccable_detector.a`, published as a `detector-v<X>` GitHub
Release on this repo. `crates/core/build.rs` resolves and links it three ways:
`IMPECCABLE_DETECTOR_LIB=<dir>` for a local detector build, else the
`~/.impeccable/detector/<version>/<target>/` cache, else a download verified
against its `.sha256` sidecar. `crates/core` is a thin shim over a three-symbol
C ABI; nothing above it knows the boundary exists.
What changed versus the engine repo copy:
- Every crate manifest moves from `license-file.workspace` to
`license.workspace` (this workspace declares Apache-2.0), and the workspace
gains the `postcard` dependency the boundary encoding needs.
- The launcher contract test reads `skill/scripts/impeccable{,.cmd}` instead of
a sibling `launcher/` dir, and `engine_binary` downloads from
`github.com/pbakaus/impeccable/releases/download/engine-v<version>/` instead
of the retired dist repo. No oracle golden carried the old URL, so no
re-recording was owed.
- The tests that hunted for a public repo through `IMPECCABLE_PUBLIC_REPO`,
`../impeccable-second` or a hardcoded home directory now resolve the root as
`CARGO_MANIFEST_DIR/../..`, because they are in it. The env var stays as an
override for an out-of-tree checkout.
- The in-page bundle (`detect-antipatterns-browser.js`, 2 MB of generated wasm
glue) is no longer tracked. `crates/core/build.rs` resolves it beside the
archive, hands the path to `impeccable_core::browser::IN_PAGE_BUNDLE_JS`, and
live mode serves that. `scripts/check-detector-release.mjs` now requires it
and its `.sha256` in a detector release.
- The live crate embeds `skill/scripts/live-browser*.js` and
`modern-screenshot.umd.js` directly rather than through vendored copies, so
the binary and the installed skill cannot drift.
- `crates/browser/assets/` (an unused second copy of the bundle) is gone.
- `tests/lib/engine-bin.mjs` also accepts `target/release/impeccable`, so a
plain `cargo build --release -p impeccable` is enough to run `bun run test`.
Verified with the archive from a local detector build: `cargo test --workspace`
267 pass, oracle 795 pass / 0 fail / 0 missing, `bun run build` clean, the
default suite green, and the launcher's `engine-probe` handshake answering
through `skill/scripts/impeccable`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY