@hasna/skills 0.10.83 → 0.10.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +166 -15
  2. package/bin/index.js +5829 -2913
  3. package/bin/mcp.js +1766 -835
  4. package/bin/migrate.js +1 -1
  5. package/bin/server.js +1 -1
  6. package/bin/worker.js +1 -1
  7. package/dist/cli/commands/agent-integration.d.ts +55 -0
  8. package/dist/cli/commands/context.d.ts +8 -0
  9. package/dist/cli/commands/runtime-launcher.d.ts +4 -9
  10. package/dist/index.js +3039 -1531
  11. package/dist/lib/agent-adapters.d.ts +5 -2
  12. package/dist/lib/agent-discovery.d.ts +22 -4
  13. package/dist/lib/agent-hermes.d.ts +7 -1
  14. package/dist/lib/agent-integration.d.ts +31 -2
  15. package/dist/lib/agent-opencode.d.ts +4 -0
  16. package/dist/lib/claude-hook-disable.d.ts +32 -0
  17. package/dist/lib/claude-settings-witness.d.ts +28 -0
  18. package/dist/lib/codex-settings-witness.d.ts +20 -0
  19. package/dist/lib/guarded-agent-config.d.ts +3 -0
  20. package/dist/lib/hook-diagnostics.d.ts +3 -1
  21. package/dist/lib/narrowed-witness-ledger.d.ts +24 -0
  22. package/dist/lib/native-discovery-roots.d.ts +8 -0
  23. package/dist/lib/native-drift-receipt.d.ts +55 -0
  24. package/dist/lib/opencode-hook-protocol.d.ts +5 -0
  25. package/dist/lib/profile-client.d.ts +1 -0
  26. package/dist/lib/selection-cache.d.ts +47 -2
  27. package/dist/lib/selection-resolver.d.ts +13 -1
  28. package/dist/lib/session-background-renewal.d.ts +118 -0
  29. package/dist/lib/session-reconciliation.d.ts +82 -2
  30. package/dist/lib/skill-context.d.ts +50 -1
  31. package/dist/lib/skill-relevance.d.ts +95 -0
  32. package/dist/runtime-prerequisites.js +570 -165
  33. package/dist/sdk/index.js +2629 -1396
  34. package/docs/plugin-admission.md +132 -3
  35. package/package.json +1 -1
package/README.md CHANGED
@@ -471,8 +471,12 @@ Retire native payloads before use. Legacy `skills-cli.md` files can shadow the
471
471
  bridge and must also be preserved and retired before proceeding. Only `skill_view(name:
472
472
  "skills-cli")` is allowed natively; author payloads with Skills CLI commands.
473
473
  Hermes itself fails open on `pre_llm_call` errors. A returned refusal is visible
474
- context, and the trusted pre-tool guard blocks drift and native skill fallback;
475
- this is not a claim that Hermes can prevent every model call after a failed
474
+ context. The trusted pre-tool guard blocks native payload skills and a
475
+ `skill_view(skills-cli)` call while the bridge is unverified or can be
476
+ shadowed (a legacy `skills-cli.md`, a bridge-named copy, or an environment
477
+ override above that leaves the effective discovery unchecked); other discovery
478
+ drift is reported and recorded, not blocked, and other tools proceed. This is
479
+ not a claim that Hermes can prevent every model call after a failed
476
480
  prompt hook or guarantee refusal if the native host/supervisor itself dies. Arbitrary project/plugin paths still require a discovery audit.
477
481
 
478
482
  Reviewed discovery can also bind `directories: [{ path, sha256 }]` alongside
@@ -604,7 +608,16 @@ inventory entry outside the manifest remains untouched.
604
608
 
605
609
  `skills hook agents --json` reports the supported adapters and coverage limits.
606
610
  Claude and Codex have lifecycle context hooks; Gemini uses `BeforeAgent`, and
607
- OpenCode uses its awaited message plugin. Cursor receives selected context at
611
+ OpenCode uses a v2 object plugin with awaited `prompt` and `context` hooks.
612
+ The OpenCode adapter targets the v2.0.32 Promise plugin contract. Prompt
613
+ admission stages genuine user text transiently. Request context matches that
614
+ text and restores verified selections
615
+ into transient system context without changing message history. Native skill
616
+ tools and prompt attachments allow only `skills-cli`. Disposal removes hook
617
+ registrations and cancels pending Skills hook children. Exact managed v1 plugin
618
+ bytes remain recognizable for reviewed upgrades. The isolated contract tests
619
+ do not establish adoption by an installed OpenCode process.
620
+ Cursor receives selected context at
608
621
  session start and gates later prompt submission; its prompt hook does not
