All notable changes to structsense-skills. Versions follow semantic versioning.
The version: field in SKILL.md frontmatter is the source of truth; this file
records what changed between versions so you can tell which features your local
copy has.
- Mapping is mandatory and tool-only. The cascade no longer silently
skips alignment. Default cascade: local hybrid (
http://localhost:8000, verified at/docs) → BioPortal → ask user for an alternate URL → hard-stop with an actionable error. The skill no longer falls back to OLS by default (OLS lacks gene coverage); pass--allow-ols-fallbackto opt in. concept_mapping_provenance: "llm_knowledge"is forbidden in canonical output. Any item carrying it is automatically demoted tounmapped, withalignment_method: "validation_failed". The item itself is preserved (exhaustive extraction is not compromised); only the fabricated mapping is dropped.
- Per-ontology regex patterns for UBERON, CL, NCBITaxon, MONDO, DOID, HP,
CHEBI, DRON, BTO, OBI, MP, HGNC, NCBIGene, MGI, UniProt, PR, GO, EFO,
NIFSTD, CIDO, plus a permissive structural fallback for unknown
ontologies (
<NS>_<NUM>OWL IRIs, identifiers.org, semanticweb.org). - Accepts legitimate cross-ontology mappings (e.g. CIDO results that
reuse HP IRIs as synonyms) — the declared
ontologyfield does NOT have to match the IRI prefix. We only rejectllm_knowledgeprovenance and structurally-malformed IRIs. - Adds
result["validation"]withpassed/demotedcounts anddemoted_by_reasonbreakdown (llm_knowledge_rejected,malformed_iri,wrong_ontology_pattern,missing_ontology_id).
stats.totalsblock at the top of every result. Top-leveltotal_items,total_entity_mentions,total_key_term_mentions,total_resources,unique_entities,unique_key_terms. The human summary showsTOTAL ITEMS: …as the second line aftertask_type.stats.task_typeauto-inferred when missing — entities present →ner; resources →resource; activity/items →structured_extraction.alignment.by_methodno longer shows{missing: N}for items that haveconcept_mapping_provenanceset. The normalizer fillsalignment_methodfrom the provenance (tool→direct_tool_call,skipped→skipped).
connecting/claude-desktop.mdadded. Explains Claude Desktop's split execution model (chat UI on your machine, code interpreter in Anthropic's cloud sandbox), why yourlocalhost:8000is unreachable from a sandboxed code-interpreter call (/home/claude/work/...paths are the giveaway), and how to bridge via an MCP server configured inclaude_desktop_config.json.
Smoke-tested against the user's actual run (2331 entity mentions across 15 labels, 210 key terms, 922 tool-mapped + 1619 skipped). The new output:
totals.total_items: 2541(prominent at top)task_type: "ner"(wasnull)alignment.by_method: {direct_tool_call: 922, skipped: 1409, missing: 210}(was{missing: 2541})
- API schema bug fixed.
scripts/local_hybrid_map.pywas POSTing{terms: [...]}but the real/map/batchendpoint takes{text: [{text, context?}], max_results}. Verified against a live deployment. The client now supports either a flat list of strings or shaped dicts with optional per-termcontext. Also handles the real response shape (resultsis a dict keyed by input text, score isfinal_score). prompts/alignment-via-http.mdadded: a turnkey curl + jq pipeline for hitting/map/batchdirectly. Use this when in Claude Code (Bash available) but the Python client isn't loaded.SKILL.mdrule #10 strengthened: "you MUST probecurl ${MAPPER_URL}/docsbefore declaring the mapper unavailable." Plus a runtime-reachability table (Claude Code → yes; claude.ai web → no, needs MCP bridge; ChatGPT cloud → no, needs Action).
scripts/input_loader.py— PDF / CSV / TXT / MD ingestion. PDF chain: GROBID → PyMuPDF (fitz) → pdfminer.six. CLI writes a sibling<stem>.txtso subsequent NER stages have stable character offsets.scripts/task_detection.py— auto-detect task type (ner / resource / structured_extraction / relation_extraction / keyphrase_extraction / …) from a free-text description. Heuristic regex first; LLM fallback viallm_client.scripts/model_context.py— model context-window registry (~50 model families, longest-match wins) +estimate_payload_tokens+compute_downstream_chunk_sizefor sizing alignment/judge chunks programmatically.group_by_entity.unify_ontology_across_entities— when the same surface form gets different ontology IDs from different chunks/models (parallel extraction is the usual cause), unify on the best one (tool-mapped > llm_knowledge > unmapped). Runs automatically insideattach_grouped_views. Mentions are preserved; only the ontology fields are normalized.
paper_title/doiremoved from per-entity items. They now live ONCE at the top level undersource_metadata: { paper_title, doi, source_path }.paper_location(section / page / paragraph) stays per-entity because it varies per mention.source_modelprovenance added to every entity item (HF model id, orllm_ner:<llm_model>for the LLM extractor).entities_grouped[](andkey_terms_grouped[]) added: per-entity index collapsing raw mentions by canonical(entity.lower(), label). Each group hassource_models[],source_model_counts{},consensus_count,judge_score_max/avg/min, deduplicatedsentences[]with theirpaper_locations[], and slim per-occurrencementions[].statsblock always embedded: totals, label histogram, by_source_model histogram, alignment provenance, judge score buckets, per-stage timings.
- Post-processing normalizer (
scripts/normalize_result.py) added. Runs automatically before every save, and is also exposed as a CLI so legacy result files can be normalized in place. It lifts per-entitypaper_title/doiintosource_metadata, tags missingsource_model, attachesentities_grouped, and computesstats. Idempotent. - Mapper cascade: local hybrid (
http://localhost:8000, verify via/docs) → BioPortal → ask the user for an alternative URL → skip alignment. - HuggingFace NER ensemble (
scripts/ner_models.py): d4data, BC5CDR-chem, NCBI-disease, BioBERT-genetic, BENT-PubMedBERT family (Gene/Chemical/Disease/Anatomical/Cell-Type/Cell-Line/Organism/Bioprocess), Clinical-AI-Apollo, blaze999. Selectable via--ner-profile:biomedical_broad/cns_cells/pharmacology/genetic/clinical/minimal/all. - Final filename is
<input_stem>_final.jsonby default.
- Three variants: general, neuroscience, CNS-cells.
- Each ships with explicit EXHAUSTIVENESS rules ("extract every occurrence,
do not deduplicate by surface form") and explicit WRONG / RIGHT example
blocks for the
source_metadatashape. - Mask-recall pass (
prompts/mask-recall-pass.md) and mask-verify pass (prompts/mask-verify-pass.md) for boosting recall and detecting label errors.
connecting/claude-code.md— install as a Claude Code skill (~/.claude/skills/or.claude/skills/).connecting/claude-skills.md— publish as a hosted Anthropic Skill.connecting/custom-gpt.md— wire as an OpenAI Custom GPT (Instructions + Knowledge files + Actions).connecting/mcp-server.md— expose as an MCP server.
- Multi-stage pipeline pattern (extractor → alignment → judge → human feedback).
- Three NER variants and resource / structured-extraction prompts.
- Ontology mapping clients: BioPortal, OLS, local hybrid.
- JSON repair, span validator, chunking helpers.
- Reference pipeline driver (
scripts/pipeline.py).
- Initial skill scaffolding from the structsense pipeline patterns.