mirror of
https://github.com/alirezarezvani/claude-skills.git
synced 2026-08-28 04:24:58 +00:00
fix(agent-memory): address automated review; harden the session-id fallback
Five of six findings were real. Verified each against the code rather than taking them at face value; one was wrong and is noted below. 1. validate_examples.py carried a stale header from the spec-only phase -- "PARKED AS AN ASSET (deliberately not .py yet)... ON IMPLEMENTATION: rename to skills/agent-memory/scripts/validate_examples.py". The file is already at exactly that path. Rewritten to describe what it now is, keeping the substantive part: why it exists, the seven check families, why it compares the doc's algorithm by source text rather than exec()-ing a code fence, and that nothing runs it automatically. 2. Missing shebang -- added. The same finding also claimed mode 100644; that half is wrong, `git ls-files -s` shows 100755 for all five scripts. 3. hooks.json's description still opened "CONTRACT ONLY -- the referenced scripts are not yet implemented", true of none of them now. Trimmed to keep only the UserPromptSubmit provisionality (9.5 is genuinely still open) and to record the measured latency alongside it. 4. The session-id fallback was the finding worth the most. `session_id` is the right key -- engineering/security-guidance's shipped hook reads the same one -- but the fallback was the CONSTANT "unknown-session", and sessions dedupe by value. Had the key ever been absent, every session would collapse onto one id, len(set(sessions)) would plateau at 1, and every claim would cap at L1 forever with no error anywhere. Now falls back to the transcript's own basename, which IS the session id. Verified end-to-end with session_id omitted from the payload: the atom records the real session UUID. 5. Dead `now` parameter on _eligible_l1 -- removed. 6. marketplace.json metadata still said 104 agents / 120 slash commands, pre-existing drift on a line this branch already edits. Trued up to 110/130. Re-verified after: 69 checks 0 failures, SKILL.md 6/6 PASS, both blocking gates still fire by name, check_paths 620 files clean, counters and plugin-json pass, all 5 scripts --help, all 3 hooks parse. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
This commit is contained in:
parent
2e59fe9873
commit
9f2c50e285
5 changed files with 39 additions and 31 deletions
|
|
@ -8,7 +8,7 @@
|
|||
"homepage": "https://github.com/alirezarezvani/claude-skills",
|
||||
"repository": "https://github.com/alirezarezvani/claude-skills",
|
||||
"metadata": {
|
||||
"description": "378 production-ready skills across 20 domains (engineering, engineering-core, marketing, product, c-level, c-level-agents, compliance-os, project management, RA/QM, business growth, finance, productivity, marketing top-level, research, research-ops, business-operations, commercial, markdown-html, loop-library, plus standards). 703 Python tools, 820 reference guides, 104 agents (cs-* + personas), 120 slash commands across 95 marketplace plugins. v2.11.2 vendors engineering/skillopt-sleep — a verbatim copy of microsoft/SkillOpt's stdlib-only skillopt_sleep engine + Claude Code plugin surface, giving a local agent a nightly gated self-improvement cycle (read-only session harvest -> mine -> offline replay -> held-out-gated CLAUDE.md/SKILL.md edits -> staged for explicit /skillopt-sleep adopt). productivity/fable-goal (unreleased, post-v2.11.1) converts a rambling description of a desired outcome into one polished /goal prompt for a fresh autonomous session. v2.11.1 turns product-team and project-management into agent-harness domains: fork-orchestrators with deterministic goal routers, a Jira MCP snapshot bridge (Kanban flow metrics + Monte Carlo forecasting), a delegation-governance loop gate, a continuous-discovery cadence tracker, and an Opportunity Solution Tree linter, with /cs:pm and /cs:product command families. v2.10.3 completes the markdown-html domain with md-slides — slide-deck converter (arrow-key / Space / PgDn / Home/End / P keyboard navigation + presenter mode with split-view clock + speaker notes + next-slide preview + URL-hash deep linking like #3 for direct slide jumps + @media print page-per-slide for browser-native PDF export). Reuses md-document's markdown parser; vanilla JS only (no framework runtime); Prism.js opt-in via --syntax. Joins md-review (v2.10.2 code-review converter), md-document (v2.10.1 long-form converter), and the v2.10.0 foundation (orchestrator + design-system). Compatible with Claude Code, Codex CLI, Gemini CLI, Cursor, OpenClaw, Hermes Agent, Mistral Vibe, and 5 more coding agents.",
|
||||
"description": "378 production-ready skills across 20 domains (engineering, engineering-core, marketing, product, c-level, c-level-agents, compliance-os, project management, RA/QM, business growth, finance, productivity, marketing top-level, research, research-ops, business-operations, commercial, markdown-html, loop-library, plus standards). 703 Python tools, 820 reference guides, 110 agents (cs-* + personas), 130 slash commands across 95 marketplace plugins. v2.11.2 vendors engineering/skillopt-sleep — a verbatim copy of microsoft/SkillOpt's stdlib-only skillopt_sleep engine + Claude Code plugin surface, giving a local agent a nightly gated self-improvement cycle (read-only session harvest -> mine -> offline replay -> held-out-gated CLAUDE.md/SKILL.md edits -> staged for explicit /skillopt-sleep adopt). productivity/fable-goal (unreleased, post-v2.11.1) converts a rambling description of a desired outcome into one polished /goal prompt for a fresh autonomous session. v2.11.1 turns product-team and project-management into agent-harness domains: fork-orchestrators with deterministic goal routers, a Jira MCP snapshot bridge (Kanban flow metrics + Monte Carlo forecasting), a delegation-governance loop gate, a continuous-discovery cadence tracker, and an Opportunity Solution Tree linter, with /cs:pm and /cs:product command families. v2.10.3 completes the markdown-html domain with md-slides — slide-deck converter (arrow-key / Space / PgDn / Home/End / P keyboard navigation + presenter mode with split-view clock + speaker notes + next-slide preview + URL-hash deep linking like #3 for direct slide jumps + @media print page-per-slide for browser-native PDF export). Reuses md-document's markdown parser; vanilla JS only (no framework runtime); Prism.js opt-in via --syntax. Joins md-review (v2.10.2 code-review converter), md-document (v2.10.1 long-form converter), and the v2.10.0 foundation (orchestrator + design-system). Compatible with Claude Code, Codex CLI, Gemini CLI, Cursor, OpenClaw, Hermes Agent, Mistral Vibe, and 5 more coding agents.",
|
||||
"version": "2.11.2"
|
||||
},
|
||||
"plugins": [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"description": "CONTRACT ONLY — the referenced scripts are not yet implemented (see ../DESIGN.md). PROVISIONAL ENTRY: the UserPromptSubmit hook below is NOT a settled part of the design. DESIGN.md section 9.5 is an open decision whose option (c) is to drop this hook entirely, because its 100ms recall budget is dominated by python interpreter cold-start rather than by any work the script does. This file listing the hook is a contract for the shape it would take IF it survives that decision, not evidence the decision was made — read on its own, a hooks.json says \"these three hooks exist\", which is exactly the wrong impression here. SessionStart and SessionEnd are not provisional. Three hooks implementing the L0-L3 memory tiers. SessionStart injects L3 (global persona) + L2 (current project context). UserPromptSubmit recalls relevant L1 atoms. SessionEnd asynchronously captures L0 into L1 and stages promotions for human adoption. Every hook fails open (exit 0, no memory) and never blocks. Disable individually with AGENT_MEMORY_SESSIONSTART=0, AGENT_MEMORY_USERPROMPTSUBMIT=0, AGENT_MEMORY_SESSIONEND=0. NOTE ON THE RECALL TIMEOUT: the hook 'timeout' field below is in SECONDS and 1 is its floor, so it is only a backstop against a wedged process. The real requirement is the 100ms internal self-budget that user_prompt_submit.py must enforce against its own monotonic clock, returning whatever it has when the budget expires. See DESIGN.md section 5.2 — finishing under 1s does NOT satisfy the spec, and section 9.5 tracks whether 100ms is achievable at all given python interpreter cold-start.",
|
||||
"description": "Three hooks implementing the L0-L3 memory tiers. SessionStart injects L3 (global persona) + L2 (current project context). UserPromptSubmit recalls relevant L1 atoms. SessionEnd asynchronously captures L0 into L1, detects contradictions, and stages promotions for human adoption. PROVISIONAL ENTRY: the UserPromptSubmit hook is not a settled part of the design. DESIGN.md section 9.5 is an open decision whose option (c) is to drop it entirely, because its 100ms recall budget is dominated by python interpreter cold-start rather than by any work the script does. Measured on the implementation machine: spawn-to-exit p50 29ms / p95 31ms / max 35ms, of which the scoring pass over 500 atoms is 2-3ms -- so the budget IS met there, but one machine is not a portability claim and the decision stays open. SessionStart and SessionEnd are not provisional. Every hook fails open (exit 0, no memory) and never blocks. Disable individually with AGENT_MEMORY_SESSIONSTART=0, AGENT_MEMORY_USERPROMPTSUBMIT=0, AGENT_MEMORY_SESSIONEND=0. NOTE ON THE RECALL TIMEOUT: the hook 'timeout' field below is in SECONDS and 1 is its floor, so it is only a backstop against a wedged process. The real requirement is the 100ms internal self-budget that user_prompt_submit.py enforces against its own monotonic clock, returning whatever it has when the budget expires. See DESIGN.md section 5.2 -- finishing under 1s does NOT satisfy the spec.",
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,7 +53,15 @@ def main():
|
|||
|
||||
cwd = payload.get("cwd") or os.getcwd()
|
||||
project = os.path.basename(os.path.abspath(cwd))
|
||||
session = payload.get("session_id") or "unknown-session"
|
||||
# A CONSTANT fallback here would be a silent, permanent bug. Sessions
|
||||
# are deduped by value (5.3), so if `session_id` were ever absent,
|
||||
# every session would collapse onto one id, `len(set(sessions))` would
|
||||
# plateau at 1, and EVERY claim would be capped at L1 forever with no
|
||||
# error anywhere -- the gates need 2-3 distinct sessions. So fall back
|
||||
# to the transcript's own basename, which IS the session: Claude Code
|
||||
# names each transcript for its session id.
|
||||
session = payload.get("session_id") or os.path.splitext(
|
||||
os.path.basename(transcript))[0] or "unknown-session"
|
||||
store = core.AtomStore(os.path.join(cwd, ".memory"))
|
||||
|
||||
new_atoms = extract.extract(transcript, project, session)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|||
import memory_core as core # noqa: E402
|
||||
|
||||
|
||||
def _eligible_l1(atom, atoms, now):
|
||||
def _eligible_l1(atom, atoms):
|
||||
"""Returns (ok, reason). reason names the blocking gate when not ok."""
|
||||
if atom["tier"] != "L1":
|
||||
return False, "not-L1"
|
||||
|
|
@ -59,7 +59,7 @@ def promote_l1_to_l2(atoms, now=None):
|
|||
for a in atoms:
|
||||
if a["tier"] != "L1":
|
||||
continue
|
||||
ok, why = _eligible_l1(a, atoms, now)
|
||||
ok, why = _eligible_l1(a, atoms)
|
||||
if not ok:
|
||||
if why != "not-L1":
|
||||
blocked.append((a, why))
|
||||
|
|
|
|||
|
|
@ -1,37 +1,37 @@
|
|||
#!/usr/bin/env python3
|
||||
# ---------------------------------------------------------------------------
|
||||
# validate_examples.py — SOURCE, PARKED AS AN ASSET (deliberately not .py yet)
|
||||
# validate_examples.py — the drift gate for DESIGN.md, memory_schema.json, and
|
||||
# the worked examples they share.
|
||||
#
|
||||
# WHY THIS IS A .txt: this PR is spec-only. A .py here would be counted by
|
||||
# scripts/derive_counters.py (verified: python_tools 663 -> 664) and would be a
|
||||
# counted "tool" belonging to no plugin, in a folder that deliberately has no
|
||||
# SKILL.md. Parking the source preserves it without moving counters or
|
||||
# contradicting the Status line.
|
||||
# WHY IT EXISTS: across this design's review, drift between DESIGN.md, the
|
||||
# schema, and the fixtures was the DOMINANT defect class — required-field
|
||||
# drift, a tier the examples never exercised, hashes that stopped reproducing,
|
||||
# headings inserted out of order, a confidence value that contradicted its own
|
||||
# lifecycle narrative. Every one was found by a check like the ones below.
|
||||
# Those checks had lived only in throwaway shell heredocs, so they died with
|
||||
# the session that wrote them. This file is where they live now.
|
||||
#
|
||||
# WHY IT EXISTS AT ALL: across this spec's review, drift between DESIGN.md, the
|
||||
# schema, and the fixtures was the DOMINANT defect class — required-field drift,
|
||||
# a tier the examples never exercised, hashes that stopped reproducing, headings
|
||||
# inserted out of order, a confidence value that contradicted its own lifecycle
|
||||
# narrative. Every one was found by a check like the ones below. Those checks
|
||||
# have so far lived only in throwaway shell heredocs, so they die with the
|
||||
# session that wrote them. That is the actual gap a reviewer named, and this
|
||||
# file closes it.
|
||||
# WHAT IT GUARDS, in seven families: schema conformance · the tier-dependent
|
||||
# back-pointer form · reproduction of the ids DESIGN.md publishes, from the
|
||||
# doc's own normalize() algorithm · confidence monotonicity and gate
|
||||
# compliance · document structure and links · prose claims that must match
|
||||
# measured reality · lifecycle coherence across a multi-tier id group.
|
||||
#
|
||||
# ON IMPLEMENTATION: rename to
|
||||
# skills/agent-memory/scripts/validate_examples.py
|
||||
# (chmod +x, argparse --help/--json per repo CLI convention), count it in the
|
||||
# tools delta, and wire it into CI. It is the FIRST file the implementation PR
|
||||
# should land — before memory_extract.py — because everything else is written
|
||||
# against the contract it guards.
|
||||
# It compares the doc's published algorithm to this file's implementation by
|
||||
# SOURCE TEXT, deliberately not by exec()-ing the doc's fenced block. That
|
||||
# earlier approach made "whoever can edit a code fence" equal to "whoever can
|
||||
# run arbitrary code" — a real vector the moment this file is wired into
|
||||
# pull_request-triggered CI.
|
||||
#
|
||||
# REVERSAL CONDITION: if the maintainer rules that a spec-stage folder may carry
|
||||
# tooling, this becomes a .py immediately; nothing else about the PR changes
|
||||
# except three counter files.
|
||||
# NOT WIRED INTO CI. Nothing runs it automatically; DESIGN.md 10.1 carries the
|
||||
# exact workflow step for whoever wants it. Run it by hand before any edit to
|
||||
# this folder lands.
|
||||
#
|
||||
# stdlib only. No jsonschema (not available repo-wide) — this is a partial
|
||||
# validator covering exactly this file's own failure modes, not a general
|
||||
# validator covering exactly this design's own failure modes, not a general
|
||||
# JSON Schema implementation. That narrowness is deliberate: a general
|
||||
# validator would be a dependency, and the four allOf branches here are the
|
||||
# only ones that have ever actually drifted.
|
||||
# validator would be a dependency, and the allOf branches here are the only
|
||||
# ones that have ever actually drifted.
|
||||
# ---------------------------------------------------------------------------
|
||||
import hashlib
|
||||
import inspect
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue