Gap Architecture
Gap Architecture
How Skillful Alhazen detects, tracks, and fixes schema gaps — the primary signal for knowledge graph evolution.
What is a schema gap?
A schema gap is when the agent tries to represent a concept, relationship, or entity type that has no place in the current TypeDB schema. This is not an execution failure — the skill ran, the agent understood the task, but the schema couldn’t express the result.
When the knowledge work outgrows the model, a schema gap is the signal.
Schema gaps are distinct from ordinary execution failures:
| Type | Symptom | Handler |
|---|---|---|
| Execution failure | Tool crash, API error, empty result | Standard error log + retry |
| Schema gap | TypeDB write error ([SYR1], [TYR01], [FEX1]…) or Claude identifies an unstorable concept |
PostToolUse hook → file-schema-gap → local fix |
Detection
1. Automatic (PostToolUse hook)
A PostToolUse hook scans tool output for TypeDB error codes. When one is found, it prints a [SCHEMA-GAP-HINT] message prompting the agent to file an issue immediately.
TypeDB error codes that indicate schema gaps:
[SYR1]— type not found (missing entity or relation definition)[TYR01]— invalid concept conversion[FEX1]— fetch expression error (e.g., trying to fetch an attribute from a relation)[INF2]— type label not found[INF11]— type-inference failure across a constraint
2. Manual (agent recognizes it)
During sensemaking, the agent realizes a concept can’t be stored. For example: a disease entity that can’t play aboutness:subject because the aboutness relation isn’t defined in that skill’s schema. The agent is instructed to file immediately rather than waiting.
Filing a Gap
uv run python local_resources/skilllog/skill_logger.py file-schema-gap \
--skill <skill-name> \
--concept "<concept the agent tried to represent>" \
--missing "<which TypeDB entity/relation/attribute is absent>" \
--suggested "<proposed TypeQL snippet, or 'unknown'>" \
[--dry-run]
This command:
- Routes the issue to the correct GitHub repo (see Routing below)
- Checks for duplicate open
gap:openissues (use--skip-dedupto override) - Builds a structured issue body
- Runs
gh issue create --label gap:open
Issue body structure:
## What was missing
<concept description>
## What broke
<missing TypeDB element>
## Suggested fix
<TypeQL snippet>
## Generalizable pattern
<broader lesson>
---
**Skill:** <name>
**Phase:** entity-schema | source-schema | derivation | analysis
**Severity:** minor | moderate | critical
Repo routing
Gap issues are routed based on skill name:
- Core skills (
typedb-notebook,web-search,curation-skill-builder,tech-recon) →GullyBurns/skillful-alhazen - External skills (
jobhunt,scientific-literature, etc.) →sciknow-io/alhazen-skill-examples - Custom mappings in
SKILL_REPO_MAPinskill_logger.pyfor skills in non-standard repos (e.g.,dismech→sciknow-io/alhazen-skill-dismech)
GitHub Issue Lifecycle
Labels
| Label | Meaning |
|---|---|
gap:open |
Issue filed, no fix started |
gap:in-progress |
Local branch created, fix underway |
gap:pr-open |
Draft PR created, awaiting human review |
severity:minor / moderate / critical |
Impact level |
phase:entity-schema / source-schema / derivation / analysis |
Skill lifecycle phase |
skill:<name> |
Which skill owns the gap |
GitHub Actions workflows
Three workflows run automatically (no code execution — API calls only):
gap-triage.yml — triggers on new issue. If the body contains ## What was missing, it parses **Severity:**, **Phase:**, **Skill:** from the body, applies matching labels, adds gap:open, and posts a comment with the local fix commands.
weekly-gap-review.yml — runs every Monday at 9 AM. Fetches all gap:open issues, groups by severity, creates a summary issue. Critical gaps open more than 7 days receive a reminder comment.
claude-guidance.yml — triggers when gap:open is labeled. Posts a structured comment with the exact CLI commands for the local fix workflow (see below).
Local Fix Workflow
Schema changes cannot be validated on GitHub Actions runners (no running TypeDB instance). All fixes happen locally.
Step 1: Start the fix
uv run python local_resources/skilllog/skill_logger.py fix-gap \
--issue <N> \
--repo <owner/repo>
Creates branch fix/gap-N-<slug>, labels the issue gap:in-progress (removes gap:open), posts a “Fix started” comment.
Step 2: Implement and validate
Edit schema.tql and the skill’s Python scripts. Validate:
make db-init # confirms schema loads cleanly
uv run python .claude/skills/<skill>/<skill>.py <command> [args] # smoke test
Post implementation decisions as comments on the GitHub issue — these get pulled into the PR body automatically.
Step 3: Open a draft PR
uv run python local_resources/skilllog/skill_logger.py submit-gap-pr \
--issue <N> \
--repo <owner/repo> \
--decisions "brief description of key implementation decisions"
This command:
- Confirms the branch has commits ahead of
main(aborts if not) - Runs
uv run pytestif a test suite exists (aborts if tests fail) - Fetches implementation decision comments from the issue
- Builds a PR title:
fix(<skill>): <slug> (closes #N) - Builds a PR body with:
Closes #N, summary, decisions, test status - Pushes the branch and creates a draft PR via
gh pr create --draft - Posts the PR URL as an issue comment
- Labels the issue
gap:pr-open
Step 4: Human merge
The PR is created as a draft. The human:
- Reviews the diff on GitHub
- Promotes from draft to ready
- Merges
This is the only step that cannot be automated — it is intentionally a human gate.
Scaffolding Gap Infrastructure in a New Repo
uv run python skills/curation-skill-builder/skill_builder.py \
scaffold-improvement-loop \
--repo <owner/repo> \
--skill <skill-name>
Creates via GitHub API (no local clone required):
.github/ISSUE_TEMPLATE/skill-gap.md.github/workflows/gap-triage.yml.github/workflows/weekly-gap-review.yml.github/workflows/claude-guidance.yml
Design Principles
Schema gaps are signal, not noise. Filing the issue is the right response — not silently working around the gap in Python.
Local execution only. Schema changes require a running TypeDB instance. GitHub Actions runners can’t do this. GitHub is used for tracking and review, not execution.
Draft PRs, human merges. submit-gap-pr always creates a draft. The merge gate is always human.
Deduplication by default. file-schema-gap checks for existing open issues with the same concept before filing.