609
622
  inject context on the supported installed path. Other inventoried clients do
610
623
  not automatically gain a working prompt adapter.
@@ -989,13 +1002,78 @@ own bounded native client; it does not reload an existing agent session.
989
1002
  Neither a receipt nor a config write proves an existing session adopted new rules;
990
1003
  use the actual native session's supported acceptance path separately.
991
1004
 
992
- At session start, the hook authenticates and refreshes the profile. Prompt hooks
1005
+ At session start, the hook authenticates and refreshes the profile within a
1006
+ five-second bound; a refresh that does not finish is named in one line and the
1007
+ session uses its last verified profile. Prompt hooks
993
1008
  select complete skill instructions from that verified cache using explicit
994
1009
  `$skill` references, profile keywords, paths and always-required selections.
995
- A session retains its loaded selections; compaction restores loaded instructions,
996
- and subagents inherit the parent's selection. Instructions that exceed the
997
- context budget produce an explicit `skills load` command. A hook never executes
998
- a skill. Cached use is explicit and expires after 24 hours. When a session
1010
+ A keyword matches as a phrase (its words adjacent and in order); a selection
1011
+ without keywords matches its whole slug as a phrase, or a shorter run of its
1012
+ slug words that has two words of three or more letters and the slug's
1013
+ least-used word ("seating plan" for event-seating-plan, never "run of" for
1014
+ live-event-run-of-show); a one-word trigger shared by more than three
1015
+ selections selects nothing on its own; and a one-word slug counts as named
1016
+ only beside the word "skill". A prompt match scoring under half of the
1017
+ prompt's best match, and prompt matches tied at the last free slot, are
1018
+ offered as `skills load` commands instead of being injected or picked by name
1019
+ order. Weaker pointers are offered the same way, at most three and never
1020
+ injected: a multi-word keyword whose words all appear apart, one of them
1021
+ discriminating ("designs review" in "the designs app for review"), or a common
1022
+ one-word keyword; a tie that does not fit is left out. Managed prompt hooks are
1023
+ stricter than a direct `skills context` call: they inject an unnamed prompt
1024
+ match only for a phrase of two or more words, and offer anything weaker as a
1025
+ `skills load` command, so a `keywords: ["pdf"]` selection needs `$pdf`, "the pdf
1026
+ skill", a two-word keyword or `triggers.always` to arrive as a body.
1027
+ `SKILLS_HOOK_PROMPT_MIN_PHRASE_WORDS` can raise that length, never lower it.
1028
+ Sumi's plugin and Cursor's prompt hook discard a prompt call's output, so a
1029
+ pointer could not reach their models, and they keep the plain selection. Each
1030
+ `skills load` command a session is offered names that session and carries
1031
+ `--cache-first`, so it loads the pinned version from the verified cache the hook
1032
+ used, which works in a sandbox with no network. Once the cache can't serve it it
1033
+ loads from the Skills service. That happens when the pin was last verified over
1034
+ 24 hours ago, which is common for a subagent, since it inherits its parent's time
1035
+ and no hook renews its own pin. With no network as well, the load refuses and says
1036
+ so, and `skills sync` doesn't renew a session's pin. Like a body the hook delivers
1037
+ from the cache, a cached load doesn't ask the service whether the selection is
1038
+ still current.
1039
+
1040
+ A load is recorded on the session the command names, whoever runs it, so running
1041
+ another session's command marks that session as having loaded the skill, and its
1042
+ later prompts offer it no pointer. Where the session store can't be written or is
1043
+ full, as in a Codex sandbox, a load still returns its content and says it wasn't
1044
+ recorded, unless the bundle isn't cached and the cache can't be written either, in
1045
+ which case it refuses. Compaction won't restore an unrecorded skill and the session
1046
+ won't be told if it's retired. An agent or subagent with no way to run a command can't use a
1047
+ pointer.
1048
+
1049
+ A session retains its loaded selections; compaction restores the two most
1050
+ recently loaded instructions, followed by `skills load` commands for the next
1051
+ most recent. A subagent started by a managed hook is offered its parent's
1052
+ loaded skills as `skills load` commands, and gets a body at its start only for a
1053
+ skill that `triggers.always` or a path selects. Claude Code's and Codex's
1054
+ subagent start carries no prompt, so naming a skill in a subagent's brief doesn't
1055
+ deliver its body there. OpenCode's adapter does pass the subagent's first prompt,
1056
+ so there it also gets a body for a skill it names or matches by a phrase. A
1057
+ direct `skills context` call, and Sumi's and Cursor's hooks, give it its parent's
1058
+ most recent one as a body. A
1059
+ read-only prompt does not rewrite the session receipt or take its write lock
1060
+ (a damaged lock still refuses), and receipt writers wait up to two seconds for
1061
+ another live writer's lock before refusing; a lock another writer is
1062
+ publishing or releasing at that moment counts as held, not damaged. Every
1063
+ delivered body is recorded in the receipt: when only that write lost its lock
1064
+ race, skills the receipt already records are still delivered, and each newly
1065
+ read one is offered as its `skills load` command under one fixed
1066
+ `[SESSION_WRITE_BUSY]` line. A new subagent whose parent recorded a load or
1067
+ renewed its pin while the subagent resolved is resolved once more from the
1068
+ current parent pin. Managed hooks inject at most 24,000 instruction
1069
+ characters; instructions that exceed that or another context budget produce
1070
+ an explicit `skills load` command. A hook never executes
1071
+ a skill. Cached use is explicit and expires after 24 hours. Managed hooks renew
1072
+ session pins in a detached background worker (`docs/session-pin-renewal.md`),
1073
+ ahead of expiry for root sessions (a failed renewal ahead of expiry is named
1074
+ in one line while context comes from the still-valid pin); an expired pin
1075
+ waits at most three seconds for its renewal and delivers nothing until it
1076
+ commits. When a session
999
1077
  receipt expires, the hook authenticates the current profile. If every loaded
