Commit Graph

22 Commits

Author SHA1 Message Date
Maciej Lisiewski
4278b6aa24 ci: RUF013, RUF015 2026-10-08 21:29:48 +02:00
Maciej Lisiewski
d76cce4f11 ci: apply all automatic linter fixes available 2026-10-08 17:22:54 +02:00
teknium1
64ad33e32d refactor: remove Skill Sync (hermes sync) and the org skill mirror from core
Skill Sync only worked against a Nous Portal sync plane that was never made
publicly accessible, so no install has ever used it. We don't want it in core
right now, so this deletes it outright instead of moving it behind a plugin
hook surface nobody needs yet:

- `hermes sync` command, `tools/skills_sync_client*.py` and their tests
- the personal pull ticks (gateway housekeeping, classic CLI startup,
  `hermes serve` maintenance) and the debounced post-write push
- the per-skill `sync` usage flag (`set_sync` / `is_sync_enabled`)
- the `skills/_org/<org_id>/` mirror: index gating on `.active_org`, the
  `[org-shared]` / name-collision labels, the org provenance header and
  `org_provenance` field on skill_view, the org delete guard and the
  auto-propose `org_sharing` note on skill_manage

The code is preserved in the private NousResearch/hermes-skill-sync repo if
the feature comes back.
2026-10-03 23:05:48 -07:00
kshitijk4poor
4638864a74 fix(skills): batch rollback undoes every file it wrote into an adopted dir
The pre-existed branch of _restore_snapshot unlinked only SKILL.md, so a batch
[create gamma (adopting an empty leftover), write_file gamma references/a.md,
failing op] left references/a.md behind while reporting "all touched skills
rolled back" — and the next create was refused as occupied, wedging the user
until they hand-deleted the dir. The batch already records each applied op's
name/file_path; hand those to the rollback so it unlinks exactly what the batch
wrote and rmdir()s the emptied dirs up to the skill dir. rmdir() fails on
anything else, so a file that landed out-of-band still survives.

One ownership rule for an adopted empty dir on both paths: the single-op create
also always rmdir()s after a blocked scan instead of tracking a created_dir flag
(rmdir removes only an empty dir, so the flag added nothing but a second rule).
create_targets loses its never-used default; _create_skill reuses
mkdir_under_hermes_home for the parent instead of inlining its assert + mkdir.
2026-09-24 16:49:18 +05:30
kshitijk4poor
85ac36f2ec fix(skills): validate a batch create's category before the snapshot
_skill_manage_batch resolved every create op's target dir (base / category / name)
before anything checked the category, so a non-string category raised TypeError
out of skill_manage instead of the JSON error the single-op path returns — and it
did so after mkdtemp, leaking the skill_batch_ snapshot dir. Reject it in
_validate_batch_ops with the same _validate_category the single-op path uses, so
the batch fails pre-effect like every other shape error.
2026-09-24 16:49:18 +05:30
kshitijk4poor
fb4dbf77fc fix(skills): batch rollback never rmtree()s a dir that pre-dated the batch
_snapshot_skills only sees a SKILL.md, so an empty pre-existing directory that
create adopts left snap=None and a later op failure rmtree()'d the whole dir,
including anything dropped into it mid-batch (ehz0ah's review repro on #120437).
Record for each create target whether the dir already existed; on rollback undo
only the SKILL.md the batch wrote and rmdir if that leaves it empty, mirroring the
single-create path which rmdir()s only a dir it made.
2026-09-24 16:49:18 +05:30
kshitijk4poor
54a867a6e9 fix(skill_manage): batch success rows carry the linter findings and org-sharing note
Since operations[] became the only call shape (#97295) the batch's success
path rebuilt each row as {name, action, file_path, success} and dropped every
advisory key the per-op handler attached — lint_warnings/lint_hint from the
create linter and the org_sharing note. The model never saw a finding.
Carry those keys onto the row, mirroring what the failure path already does
for teaching payloads.
2026-09-22 12:52:49 +05:30
teknium1
0bd85d314c fix(skills): keep absorbed_into in the delete shape; decide every patch shape miss pre-effect
The per-action schema made the delete branch `additionalProperties: false`
with no `absorbed_into`, so a schema-validating or grammar-constrained
backend could no longer emit the curator's consolidation delete and
`_curator_consolidation_delete_guard` fail-closed every consolidation.
Advertise `absorbed_into` on the delete branch and cover the batch path
that forwards it to the guard.

Also fold the two remaining patch shape checks (missing new_string,
content mixed with old_string/new_string) into `_op_shape_error`, so a
batch rejects them before applying any sibling instead of creating op[0]
and rolling it back. Drop the stale `edit` vocabulary from skills.md:440
and the curator prompt, and move the schema-diet test helpers above the
`__main__` guard.
2026-09-17 08:47:01 -07:00
teknium1
75a0649a18 fix(skills): skill_manage advertises one shape per action; a misfiled text slot fails before any op applies
The operations[] item schema was one flat object with four coexisting text
slots (content / new_string / file_content / file_path). A 27B local model
that had just used write_file's file_content kept emitting it on create and
patch ops; the call validated against the advertised schema, the handler
failed on "content is required", and the whole batch rolled back — eight
identical retries until the tool-loop guardrail tripped (#112677).

- items is now an anyOf of self-contained per-action op objects (create,
  patch targeted, patch full-rewrite, write_file, remove_file, delete), each
  with additionalProperties: false. The wire shape of a correct call is
  unchanged (still a flat op with name/action/...), so transcripts, staging
  and replay are untouched; grammar-constrained backends can no longer emit
  another action's slot, and schema-validating providers reject it up front.
  Nested (non-top-level) anyOf survives every sanitizer (schema_sanitizer,
  Gemini legacy translator). Cost: parameters JSON 1352 -> 2414 bytes.
- _validate_batch_ops runs the per-op argument-shape check (_op_shape_error)
  before any op is applied, so a misfiled op[1] no longer applies op[0] and
  then rolls the batch back; the error carries the same misplaced-key hint.
- The hint is attached to argument-shape misses only: a patch whose real
  problem is an unmatched old_string is no longer told to "move that text to
  'content' (full rewrite)", the escape the patch error itself warns against.
- Shape tables (_REQUIRED_ARGS, text-slot maps, _misplaced_text_hint,
  _op_shape_error) move out of the facade into skill_manager_batch.py, the
  op-validation sibling; _patch_skill shares the old_string guidance text.
- Docs: skills.md Actions table states the one-slot-per-action contract.
2026-09-17 08:47:01 -07:00
teknium1
273986f88f fix(skills): route the skill_manage lock through the existing skill_usage lock helper
Slim follow-up to the cherry-picked #111585 (@KoNit-K):

- tools/skill_usage.py: generalize the usage ledger's `_usage_file_lock()` into
  `skill_file_lock(lock_path)` — same fcntl/msvcrt idiom, now thread-re-entrant
  via a per-thread held set (flock is not re-entrant across separate fds; a
  ContextVar would leak "held" into copy_context() timer threads).
- tools/skill_manager_tool.py: drop the third fcntl/msvcrt copy, hashlib and the
  ContextVar; the per-skill lock is `<skills>/.locks/<skill-dir-name>.lock`
  (readable, outside the skill dir so delete/recreate cannot unlink it under a
  waiting writer). Batch locks sort by lock PATH, not name, so two batches
  naming the same skills in different forms cannot deadlock.
- tools/skill_manager_batch.py: plain `with` around snapshot -> commit/rollback
  instead of manual __enter__/__exit__ bookkeeping.
- tests: trimmed to two invariants — the two-writer lost-update test on
  SKILL.md (from #111585) and a re-entrancy/exclusivity test on the helper.
  Dropped: the edit/write_file/remove_file parametrization (same dispatcher
  path as patch) and the category-dir cleanup test (lock files never lived in
  category dirs here).
2026-09-15 19:03:33 -07:00
KoNit-K
0b8b000ce9 fix(skills): serialize skill mutations 2026-09-15 19:03:33 -07:00
Teknium
e83816a4d1 review-fix(comments): restore lost #NNNN rationale comments across non-test source (mechanical sweep, condensed, code unchanged)
For each issue anchor present in BASE 63279301bc non-test .py and absent on HEAD, the BASE comment/docstring block was re-attached at the HEAD location of the code it explained (matched by the distinctive code line / enclosing def). Sentences already covered by an existing HEAD comment were deduped; the issue number always survives. Insert-only: no code lines changed.
2026-09-03 09:44:26 -07:00
Teknium
e6048ff6aa refactor(tools): skill_manage/ledger — shared identifier check, chainable result decorators, ledger read/filter fold 2026-09-03 01:30:26 -07:00
Teknium
370c6a2456 refactor(tools): skill_manage — dispatch default for unknown action, simpler ledger read, squeeze body blanks 2026-09-03 01:26:03 -07:00
Teknium
4ba77a6c13 refactor(tools): skill_manage — shared missing-arg predicates, compact category validation and comments 2026-09-03 01:23:09 -07:00
Teknium
eeb86e4b6f refactor(tools): skill_manage — fold gate/flat-op plumbing, shared root/pin/org helpers in guards, ledger tarball lookup inline; compact docstrings 2026-09-03 01:17:57 -07:00
Teknium
d9d25c89ba refactor(tools): unify skill_manage guard/ledger boilerplate; compact batch + ledger helpers 2026-09-03 01:06:07 -07:00
Teknium
ce992963a2 refactor(tools): skill ledger/batch — inline one-use helpers, drop section banners 2026-09-02 23:10:14 -07:00
Teknium
a861976519 refactor(tools): skill guards/tool — is_relative_to collapses, string reflow 2026-09-02 23:03:24 -07:00
Teknium
b187d4e547 refactor(tools): skill linter checks as generators, skill_manage arg-shape table, suppress() collapses 2026-09-02 22:43:10 -07:00
Teknium
71dadfeb99 refactor(tools): trim skill_manage stack — dead linter CLI/format helpers, merged path resolvers, compact layout 2026-09-02 22:23:24 -07:00
Teknium
7c1ec19d4a refactor(tools/skills): split skills_hub into per-source modules; extract skill_manager guards/batch, skills_tool dedup/plugin/setup; compact skill_usage, skills_guard 2026-09-02 14:45:15 -07:00