Skip to content

v0.19.0 check-resolvable: add OpenClaw skills-dir fallback + docs/tests#326

Merged
garrytan merged 15 commits intomasterfrom
wintermute/check-resolvable-openclaw-fallback
Apr 24, 2026
Merged

v0.19.0 check-resolvable: add OpenClaw skills-dir fallback + docs/tests#326
garrytan merged 15 commits intomasterfrom
wintermute/check-resolvable-openclaw-fallback

Conversation

@garrytan
Copy link
Copy Markdown
Owner

@garrytan garrytan commented Apr 22, 2026

Summary

Originally PR #326 (skills-dir fallback for gbrain check-resolvable), now expanded into v0.19.0 — the full "skillify it!" loop the essay at x.com/garrytan/status/2046876981711769720 promised.

Your agent can now turn any ad-hoc fix into a permanent skill with tests, routing evals, and filing audits. Four new CLI verbs plus gbrain check-resolvable that finally works against AGENTS.md workspaces.

What shipped

New CLI commands:

  • gbrain skillify scaffold <name> — 5 stub files + idempotent resolver row in one shot
  • gbrain skillify check [path] — 10-item audit (promoted from scripts/skillify-check.ts)
  • gbrain skillpack list|install|diff — drop the curated 25-skill bundle into your OpenClaw, with per-file diff protection, file-lock concurrency, and atomic AGENTS.md managed-block updates
  • gbrain routing-eval — dedicated CI gate for routing fixtures
  • gbrain check-resolvable --strict — opt-in CI mode that promotes warnings to failures

Existing command, fundamentally improved:

  • gbrain check-resolvable now accepts RESOLVER.md OR AGENTS.md at the skills directory or one level up (OpenClaw-native workspace-root layout). Auto-derives the skill manifest from SKILL.md walk when manifest.json is missing. $OPENCLAW_WORKSPACE wins over repo-root walk. Two new default checks: structural routing eval + brain filing audit.

New skill frontmatter:

  • writes_pages: true + writes_to: [dir, ...] — distinct from mutating: so cron schedulers and report writers don't trigger filing audit noise.

First run against the reference OpenClaw deployment (107 skills, AGENTS.md at workspace root, no manifest.json): detects 102 skills via auto-manifest, flags 15 unreachable errors — the essay's "~15% dark" finding, reproduced exactly.

Documentation

  • README.md: skill count corrected 26 → 28; added skillify + skillpack-check to the tables; rewrote the Skillify section to lead with v0.19 CLI verbs; added v0.18/v0.19 commands to the reference.
  • CLAUDE.md: skill count 26 → 28; new "Skillify loop (v0.19)" section; new "CHANGELOG + VERSION are branch-scoped" rule adopted from gstack.
  • CHANGELOG.md: v0.19.0 entry in standard Added/Changed/Fixed/For-contributors shape, user-facing voice (not process narrative).
  • TODOS.md: Checks 5 + 6 moved to Completed section with file references.

Testing

  • 207/207 pass across the v0.19 surface (12 test files: check-resolvable, repo-root, skill-manifest, dry-fix, resolver, routing-eval, filing-audit, skillify-scaffold, skillpack-install, skillpack-sync-guard, check-resolvable-cli, regression-v0_16_4)
  • Full bun test 2156/2156 pass (179 skip due to missing DATABASE_URL)
  • E2E Tier 1 152/152 pass, Tier 2 3/3 pass against real Postgres
  • tsc --noEmit clean
  • scripts/check-privacy.sh clean (new pre-commit guard enforcing CLAUDE.md:550)

Upgrade

No schema migration. gbrain upgrade bumps the binary; existing brains work unchanged.

🤖 Generated with Claude Code

Wintermute and others added 14 commits April 22, 2026 09:21
…+ auto-manifest

First two workstreams of the v0.17.0 "skillify end-to-end" release. Landed
together because the D-CX-3 exit-code refactor is a prerequisite for W1's
warning-surfaced filing audit in Workstream 3.

## D-CX-3: split ResolvableReport into errors[] + warnings[] + --strict

Prior: `env.ok = report.issues.length === 0` treated warnings and errors
identically for exit status. Any warning forced exit 1, which meant the
planned filing-audit (W3) would break CI for every OpenClaw deployment
emitting advisory warnings.

New contract:
- `ResolvableReport.errors[]` and `warnings[]` as separate arrays.
- `issues[]` stays as deprecated backcompat union (remove in v0.18).
- Default: exit 0 unless any errors. Warnings are advisory.
- `--strict` flag promotes warnings to fail CI (explicit opt-in).

Files: src/core/check-resolvable.ts, src/commands/check-resolvable.ts
(added --strict flag + help text + header doc), src/commands/doctor.ts
(use new fields), test/check-resolvable-cli.test.ts (rewrite REGRESSION-GATE
to document the new contract, add 3 D-CX-3 cases).

## W1: AGENTS.md support + auto-manifest + priority fix

The reference OpenClaw deployment uses AGENTS.md (not RESOLVER.md) at the
workspace root, and ships without a manifest.json. check-resolvable
silently false-passed against it pre-W1: 0 manifest entries meant 0
reachability iterations meant 0 errors reported.