1000
1078
  selection still has identical metadata and bundle digest, it archives the old
1001
1079
  receipt and advances that session to the current profile under an exact receipt
@@ -1015,7 +1093,7 @@ that lock in its receipt and is never migrated automatically, whatever
1015
1093
  directory it later prompts from. A session without that record is not migrated
1016
1094
  while a lock sits in the prompt's working directory or any ancestor. A loaded
1017
1095
  skill whose lifecycle epoch rotated while its bytes stayed the same also keeps
1018
- the refusal. If the migration cannot finish within the four-second renewal window,
1096
+ the refusal. If the migration cannot finish within the renewal window,
1019
1097
  the hook reports `SESSION_RECONCILIATION_REQUIRED` with that reason and the next
1020
1098
  prompt retries. Turn this off station-wide with `skills config set
1021
1099
  sessionPinMigration off --global` (the key is refused without `--global`, and a
@@ -1543,6 +1621,54 @@ The operation is read-only. It reads the policy and the stored witness paths
1543
1621
  and directories. It writes no file, cache, selection pin or policy, and it does
1544
1622
  not start Claude or change native state.
1545
1623
 
1624
+ ### Disable only Claude context delivery hooks
1625
+
1626
+ `skills hook disable-claude-context` previews removal of exact Skills-owned
1627
+ `SessionStart`, `UserPromptSubmit` and `SubagentStart` registrations. It requires
1628
+ an explicit physical settings path, its exact SHA-256 and `0600` mode, the exact
1629
+ Skills executable and its physical byte digest, and the registered selection
1630
+ profile. It compares complete commands produced by Skills' own renderer, never
1631
+ a command substring. Unsupported near matches refuse. Duplicate JSON keys,
1632
+ aliases, unsafe paths, and changed target/command witnesses refuse too.
1633
+
1634
+ ```sh
1635
+ skills hook disable-claude-context --settings /absolute/native/settings.json \
1636
+ --expected-settings-sha256 <exact-settings-sha256> --expected-mode 0600 \
1637
+ --skills-command /absolute/bin/skills \
1638
+ --expected-command-sha256 <exact-command-sha256> \
1639
+ --selection-profile <exact-profile> --json
1640
+ ```
1641
+
1642
+ The default preview writes nothing. Add `--apply --preimage-dir <new-absolute-dir>`
1643
+ to apply. The preservation directory's parent must already exist. Apply creates
1644
+ an exclusive private directory and reads back the exact original before changing
1645
+ settings. An existing directory is never reused. The operation preserves all
1646
+ other settings and handlers, including `PreToolUse` native Skill enforcement,
1647
+ unrelated empty groups, permissions, policy, profiles and sessions. JSON spacing
1648
+ is reserialized, while unknown numeric spellings remain intact.
1649
+
1650
+ The result distinguishes `no-data` (an explicitly absent target, using `absent`
1651
+ for both expected hash and mode), `no-op` (a present file with no exact matches),
1652
+ `preview`, `applied`, and `ambiguous`. `plannedAfterSha256` describes the proposed
1653
+ bytes. `afterSha256` is unavailable until readback verifies an applied target.
1654
+ Apply uses a descriptor-held package lock and atomic file exchange, retaining
1655
+ both a private preimage and the displaced entry. Exchange is not compare-and-swap.
1656
+ A post-exchange race or failed verification returns `ambiguous`, exit 2,
1657
+ `mutationOccurred: true` and exact recovery paths. It never claims no write or
1658
+ blindly overwrites a concurrent edit during rollback. Failed staging and all
1659
+ preservation evidence remain for recovery.
1660
+
1661
+ This command makes no hosted request and needs no credential. It can run from
1662
+ an exact reviewed task-scoped CLI artifact without installing it as the shared
1663
+ Skills command. Its lock file remains in the target directory. Removing context
1664
+ hooks can stale enrolled settings witnesses that bind those hooks. The operation
1665
+ reports `settingsWitness: not-renewed` and does not refresh or relax them.
1666
+ `PreToolUse` enforcement can therefore still refuse on a stale witness. This is
1667
+ a context-delivery shutdown, not admission recovery or permission to reactivate
1668
+ hooks. Linux uses `renameat2(RENAME_EXCHANGE)` and macOS uses
1669
+ `renamex_np(RENAME_SWAP)`; unsupported exchange or filesystem behavior refuses.
1670
+
1671
+
1546
1672
  ## Profiles, station sync and rollback
1547
1673
 
1548
1674
  ```bash
@@ -2099,7 +2225,7 @@ on the exact entry, through `env -i` with an explicit environment allowlist:
2099
2225
  (`TERM`, `TERM_PROGRAM`, `TERM_PROGRAM_VERSION`, `COLORTERM`, `COLUMNS`, `LINES`),
2100
2226
  `NO_COLOR`, `FORCE_COLOR`, `CI`, `EDITOR`, `VISUAL`, `PAGER`, `SSH_AUTH_SOCK`,
2101
2227
  the server settings `HOST`, `PORT`, `NODE_ENV`, `AGENT_ID` and
2102
- `ECS_CONTAINER_METADATA_URI_V4`, the agent names `TERMINAL_CWD`, `CODEX_HOME`,
2228
+ `ECS_CONTAINER_METADATA_URI_V4`, the agent names `TERMINAL_CWD`, `CODEX_HOME`, `CLAUDE_CONFIG_DIR`,
2103
2229
  `HERMES_HOME` and `HERMES_ENABLE_PROJECT_PLUGINS`, and every name starting with
2104
2230
  `HASNA_`, `SKILLS_`, `SKILL_`, `MCP_`, `XDG_`, `LC_` or `AWS_`. Your `LC_ALL` passes
2105
2231
  through unchanged. Everything else never reaches the runtime, including `BUN_*`,
@@ -2107,7 +2233,7 @@ through unchanged. Everything else never reaches the runtime, including `BUN_*`,
2107
2233
  (`HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`). A `bunfig.toml`, `.env` or `tsconfig.json`
2108
2234
  in the directory you run a command from is never read.
2109
2235
 
2110
- New launchers use the V2 format with an explicit environment profile. The CLI and
2236
+ New launchers use the V3 format, preserving `CLAUDE_CONFIG_DIR`, with an explicit environment profile. The CLI and
2111
2237
  MCP entries use the client profile, which excludes `DATABASE_URL`,
2112
2238
  `HASNA_SKILLS_DATABASE_URL` and `SKILLS_DATABASE_URL` even when their prefixes are
2113
2239
  otherwise allowed. The API server, worker, maintenance and migration entries use
@@ -2124,10 +2250,10 @@ directory first. The receipt records the old and new launcher shape of every pat
2124
2250
  the backup keeps the exact previous launcher (symlink text or pinned bytes), and
2125
2251
  `--rollback` restores it byte for byte. Codex hook trust, the Claude settings
2126
2252
  projection and `skills self-update` read a managed pinned launcher as the exact
2127
- entry it runs and bind the launcher's own bytes as well. Existing V1 launchers
2128
- remain recognized in their exact original format. Receipts without launcher
2129
- format metadata restore V1 bytes; new receipts bind the V2 format and environment
2130
- profile. An upgrade does not prevent rollback to the prior V1 launcher.
2253
+ entry it runs and bind the launcher's own bytes as well. Existing V1 and V2 launchers
2254
+ remain recognized in their exact original formats. Receipts without launcher
2255
+ format metadata restore V1 bytes; new receipts bind the V3 format and environment
2256
+ profile. An upgrade preserves byte-exact rollback to a prior V1 or V2 launcher.
2131
2257
 
2132
2258
  An updater from before pinned launchers (0.10.48 and earlier) writes bare symlinks,
2133
2259
  including when it installs a version that has them, and an exact-version update to
@@ -3416,6 +3542,12 @@ signal refuses before calling the transport.
3416
3542
 
3417
3543
  Payload writers reject known native skill folders, physical aliases of the account's native roots, and configured home discovery roots (including OpenCode `skills.paths`) before creating directories. Malformed or unresolved native registrations fail closed and require the existing Skills discovery review. Changing the authoring data directory does not hide the account's native policy.
3418
3544
 
3545
+ `CODEX_HOME` and `CLAUDE_CONFIG_DIR` also exclude their selected native home and its current configured discovery roots. Relative Codex homes resolve from the caller's directory. Claude requires an absolute configuration directory. Native skills and plugin-cache subroots, Claude's synced-plugin and legacy-command subroots, and their physical targets remain excluded when those subroots are symlinks outside the selected home. Bounded metadata traversal also excludes readable descendant alias targets while allowing unrelated private authoring. The same traversal protects default homes with no override, or when the override equals or aliases the default home. Physical aliases and destinations containing an excluded root are refused too. Default and retained roots remain excluded when an override is selected. An override does not enroll a new native consumer or reuse another home's opaque-hook review. Unsupported custom Hermes homes fail closed even when the default Hermes directory is absent.
3546
+
3547
+ Authoring derives a read-only exclusion set from current supported discovery controls and unions it with every retained policy root. A stale full-file settings witness does not by itself block a safe portable destination. For example, ordinary Claude model/theme changes without opaque hooks, or a newly added OpenCode `skills.paths` directory, do not require enrollment or policy updates. Both the old and new custom roots remain forbidden destinations. Native loading and enrollment still verify their original witnesses strictly.
3548
+
3549
+ Unknown discovery controls, malformed or ambiguous registrations, unresolved aliases/runtimes and bounded-enumeration failures refuse before a payload write. Executable hooks whose roots cannot be enumerated still need their existing current source review. Typed Claude v5/Codex v7 settings witnesses and an already recorded narrowed witness can establish that review without a write. A legacy opaque hook registration whose full-file witness is stale and has no previously recorded narrowed proof remains unsupported. Authoring never manufactures that proof or enrolls the account. Opaque hooks also retain the existing reviewed executable/dependency source population and directory evidence: matching settings, `hooks.json`, or a manifest alone is insufficient. The authoring-only check reuses the native verifier's source, directory, semantic and retired-source predicates, exempting only the primary configuration already handled by the current bounded root pass. Missing executable closure evidence refuses. A filesystem-root exclusion such as OpenCode `skills.paths: ["/"]` excludes all descendants, including physical aliases.
3550
+
3419
3551
  Other authoring tools can use the same read-only guard from the package root:
3420
3552
 
3421
3553
  ```ts
@@ -3462,6 +3594,25 @@ refuses native discovery or unknown control changes, and changes policy only.
3462
3594
  After explicit migration, ordinary supported local MCP updates require no
3463
3595
  coordinated policy write.
3464
3596
 
3597
+ ### Native discovery drift is reported, not blocking
3598
+
3599
+ Live prompt, session, subagent and tool hooks no longer block on
3600
+ `NATIVE_SKILL_DRIFT`. The turn proceeds without Skills context, the agent shows
3601
+ one warning naming the change and the repair command, and the hook records a
3602
+ receipt in `<skills-data>/native-drift/<agent>.json`; `skills hook drift --json`
3603
+ lists them. Invoking a native payload skill instead of the `skills-cli` bridge
3604
+ is still denied, and so is invoking the bridge while the bridge itself is
3605
+ missing or modified; install, trust and migration still refuse drift.
3606
+
3607
+ `claude-settings-v5` and `codex-settings-v7` reviews bind only settings that can
3608
+ add, remove or redirect native skills, hooks or plugins (and, for Codex, every
3609
+ MCP server and instruction source), so a model switch, an "always allow" rule, a
3610
+ status line or Codex's folder trust and notices are not drift. Existing Claude
3611
+ and Codex reviews keep verifying through a narrowed-witness ledger the live hook
3612
+ records while they still match; a station that had already drifted, V6 and Sumi
3613
+ witnesses still need one fresh review. See
3614
+ [docs/plugin-admission.md](docs/plugin-admission.md#narrowed-discovery-reviews-claude-settings-v5-and-codex-settings-v7).
3615
+
3465
3616
  ### Reproduce a reviewed runtime dependency closure
3466
3617
 
3467
3618
  For an exact-version copyfile update, supply an owner-private absolute npm