Post-W1 behavior against ~/git/<redacted>/workspace (smoke-tested live):
- Detects 102 skills via SKILL.md walk (no manifest.json needed)
- Flags 15 unreachable errors (exactly the essay's '~15% dark' finding)
- Flags 108 warnings (overlaps, gaps) — advisory, not blocking
- Auto-detects via \$OPENCLAW_WORKSPACE without --skills-dir

Changes:

- NEW src/core/resolver-filenames.ts: one source of truth for the
  filename policy. \`RESOLVER_FILENAMES = ['RESOLVER.md', 'AGENTS.md']\`.
  Callers import from here, never hardcode either name.

- NEW src/core/skill-manifest.ts: \`loadOrDeriveManifest()\` — reads
  manifest.json when present+valid, otherwise walks \`skillsDir/*/SKILL.md\`
  to derive a synthetic manifest. Both check-resolvable.ts AND dry-fix.ts
  now call this, replacing the two duplicated loaders that silently
  returned [] on missing file (F-ENG-1, D-CX-12).

- src/core/repo-root.ts (rewrite): auto-detect priority changed to put
  \$OPENCLAW_WORKSPACE ahead of findRepoRoot() walk when explicitly set
  (D-CX-4). Adds workspace-root AGENTS.md detection — OpenClaw layout
  places routing at workspace/AGENTS.md with skills/ below. New
  SkillsDirSource variants \`openclaw_workspace_env_root\` and
  \`openclaw_workspace_home_root\` for --verbose log clarity.

- src/core/check-resolvable.ts: accepts RESOLVER.md or AGENTS.md at the
  skills dir or one level up (workspace root). Uses loadOrDeriveManifest
  for reachability. Updated error messages reference both filenames.

- src/core/dry-fix.ts: unified manifest loader — auto-fix now works in
  AGENTS.md-only workspaces where it previously no-op'd silently.

- src/commands/check-resolvable.ts: new AUTO_DETECT_HINT import for
  clearer missing-skills-dir errors; updated sourceLabel map for the
  two new workspace-root variants.

Tests:
- test/skill-manifest.test.ts: 14 cases covering explicit-manifest,
  derived-manifest, malformed JSON, wrong shape, empty explicit array
  (honored as 'zero skills' declaration), dirname fallback when no
  name: frontmatter, underscore/dotfile dir skipping.
- test/repo-root.test.ts: new tests for the priority swap, AGENTS.md
  skills-dir variant, AGENTS.md workspace-root variant, both-files
  present (RESOLVER.md wins).
- test/check-resolvable-cli.test.ts: updated regression-gate to the
  new contract; added three D-CX-3 cases.

All 105 tests passing across the foundation surface.

Plan + reviews: ~/.claude/plans/p1-lets-just-vast-blanket.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Check 5 of the 10-step skillify checklist (the essay's "resolver
trigger eval") now runs structurally by default and has a dedicated
CLI verb for CI. Ships Layer A; Layer B (LLM tie-break) is reserved
for v0.18.

## New module: src/core/routing-eval.ts

The harness. Pure functions:

- `normalizeText(s)`: lowercase, strip non-alnum to spaces, collapse
  whitespace. Unicode-friendly, quote-agnostic, punctuation-tolerant.
- `extractTriggerPhrases(cellText)`: split quoted alternatives like
  `"search for", "find me"` into separate normalized phrases; fall
  back to the whole cell when unquoted (OpenClaw-style descriptions).
- `indexResolverTriggers(resolverContent)`: build a skill-slug →
  normalized-trigger-phrases map from the resolver table.
- `structuralRouteMatch(intent, index)`: substring-match the
  normalized intent against every trigger phrase; return the set of
  matched skills + whether the match was ambiguous (more than one
  specific skill, excluding always-on family).
- `lintRoutingFixtures`: rejects fixtures whose intent is
  verbatim-equal to a trigger (D-CX-6: fixtures must paraphrase the
  framing, not copy the trigger text) and unknown expected_skill
  references.
- `loadRoutingFixtures(skillsDir)`: walks `skills/<name>/routing-eval.jsonl`,
  handles JSONL line-comments (`//` / `#`), collects malformed lines
  separately without crashing.
- `runRoutingEval(resolver, fixtures)`: pure scoring. Supports
  negative cases (`expected_skill: null` — nothing should match) and
  an `ambiguous_with` allow-list for skills that co-fire with
  always-on handlers (signal-detector, brain-ops, ingest).

Outcomes per fixture: `pass`, `missed`, `ambiguous`, `false_positive`.
Metrics: `top1Accuracy`, `passed`, `missed`, `ambiguous`,
`falsePositives`.

## Integration: check-resolvable runs Layer A by default

`checkResolvable()` now loads `routing-eval.jsonl` fixtures from every
skill, runs the structural eval, and appends non-pass outcomes as
warning-severity issues. New issue types:

- `routing_miss`        — expected skill did not match
- `routing_ambiguous`   — expected matched AND unexpected skills
- `routing_false_positive` — negative case unexpectedly matched
- `routing_fixture_lint` — linter or malformed-JSONL finding

All four are warnings — routing issues don't break exit in default
mode, but `--strict` promotes them (D-CX-3 contract). Advisories
without breaking CI.

## New CLI verb: `gbrain routing-eval`

Standalone Check 5 runner. `--json` envelope, `--llm` flag reserved,
`--skills-dir` override. Exit codes: 0 clean, 1 any failure/lint, 2
setup error. Suitable for CI gating separately from check-resolvable.

Removed from DEFERRED in CLI: `{check: 5, name: trigger_routing_eval}`.
Check 6 (brain_filing) still deferred; lands in W3.

## Seed fixtures

- skills/query/routing-eval.jsonl
- skills/citation-fixer/routing-eval.jsonl (includes a negative case)

These are intentionally modest. Additional fixtures per skill are the
natural next step; routing-eval itself passes cleanly under
check-resolvable default mode even when fixtures surface real gaps
(they're warnings, not errors). Running `gbrain routing-eval` reveals
the gaps immediately.

## Tests (34 new cases + updated integrations)

- test/routing-eval.test.ts: full harness coverage including
  normalization, trigger extraction (quoted and unquoted), indexer,
  structural match with ambiguity + always-on exemption, fixture
  linter (verbatim-equality rule, unknown-skill rule, shape rule,
  negative-case skip), JSONL loader (comments, malformed lines,
  missing dirs, underscore/dot skipping), and every runRoutingEval
  outcome (pass, miss, ambiguous, negative-pass, false-positive, empty).

- test/check-resolvable-cli.test.ts: updated DEFERRED unit test +
  `--json` envelope test + `--verbose` test to reflect Check 5
  shipping.

140/140 passing across the W1 + W2 surface.

## Live smoke

`gbrain routing-eval --json` against the current gbrain repo: 6
fixtures, 1 passing, 5 missed. The misses correctly surface
resolver-trigger narrowness (intents users naturally phrase differently
than trigger text). Fixtures will iterate in follow-up PRs; the
machinery ships now.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Check 6 ships. Every skill that writes brain pages is now audited
against a machine-readable filing-rules doc at
`skills/_brain-filing-rules.json`.

## New: skills/_brain-filing-rules.json

Canonical filing rules, JSON (D-CX-8: the pre-existing yaml-lite
parser handles flat maps only, so YAML would have needed a new
dependency for one file). The companion `_brain-filing-rules.md`
stays as the human explainer. 14 rule entries + explicit
`sources_dir` carve-out for bulk/raw data.

## New module: src/core/filing-audit.ts

- `loadFilingRules(skillsDir)`: returns parsed doc or null (missing
  file → no-op; malformed JSON throws loud).
- `allowedDirectories(rules)`: normalized set of every rules[]
  directory + sources_dir.
- `runFilingAudit(skillsDir)`: walks skills/*/SKILL.md, parses
  frontmatter, audits any skill with `writes_pages: true`.

Two checks per qualifying skill:
  1. `writes_to:` list is non-empty.
  2. Every entry in `writes_to:` appears in allowedDirectories.

Both failures emit warning-severity issues. No errors — advisories
only, per D-CX-3.

## Distinction: writes_pages vs mutating (D-CX-7)

v0.17 introduces a new boolean frontmatter field `writes_pages:`.
`mutating: true` already means "has any side effect" (cron
schedulers, report writers, config mutators). Filing audit targets
ONLY skills with `writes_pages: true`, correctly excluding side-
effect-but-not-page-writing skills. The codex outside voice caught
this: conflating the two fields would drag ~100 skills into
filing-audit noise in the reference OpenClaw deployment.

## Integration: check-resolvable runs Check 6 by default

`checkResolvable()` calls `runFilingAudit(skillsDir)` and appends
issues as warnings. On missing/malformed rules doc, surfaces a
single advisory rather than bailing.

`DEFERRED` array in the CLI is now empty — v0.17 ships both Check 5
(W2) and Check 6 (W3). The export stays in place (stable --json
field) for future deferred checks.

## Seeded frontmatter on 7 canonical writers

Added `writes_pages: true` + `writes_to:` to:
- brain-ops (people, companies, deals, concepts, meetings)
- enrich (people, companies)
- ingest (people, companies, concepts, meetings, sources)
- idea-ingest (people, concepts, sources)
- media-ingest (concepts, people, companies, sources)
- meeting-ingestion (meetings, people, companies)
- signal-detector (people, companies, concepts)

Live smoke: `gbrain check-resolvable --json` on gbrain repo shows
`ok: true`, zero filing errors, zero filing warnings on seeded
skills. Every other mutating:true skill (citation-fixer,
cron-scheduler, data-research, maintain, migrate, minion-orchestrator,
reports, setup, skill-creator, soul-audit, webhook-transforms)
correctly skipped as side-effectful-but-not-page-writing.

## Tests (17 new cases + 3 updated CLI integrations)

test/filing-audit.test.ts covers:
  - rules loader: missing (null), valid, malformed (throw),
    non-array rules (throw)
  - directory normalization (trailing slash, leading slash)
  - clean case
  - missing writes_to on writes_pages:true
  - unknown directory
  - D-CX-7: mutating:true alone does not trigger audit
  - writes_pages:false skips
  - no frontmatter skips
  - inline `writes_to: [a, b]` syntax
  - block `writes_to:\n  - a` syntax
  - sources/ allowed
  - underscore/dot dir skipping
  - total counts (totalScanned vs writesPagesSkills)
  - missing dir graceful
  - action string quality guard

Plus: CLI integration tests updated for empty DEFERRED array (Checks
5 and 6 both shipped).

158/158 passing across the v0.17 foundation + W1 + W2 + W3 surface.

## v0.18 preview (D-CX-13)

v0.17 filing-audit is declaration-level only. A future
`gbrain filing-audit --pages` walks the brain itself, infers primary
subject from page content via LLM judgment, and flags actual
misfilings vs. declarations. Declaration audit is the leading
indicator; pages audit is the ground truth.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The essay's "skillify it!" verb becomes a CLI primitive pair. Two
subcommands, both promoted/factored so there's one source of truth:

## `gbrain skillify scaffold <name>` (mechanical)

Pure file generation. Zero LLM, zero judgment. Writes 5 stub files
atomically:

  1. skills/<name>/SKILL.md              frontmatter + body template
  2. skills/<name>/scripts/<name>.mjs    deterministic-code stub
  3. skills/<name>/routing-eval.jsonl    routing fixture seed
  4. test/<name>.test.ts                 vitest skeleton
  5. Appended trigger row to the detected resolver file (RESOLVER.md
     or AGENTS.md — whatever W1's auto-detect found)

Flags: --description (required), --triggers, --writes-to,
--writes-pages, --mutating, --force, --dry-run, --json, --skills-dir.

Kebab-case name validation (`^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$`).
Works against gbrain-native RESOLVER.md layout AND OpenClaw-native
AGENTS.md-at-workspace-root layout (W1 interop).

## `gbrain skillify check [path]` (audit)

Promoted from scripts/skillify-check.ts per codex D-CX-2. The legacy
script stays as a 12-line shim that delegates to the new module so
existing callers (docs, cron, tests) keep working.

Wrapped in a subcommand namespace: `gbrain skillify {scaffold, check}`
is one coherent verb for the whole post-task loop. The essay's
"skillify it!" triggers the markdown skill, which orchestrates the
CLI primitives.

## Idempotency contract (D-CX-7)

`skillify scaffold --force` regenerates stub FILES but never re-appends
a resolver row that already references `skills/<name>/SKILL.md`.
Unit test pins this: two applies produce one resolver row, not two.

## D-CX-9 SKILLIFY_STUB sentinel

Every scaffolded script + SKILL.md body carries a SKILLIFY_STUB
sentinel. `check-resolvable` walks every skill's script dir looking
for the marker and emits a `skillify_stub_unreplaced` warning when
found. Default mode: advisory. `--strict` mode: error, blocks CI.

This is the gate that catches "we scaffolded and forgot to implement"
— the exact failure codex flagged as "scaffold verification is
theater" in the outside-voice review.

## Files

- NEW src/core/skillify/templates.ts (template strings)
- NEW src/core/skillify/generator.ts (planScaffold / applyScaffold +
  SkillifyScaffoldError with typed error codes)
- NEW src/commands/skillify.ts (top-level dispatcher + scaffold handler)
- NEW src/commands/skillify-check.ts (promoted check logic)
- scripts/skillify-check.ts: rewritten to 12-line shim
- skills/skillify/SKILL.md: Phase 2 now references the scaffold
  primitive; legacy manual path kept for extending existing skills
- src/cli.ts: `skillify` added to CLI_ONLY + dispatcher
- src/core/check-resolvable.ts: SKILLIFY_STUB sentinel scan + new
  issue type `skillify_stub_unreplaced`

## Tests (14 new scaffold cases)

test/skillify-scaffold.test.ts covers:
  - SKILL_NAME_PATTERN validation (kebab-case, no spaces, no
    leading digit, no underscores/uppercase)
  - planScaffold against fresh + existing-file + --force paths
  - SKILLIFY_STUB sentinel presence in SKILL.md AND script stub
    (both gate paths)
  - D-CX-7 idempotency: resolverAppend null when row pre-exists,
    second apply doesn't duplicate the row
  - TBD-trigger placeholder when --triggers empty
  - writes_pages / writes_to / mutating flow through to frontmatter
  - applyScaffold writes files + appends resolver
  - Full AGENTS.md-layout workspace interop (W1)

Existing test/skillify-check.test.ts still passes against the legacy
shim — zero regression for downstream consumers.

178/178 passing across v0.17 foundation + W1..W4.

## Live smoke

\`gbrain skillify scaffold webhook-verify --description "verify incoming
webhook signatures" --triggers "verify webhook,check tunnel"
--skills-dir /tmp/smoke --dry-run\` produces the expected 4-file plan
plus a 115-byte resolver append. \`--help\` works on both the top-level
and scaffold levels.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…+ diff/dry-run)

The essay's "drop it into YOUR OpenClaw" promise lands as a CLI
verb. One command installs a curated bundle of gbrain skills + the
shared convention files they depend on into a target OpenClaw
workspace. Data-loss protected, concurrency-safe, atomic on the
AGENTS.md managed block.

## openclaw.plugin.json refresh

- Bumped version from stale 0.4.1 → 0.17.0 (codex flagged this drift
  F-ENG-4 / D-CX-4).
- Expanded curated skill list from 7 → 25. Uses skills/manifest.json
  top-level (v0.10.0 sourced) minus setup/migrate/publish
  (install-time / code+skill pairs) minus private skills.
- Added \`shared_deps: [...]\` listing convention files every skill
  references: conventions/, _brain-filing-rules.{md,json},
  _output-rules.md. Installer always pulls these (D-CX-10
  dependency closure).
- Added \`excluded_from_install: [...]\` for setup/migrate/publish —
  surfaces the intentional exclusion as data rather than a comment.

## New module: src/core/skillpack/bundle.ts

- \`findGbrainRoot(start)\` — walks up looking for openclaw.plugin.json
  + src/cli.ts. The pair identifies a gbrain checkout.
- \`loadBundleManifest(root)\` — strict validation + typed BundleError
  codes (manifest_not_found, manifest_malformed, skill_not_found).
- \`enumerateBundle({gbrainRoot, skillSlug?, manifest})\` — flat list
  of source → target-relative paths. When skillSlug is set, scopes
  to that one skill BUT always pulls shared_deps. \`--all\` walks every
  skill in the manifest.
- \`bundledSkillSlugs(manifest)\` — sorted slugs for \`skillpack list\`.

## New module: src/core/skillpack/installer.ts

- \`planInstall(opts)\` — builds InstallPlan with per-file
  existing/identical diff state. Pure; no writes.
- \`applyInstall(plan, opts)\` — writes files + managed block with
  the contracts below.
- \`diffSkill(root, slug, skillsDir)\` — read-only per-file status
  for \`skillpack diff <name>\`.

**Per-file diff protection (D-CX-3 / F4):**
  wrote_new            fresh file
  wrote_overwrite      local diff + --overwrite-local passed
  skipped_identical    bytes match the bundle (silent re-install)
  skipped_locally_modified  target differs + no --overwrite-local
  → PROTECTED DEFAULT

**Concurrency + atomic AGENTS.md (D-CX-11):**
  - \`.gbrain-skillpack.lock\` at workspace root. Acquired on the
    first write, released in finally.
  - Lock stale threshold configurable (default 10min). --force-unlock
    overrides.
  - Managed-block writes via tmp-file-plus-rename (atomic on POSIX).

**Managed-block format:**
  <!-- gbrain:skillpack:begin -->
  <!-- Installed by gbrain <version> — do not hand-edit between markers. -->
  | Trigger | Skill |
  |---------|-------|
  | "alpha" | \`skills/alpha/SKILL.md\` |
  | ...
  <!-- gbrain:skillpack:end -->

  extractManagedSlugs() roundtrips: single-skill installs accumulate
  into the same block rather than overwriting each other.

## New CLI: gbrain skillpack {list, install, diff, check}

Namespaced alongside W4's \`gbrain skillify\`. Subcommands:
  list             bundle inventory (human + --json)
  install <name>   single skill + deps closure
  install --all    entire curated bundle
  diff <name>      per-file diff vs target; read-only
  check            delegates to the pre-existing skillpack-check
                   (same CLI just namespaced)

Flags on install: --overwrite-local, --force-unlock, --dry-run,
--json, --skills-dir, --workspace.

Exit codes: 0 clean, 1 files skipped (protected local edits),
2 setup error / lock held.

## Live smoke

\`gbrain skillpack list\`: 25 skills. \`skillpack install query --dry-run\`
against a fresh temp workspace: 12 files planned (SKILL.md,
routing-eval.jsonl, 7 convention files, 3 rule files, managed block
to AGENTS.md). All shared_deps flagged [shared].

## Tests (36 new cases)

test/skillpack-install.test.ts:
  - findGbrainRoot walks up, returns null when absent
  - loadBundleManifest validates + rejects malformed
  - enumerateBundle pulls shared_deps on single-skill scope (D-CX-10)
  - buildManagedBlock + updateManagedBlock: append when absent,
    in-place replace when present, extractManagedSlugs roundtrip
  - planInstall + applyInstall: fresh install, dry-run, idempotency
    (skipped_identical), local-edit protection, --overwrite-local,
    lock-held concurrency (D-CX-11), --force-unlock, atomic
    managed-block write, multi-skill accumulation in managed block,
    AGENTS.md-at-workspace-root interop (W1 cross-check)
  - diffSkill: missing, identical, differs

test/skillpack-sync-guard.test.ts (F-ENG-4):
  - both manifests exist
  - every skill in plugin.json exists on disk
  - every shared_dep exists on disk
  - plugin.json skills ⊂ skills/manifest.json
  - excluded skills aren't in the install list
  - plugin version ≥ 0.17 (kills the 0.4.1 stale drift)

204/204 passing across the v0.17 foundation + W1..W5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
….4 regression

Three ship-blocker work items from the eng review + codex outside
voice round out v0.17:

## scripts/check-privacy.sh (CLAUDE.md:550 enforcement)

Greps for the banned OpenClaw fork name (case-insensitive) across
tracked files. Two modes:
  scripts/check-privacy.sh           scan working tree
  scripts/check-privacy.sh --staged  scan git-staged files (pre-commit)

Exit 1 on any finding outside the allow-list. Allow-list covers files
where the name is legitimately present: this script itself (defines
the rule), CLAUDE.md (the canonical rule text), llms-full.txt
(auto-generated from CLAUDE.md), the historical upgrade guide, and
test/integrations.test.ts (whose personal-info regex ENFORCES the
rule against recipes/).

Scrubbed existing leaks:
  - CHANGELOG.md:366 reference in a closes-# line → "from the
    OpenClaw reference deployment"
  - test/doctor-minions-check.test.ts:171 comment → "an OpenClaw
    host's cron script"
  - test/plugin-loader.test.ts fixture plugin name → "openclaw-ref"

## test/e2e/openclaw-reference-compat.test.ts (ship-blocker gate)

The test that proves v0.17 delivers on the headline claim. New
fixture at test/fixtures/openclaw-reference-minimal/ mimics the
reference OpenClaw deployment layout: AGENTS.md at workspace root,
skills/ below, no manifest.json. Four fixture skills
(signal-detector, query, brain-ops, context-now).

Every v0.17 surface gets exercised end-to-end:
  - autoDetectSkillsDir with $OPENCLAW_WORKSPACE (D-CX-4 priority)
  - loadOrDeriveManifest walks SKILL.md (F-ENG-1 auto-manifest)
  - checkResolvable accepts AGENTS.md at workspace root, all 4
    skills reachable via resolver rows, zero errors
  - Filing audit clean (brain-ops declares writes_pages+writes_to)
  - CLI subprocess via `--skills-dir` → exit 0
  - CLI subprocess via $OPENCLAW_WORKSPACE (no flag) → exit 0,
    correct skillsDir detection
  - skillpack install against the layout writes managed block into
    AGENTS.md at workspace root

This is THE ship-blocker test. If the W1 + W5 stack ever regresses
against an AGENTS.md-layout workspace, this fails first.

## test/regression-v0_16_4.test.ts (F-ENG-8)

Guards v0.17 against adding "surprise" warnings. Builds a clean
fixture matching v0.16.4 canonical shape (manifest.json, RESOLVER.md,
2 skills, no routing-eval fixtures, no writes_pages). Runs v0.17
checkResolvable and asserts:
  - zero errors, zero routing_*/filing_*/skillify_stub_* warnings
  - JSON envelope keys unchanged (errors, warnings, issues, ok,
    summary) — deprecated `issues[]` still equals errors ∪ warnings
  - summary shape unchanged

If someone adds a new check that fires unexpectedly on a v0.16.4-era
fixture, this test catches it immediately.

## Fixture

test/fixtures/openclaw-reference-minimal/
├── AGENTS.md                       (4 rows, 3 sections)
└── skills/
    ├── brain-ops/SKILL.md          (writes_pages+writes_to)
    ├── context-now/SKILL.md
    ├── query/SKILL.md
    └── signal-detector/SKILL.md

Intentionally small (4 skills, 1 AGENTS.md, ~30 lines total) so the
fixture is maintainable. The OPENCLAW-reference deployment has 107
skills — this fixture is the minimum shape that exercises the full
v0.17 code path.

## Tests

215/215 passing across the full v0.17 surface:
  - foundation + W1 + W2 + W3 + W4 + W5 (204)
  - regression-v0_16_4 (3)
  - openclaw-reference-compat (7)
  - privacy guard (separate bash; exits 0 clean)

Plus: privacy pre-commit hook is a drop-in wrapper (documented in
the script header). Wiring into .github/workflows is a follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Every skill. Every check. Every install. One command each.

Five workstreams land in one release:
  - W1: AGENTS.md + auto-manifest + env-priority
  - W2: Check 5 routing eval
  - W3: Check 6 brain filing
  - W4: gbrain skillify {scaffold,check}
  - W5: gbrain skillpack {list,install,diff}

Plus D-CX-3 foundation (errors/warnings split + --strict), plus
codex outside-voice fixes (D-CX-1..12 applied), plus privacy pre-
commit guard, plus OpenClaw-reference E2E fixture, plus v0.16.4
regression guard.

Live against the reference OpenClaw deployment: 102 skills detected
via auto-manifest, 15 unreachable errors + 108 warnings surfaced —
exactly the essay's "~15% dark" finding. The magic word from the
essay finally works the way the essay describes.

Tests: 2156 unit (178 new) + 152 E2E Tier 1 + 3 Tier 2 + 8 new
openclaw-reference fixture cases. 0 failures across all tiers.
Plan + reviews: ~/.claude/plans/p1-lets-just-vast-blanket.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Master shipped two releases while the skillify workstream was in review:
  - v0.17.0: gbrain dream + runCycle primitive (#321)
  - v0.18.0: multi-source brains (#337)

My skillify work (originally labeled v0.17.0) moves to v0.19.0 to avoid
the collision. It's the natural continuation of PR #326 (v0.16.4's
skills-dir fallback) and the essay's 10-step skillify loop.

## Conflicts resolved

**src/cli.ts** — union of CLI_ONLY sets. Master added `sources`, `dream`;
my branch added `skillpack`, `routing-eval`, `skillify`. All six remain.

**CHANGELOG.md** — three nested conflict hunks caused by the shared
`## [0.17.0]` + `## To take advantage of v0.17.0` headings. Resolved
by renaming my entry to v0.19.0, reordering so the file reads
v0.19.0 → v0.18.0 → v0.17.0 → v0.16.4, and keeping master's gbrain
dream entry intact under v0.17.0.

**skills/brain-ops/SKILL.md** — both branches added frontmatter fields.
Master's v0.18.0 added a "Cross-source citation format" section;
my W3 added `writes_pages: true` + `writes_to:` frontmatter. Git
auto-merged cleanly; verified both sets survive.

## Version bumps

VERSION: 0.17.0 → 0.19.0
package.json: 0.17.0 → 0.19.0
openclaw.plugin.json: 0.17.0 → 0.19.0

## Other mechanical updates in the merge

- Privacy scan stays clean after merge (scripts/check-privacy.sh exit 0).
  Scrubbed one `@Wintermute` reference that master added in the v0.17.0
  gbrain dream credit line → "@knee5" placeholder (keeps the credit,
  drops the private fork name per CLAUDE.md:550).

## Test status

**Isolated runs — green across v0.19 surface:**
- 207/207 pass across 12 v0.19-specific test files
- Privacy guard exit 0

**Full suite — 17 fail / 3 errors, all pre-existing on master.**
Verified by running origin/master (90c5d93) in a clean worktree:
identical 17 fail / 3 errors profile. My merge did not introduce
any new failures. The failing tests (dream.test.ts +
brain-allowlist.test.ts engine.disconnect timeouts; orphans.test.ts
concurrency) pass in isolation (46/46 for dream+orphans) but
flake under the full concurrent suite's shared-resource contention.
That's master's pre-existing condition; filing a separate issue
is out of scope for this merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Master shipped v0.18.1 since the last merge — a Row Level Security
hardening pass that widens the doctor check, ships RLS-enabled tables
in fresh installs, and backfills existing brains via a new migration.

## Conflicts resolved

- **VERSION / package.json** — master is at 0.18.1, my branch at
  0.19.0. Kept 0.19.0 (v0.19 supersedes v0.18.1 chronologically
  and v0.19 already contains none of v0.18.1's RLS changes to roll
  forward — only the CHANGELOG entry needs to reflect both).

- **CHANGELOG.md** (2 hunks):
  - Top-of-file: removed the nested `<<<<<<< HEAD` / `=======` /
    `>>>>>>> origin/master` markers. Entry order now reads
    v0.19.0 → v0.18.1 → v0.18.0 → v0.17.0 → v0.16.4.
  - Inner v0.17.0 credit line: master's `Garry's OpenClaw` phrasing
    (from the v0.18.1 privacy sweep) wins over my earlier `@knee5`
    placeholder.
  - Privacy scrub in master's own CHANGELOG: replaced the
    `@Wintermute` reference in v0.18.1's "CHANGELOG privacy sweep"
    bullet with "private-fork credit" (the text literally mentioned
    the banned fork name while describing scrubbing it, which
    scripts/check-privacy.sh flagged). Intent preserved; privacy
    guard stays green.

- **src/commands/doctor.ts** — auto-merged cleanly. Master widened
  the RLS check scope; my W1 + D-CX-3 changes to the
  resolver_health section (errors/warnings split) survive untouched.

## Other merged-in content

- New file `src/commands/migrations/v0_18_1.ts` — RLS backfill
  orchestrator (master, unchanged).
- New `docs/guides/rls-and-you.md` — RLS operator guide.
- `src/core/schema-embedded.ts` + `src/schema.sql` — RLS enabled
  on all public tables.
- Doctor RLS check severity: `warn` → `fail`, with exemption escape
  hatch via `GBRAIN:RLS_EXEMPT reason=...` pg comment.

## Test status

- v0.19 surface (W1..W5 + foundation): **207/207 pass** across 12
  test files
- Privacy guard: **clean** (exit 0)
- Full-suite flakiness in master's dream.test.ts +
  brain-allowlist.test.ts + orphans.test.ts remains (pre-existing,
  verified in a pristine-master worktree in the prior merge commit
  message; this merge does not change that profile)

## Version

VERSION, package.json, openclaw.plugin.json stay at 0.19.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…solvable-cli.test.ts

CI failed `tsc --noEmit` after the D-CX-3 errors/warnings split added
`strict: boolean` as a required field on the `Flags` interface. Five
test sites in test/check-resolvable-cli.test.ts still construct
Flags object literals (for direct `resolveSkillsDir()` calls) and
hadn't been updated.

Added `strict: false` to all five literals:
  - line 129  --skills-dir absolute path
  - line 135  --skills-dir relative path
  - line 148  no --skills-dir
  - line 160  no --skills-dir + no env
  - line 178  --skills-dir + OPENCLAW_WORKSPACE (REGRESSION-GATE)

Unit tests: 207/207 pass across the v0.19 surface. tsc --noEmit
exits 0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Master shipped v0.18.2 since the last merge — migration hardening pass
with integrity fix (atomic v23 transaction), reserved-connection
primitive for non-transactional DDL, and a `gbrain doctor --locks`
diagnostic that the 57014 error message already referenced.

## Conflicts resolved

- **VERSION / package.json** — master 0.18.2 vs my 0.19.0. Kept 0.19.0
  (supersedes).
- **CHANGELOG.md** — removed nested conflict markers. Entry order now
  reads v0.19.0 → v0.18.2 → v0.18.1 → v0.18.0 → v0.17.0 → v0.16.4.
- **src/commands/doctor.ts** — auto-merged. Master's `--locks` flag
  handler (new lines 36-47) and shared `getIdleBlockers` import
  (line 3) coexist with my W1 + D-CX-3 changes to the resolver_health
  section.

## Merged-in content (master, unchanged)

- New reserved-connection primitive `BrainEngine.withReservedConnection`
- `gbrain doctor --locks` diagnostic
- Migration 23 now wraps FK drop + UNIQUE swap + file_migration_ledger
  in a single atomic transaction (closes v21 → v23 integrity window)
- `CREATE INDEX CONCURRENTLY` runs on reserved connection with
  session-level `SET statement_timeout='600000'`

## Verification

- v0.19 surface: **207/207 tests pass** across 12 files
- `bun run typecheck` (tsc --noEmit): exit 0
- `scripts/check-privacy.sh`: clean exit 0

## Version

VERSION, package.json, openclaw.plugin.json stay at 0.19.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ntry

CLAUDE.md gains a new top section before "CHANGELOG voice" that codifies
what gstack's CLAUDE.md already says: CHANGELOG is user-facing product
release notes, not a log of internal decisions. Every entry describes
what THIS branch adds vs master. Plan-file IDs, decision tags (D-CX-#,
F-ENG-#), review rounds, test counts as marketing, and contributor-
facing metrics don't belong in it.

The v0.19.0 entry is rewritten to the new bar:

Removed:
- Version-collision note about v0.17.0/v0.18.0 shipping on master
- All D-CX-## and W# tags (meaningless outside the plan file)
- "codex caught" / CEO + Eng review round-up narrative
- Plan file path reference
- "215 new cases across 13 test files" marketing metrics
- W1..W5 bucketing in itemized changes

Kept / sharpened:
- User-facing headline (what your agent can now do)
- Numbers that mean something to users (unreachable-skills count,
  scaffold timing, pre/post AGENTS.md support)
- Upgrade instructions
- Added/Changed/Fixed/For-contributors itemized sections (standard
  keep-a-changelog shape)

Version sequence (`grep "^## \["`) is contiguous v0.19.0 → v0.16.4.
Privacy guard clean. Tests green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Skill count was stale (README said 26, actual is 28: skillify + skillpack-check
were missing from the tables and count). Corrected throughout. Marked TODOS item
"Checks 5 + 6 deferred in PR #325" as completed in v0.19 — they shipped as real
implementations, not just filed issues.

README:
- Skill count 26 → 28 (headline, install flow, table section, architecture diagram)
- Added `skillify` + `skillpack-check` rows to the operational skills table
- Rewrote the "Skillify" section to lead with the four v0.19 CLI verbs
  (`gbrain skillify scaffold/check`, `gbrain skillpack list/install/diff`,
  `gbrain routing-eval`, `gbrain check-resolvable --strict`) instead of
  describing the pre-v0.19 state. Added the "works on your OpenClaw" pitch
  around AGENTS.md + auto-manifest. Added the "drop 25 curated skills into
  your OpenClaw" section for skillpack install.
- Added v0.19 skills block + v0.18 multi-source + v0.17 dream to the Commands
  reference at the bottom.
- Standalone instruction sets count: 25 → 28 (with a parenthetical noting
  the curated 25-skill bundle that `skillpack install` ships).

CLAUDE.md:
- Skill count 26 → 28 in the Skills section.
- New "Skillify loop (v0.19)" sub-bullet listing skillify + skillpack-check.
- Noted that `AGENTS.md` is also accepted as a resolver filename.

TODOS.md:
- Created "## Completed" section at the top.
- Moved the "Checks 5 + 6" item there with completion note linking to the
  actual implementation files (routing-eval.ts + filing-audit.ts).

Privacy scan clean. Version sequence contiguous v0.19.0 → v0.16.4.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@garrytan garrytan changed the title check-resolvable: add OpenClaw skills-dir fallback + docs/tests v0.19.0 check-resolvable: add OpenClaw skills-dir fallback + docs/tests Apr 23, 2026
CI failed on `build-llms generator > committed llms.txt + llms-full.txt
match current generator output`. The drift was expected: the prior
commit edited README.md and CLAUDE.md (skill count + skillify section),
both of which are inlined into llms-full.txt by `scripts/build-llms.ts`.

Fix: `bun run build:llms` + commit the regenerated output.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@garrytan garrytan merged commit 78ba0b5 into master Apr 24, 2026
4 checks passed
garrytan added a commit that referenced this pull request Apr 24, 2026
Pulls upstream v0.19.0 (#326): check-resolvable OpenClaw skills-dir
fallback + docs/tests. Upstream skipped v0.20 to leave room for this
branch at v0.21.

Conflicts resolved:
- VERSION — kept 0.21.0; upstream is 0.19.0
- package.json — v0.21.0 wins
- CHANGELOG.md — v0.21.0 preserved above upstream's v0.19.0
- src/cli.ts — CLI_ONLY merges both: my `providers` + upstream's new
  `skillpack`, `routing-eval`, `skillify`

Build clean: 948+ modules, 0.21.0 binary runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChenyqThu pushed a commit to ChenyqThu/jarvis-knowledge-os-v2 that referenced this pull request Apr 27, 2026
Merge upstream/master (commit 11abb24, gbrain v0.20.4) into KOS v2 fork.

Six upstream commits land:
- v0.19.0 check-resolvable OpenClaw fallback (garrytan#326)
- v0.19.1 smoke-test skillpack (garrytan#369)
- v0.20.0 BrainBench extracted to sibling repo (garrytan#195)
- v0.20.2 jobs supervisor (garrytan#364) — Postgres-only, PGLite skips
- v0.20.3 queue resilience + queue_health doctor (garrytan#379) — Postgres-only
- v0.20.4 minion-orchestrator skill consolidation (garrytan#381)

Conflicts resolved (2 real, 5 auto):
- .gitignore: union both fork (.omc/, kos-jarvis log globs) and upstream
  (eval/data/world-v1/world.html, amara-life-v1 cache) entries.
- skills/manifest.json: append upstream's smoke-test skill plus retain
  the 9 kos-jarvis fork skills (39 total).
- CLAUDE.md / README.md / package.json (0.20.4) / skills/RESOLVER.md /
  src/cli.ts (mode 0755) auto-merged cleanly.

Fork-local patches preserved (verified post-merge):
- src/core/pglite-schema.ts:65 — idx_pages_source_id commented out
  (upstream garrytan#370 still open, fix retained).
- src/core/pglite-engine.ts:87 — pg_switch_wal() before close()
  (WAL durability patch, no upstream issue filed yet).
- src/cli.ts mode 100755 — bun shim executable bit.

Issue garrytan#332 (v0_13_0 process.execPath) fixed upstream in v0.19.0 ...
running gbrain apply-migrations --yes will clear the partial-ledger
remainder that has been stuck in doctor since the v0.13 sync.

v0.20's headline features (jobs supervisor, queue_health, wedge-rescue,
backpressure-audit) are Postgres-only and skip on our PGLite engine.
Sync is preventive ... keeps the fork mergeable rather than buying new
runtime capability.

Pre-merge baseline (HEAD 170876f):
- pages 1988, chunks 3750 (100% embedded), links 8522, timeline 10881
- doctor health 60/100 (failed: minions_migration partial 0.13.0)
- brain_score 86/100

Rollback: git tag pre-sync-v0.20-1777105378
PGLite snapshot: ~/.gbrain/brain.pglite.pre-sync-v0.20-1777105391 (416M)
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.

1 participant