Skip to content
Back to skills

Edit Ontology

ASecurity

Change Garura''s product ontology — its kinds, their links and their rules — one need at a time, with the product owner. Opens its own change (start-change), has the product-os-keeper agent run the author-product-ontology skill stage by stage, and stops for the product owner''s typed yes at three checkpoints: the questions the ontology must answer, the kinds, and the links and rules. Then it writes the ontology, runs its check until it reads valid, checks that only the needed kinds changed, t...

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
toolspythongobashgit

Security analysis

A100/100

Pro scans all 10 files and shows the line behind each finding

Scanned November 7, 2026

npx -y skills add intent-driven-ai/garura --skill edit-ontology --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Edit Ontology?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Edit Ontology
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/intent-driven-ai-edit-ontology/badge)](https://www.skillsdirectory.com/skills/intent-driven-ai-edit-ontology)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: edit-ontology
position: both
description: 'Change Garura''s product ontology — its kinds, their links and their rules — one need at a time, with the product owner. Opens its own change (start-change), has the product-os-keeper agent run the author-product-ontology skill stage by stage, and stops for the product owner''s typed yes at three checkpoints: the questions the ontology must answer, the kinds, and the links and rules. Then it writes the ontology, runs its check until it reads valid, checks that only the needed kinds changed, that the version is up by one with one log line, and that no real name appears, and lands the change through commit-change, propose-change, check-change and merge-change — on the plan''s branch when the issue is in a plan. The only way to run the ontology skill. Use when the product model needs a new kind, or a kind, link or rule changed.'
user-invocable: true
---

# edit-ontology

Change Garura's **product ontology** — the agreed map of the kinds of things a product is
made of, their links and their rules (`core/components/memory/standards/schemas/product-os/ontology.md`)
— one need at a time. The product owner decides at three checkpoints; a script decides
whether the result is valid; the change lands through the change plays.

This play is the only way to run the `author-product-ontology` skill. A person never runs
the skill directly (C8).

**Pipeline position: both.** The D2 rule prepends `start-change` and appends
`commit-change → propose-change → check-change → merge-change`. When the issue sits in a
plan, start-change cuts the plan's sub-branch and merge-change lands on the plan's branch.

## Compiled From

This play was compiled from the edit-ontology ICE (`reference/ice.md`) by create-play
(#777). Intent defines constraints (C1–C8) and failure conditions (F1–F8); the expectation
defines success scenarios (S1–S5), a Done means (D1–D4, baked to `stop-condition.yaml`), and
one recovery entry per failure condition. To modify this play, update `reference/ice.md`
and recompile with edit-play.
Do NOT edit this file manually — it is a compiled artifact.

## Role

You are the orchestrator. You own the step order and the three checkpoints. You hand the
ontology work — reading the sources, drafting the questions, the kinds, the properties,
links and rules, the example, and writing the ontology — to the `product-os-keeper` agent,
which runs the `author-product-ontology` skill one stage at a time, through a JSON contract
over files on disk. You run the mechanical work through bundled scripts: recording each
answer (`record_checkpoint.py`), the ontology check (`check_ontology.py`), the change check
(`check_ontology_change.py`) and the stop condition. You never write the ontology yourself,
and you never record an answer the product owner did not type.

**Forbidden:** changing a kind the need does not touch (C1); writing anything as agreed
before its checkpoint's yes (C2); redefining a kind with no log line (C3); a real name, text a
newcomer cannot follow, or a checkpoint draft that does not follow the rule for asking a
person (C4); closing while the ontology check fails (C5); a missing
version bump, date or log line (C6); landing outside the change plays or on the wrong branch
(C7); running the ontology skill outside this play (C8).

**Agent boundaries:**

| Agent | Domain | Skill it invokes | Phases |
|-------|--------|------------------|--------|
| `product-os-keeper` | Read the sources the need names, run the skill's stage, write the stage's draft (and, at the last stage, the ontology itself) | `author-product-ontology` | Draft, Write |

`product-os-keeper` is the single **domain agent**. The start and end sequence are injected
sub-plays. Everything else is a script.

## Pre-flight

| Check | Constraint | Action on Failure |
|-------|-----------|-------------------|
| Resolve config + `stm_base` (`.garura/core/config.yaml`) | — | Hard halt |
| A need was given, in plain words, with the issue it serves | C1 | Ask the person for it (gather, not a halt) |
| The ontology source exists (`core/components/memory/standards/schemas/product-os/ontology.md`) | C5 | Hard halt |
| **Clean ontology** — checked at the end of Step 0: `git status --porcelain -- <ontology>` is empty | C1 | Hard halt (REC1) |

Resolve the facts with the bundled resolver — not by inference — once Step 0 has opened the
change:

```
git branch --show-current
python3 scripts/preflight.py --play edit-ontology --config .garura/core/config.yaml \
    --branch "<current branch>"
python3 scripts/session_stamp.py --phase start \
    --marker "{stm_base}<issue>/status/session-stamp-edit-ontology.json" \
    --cwd "$(pwd)" --branch "$(git branch --show-current)"
```

The working folder `<working>` is `{stm_base}<issue>/context/edit-ontology/`. Keep a copy of
the ontology as it is before any change, for the change check:

```
git show HEAD:core/components/memory/standards/schemas/product-os/ontology.md > <working>/ontology-before.md
```

## Task DAG

Create ALL tasks immediately after pre-flight, before any domain work.

```
[T0] start-change (injected — start)                       blockedBy: []
[T1] Draft the questions (stage: scope)                     blockedBy: [T0]
[T2] Checkpoint 1 — the questions                           blockedBy: [T1]
[T3] Draft the kinds (stage: kinds)                         blockedBy: [T2]
[T4] Checkpoint 2 — the kinds                               blockedBy: [T3]
[T5] Draft the properties, links and rules (stage: links)  blockedBy: [T4]
[T6] Checkpoint 3 — the links and rules                     blockedBy: [T5]
[T7] Write the ontology and check it (stage: write)        blockedBy: [T6]
[T8] Check the change (scope, version, names)               blockedBy: [T7]
[T9] Commit the ontology                                     blockedBy: [T8]
[E1] commit-change (injected — end)                          blockedBy: [T9]
[E2] propose-change (injected — end)                         blockedBy: [E1]
[E3] check-change (injected — end)                           blockedBy: [E2]
[E4] merge-change (injected — end)                           blockedBy: [E3]
[T10] Scenario Validation                                    blockedBy: [E4]
[T11] Close                                                  blockedBy: [T10]
```

Mark each task in progress before its step and completed right after its eval passes. No
runtime reordering. On resume, skip completed and reset in-progress to pending.

## Workflow

### Phase: Start (injected — D2 position: start)

**Step 0 — start-change** · Owner: `start-change` (sub-play) · Depends on: pre-flight
Run the start-of-pipeline member as a sub-play with `parent_run_id`: it resolves the issue,
cuts its branch (the plan's sub-branch when the issue sits in a plan), and inits STM. Then
check the ontology is clean (`test -z "$(git status --porcelain -- <ontology>)"`, else hard
halt — REC1) and write `<working>/need.md`: the need in the person's words, the issue, and
the kinds it touches (`## Touches`, one kind per line — new or existing).

    { "play": "start-change", "parent_run_id": "<this run id>",
      "inputs": { "title": "edit-ontology: <the need in a few words>" },
      "outputs": { "result": "{stm_base}<issue>/context/edit-ontology/start-change.json" } }

### Phase: Draft (three stages, each ending at a checkpoint)

**Step 1 — Draft the questions** · Owner: `product-os-keeper` · Depends on: Step 0

    { "task":    "run author-product-ontology stage 'scope' (step 1): write the questions the ontology must answer for this need",
      "inputs":  { "need": "<working>/need.md",
                   "ontology_path": "core/components/memory/standards/schemas/product-os/ontology.md",
                   "template_path": "<memory>/standards/templates/product-ontology.md",
                   "asking_rule": "../_shared/asking-a-person.md",
                   "sources": ["<paths the need names>"], "stage": "scope" },
      "outputs": { "draft": "<working>/draft-questions.md" },
      "task_id": "edit-ontology-scope" }

The draft lists each new or changed question with a plain example from a real product, in
ASD-STE100 plain English, with personas and no real names (C4). Every draft shown at a
checkpoint follows the shared rule for asking a person, `_shared/asking-a-person.md`: the
install lays it beside the installed skills (`../_shared/asking-a-person.md` from this play's
folder), and `product-os-keeper` passes that path to the skill as `asking_rule`. The rule is
not memory; nothing looks for it through the memory tool. Steps 3 and 5 carry the same input.

**Step 2 — Checkpoint 1: the questions** · Owner: play · Depends on: Step 1 · Checkpoint
(class: standard, **pinned** — the product owner decides, C2; never skipped by config)
Show `draft-questions.md` exactly as written, and ask the product owner to type **yes**, or
**change: <what>**. Record the answer verbatim:

```
python3 scripts/record_checkpoint.py --decisions <working>/decisions.json --point questions \
    --verdict <yes|change> --reply "<their exact words>" --draft <working>/draft-questions.md
```

On **change**, send the change back to Step 1 (same contract plus `"change": "<their words>"`)
and ask again. Go on only on **yes**.
**SE-1 (F2/C2):** `decisions.json` holds a `questions` entry with verdict `yes`, a non-empty
reply, and the sha256 of the draft that was shown; no later stage's draft existed before it.

**Step 3 — Draft the kinds** · Owner: `product-os-keeper` · Depends on: Step 2
Same contract as Step 1 with `"stage": "kinds"` (the skill's steps 2–4: reuse, terms, kinds),
`inputs.questions: <working>/draft-questions.md`, `outputs.draft: <working>/draft-kinds.md`.
The draft names, for each existing kind it reuses or changes, what changes and why — the log
line it will need (C3).

**Step 4 — Checkpoint 2: the kinds** · Owner: play · Depends on: Step 3 · Checkpoint (pinned)
As Step 2, with `--point kinds --draft <working>/draft-kinds.md`. Update `need.md`'s
`## Touches` to the kinds the product owner agreed.
**SE-2 (F2/C2):** `decisions.json` holds a `kinds` entry with verdict `yes`, recorded after
the `questions` yes.
**SE-3 (F3/C3):** every existing kind that `draft-kinds.md` marks as changed has its log line
drafted in it.

**Step 5 — Draft the properties, links and rules** · Owner: `product-os-keeper` · Depends on:
Step 4
Same contract with `"stage": "links"` (the skill's steps 5–6), `inputs.kinds:
<working>/draft-kinds.md`, `outputs.draft: <working>/draft-links.md`.

**Step 6 — Checkpoint 3: the links and rules** · Owner: play · Depends on: Step 5 · Checkpoint
(pinned)
As Step 2, with `--point links --draft <working>/draft-links.md`.
**SE-4 (F2/C2):** `decisions.json` reads `all_agreed: true` — a `yes` for all three points —
before Step 7 writes anything.

### Phase: Write

**Step 7 — Write the ontology and check it** · Owner: `product-os-keeper` · Depends on: Step 6

    { "task":    "run author-product-ontology stage 'write' (step 7 + write): write the agreed result into the ontology, with a real example of each new or changed kind, bump the version by one, set updated, add one log line; then run the check",
      "inputs":  { "need": "<working>/need.md", "questions": "<working>/draft-questions.md",
                   "kinds": "<working>/draft-kinds.md", "links": "<working>/draft-links.md",
                   "ontology_path": "core/components/memory/standards/schemas/product-os/ontology.md",
                   "date": "<today, UTC>", "stage": "write" },
      "outputs": { "ontology": "core/components/memory/standards/schemas/product-os/ontology.md",
                   "report": "<working>/ontology-check.json" },
      "task_id": "edit-ontology-write" }

Then run the check yourself — the script decides valid, not the agent (C5):

```
python3 scripts/check_ontology.py \
    --ontology core/components/memory/standards/schemas/product-os/ontology.md \
    --out <working>/ontology-check.json
```

Exit 2 → send the report's problems back to the agent (stage `write`, plus
`"problems": "<working>/ontology-check.json"`), and run the check again (REC5). Exit 3 → hard
halt.
**SE-5 (F5/C5):** `ontology-check.json` reads `valid: true`, written by `check_ontology.py`
after the last write to the ontology.

**Step 8 — Check the change** · Owner: play (script) · Depends on: Step 7

```
python3 scripts/check_ontology_change.py --before <working>/ontology-before.md \
    --after core/components/memory/standards/schemas/product-os/ontology.md \
    --allow-kind <each kind under need.md ## Touches> --date <today, UTC> \
    $(git config user.name | tr ' ' '\n' | sed 's/^/--forbid-name /') \
    --out <working>/change-check.json
```

**SE-6 (F1/C1):** `change-check.json` reads `scope_ok: true` — no kind outside `## Touches`
changed.
**SE-7 (F6/C6):** `change-check.json` reads `version_ok: true` — the version is up by one,
`updated` equals the run's date, and there is exactly one new log line.
**SE-8 (F4/C4):** `change-check.json` reads `names_ok: true`, and every new or changed kind
has an `**Example**` part; each draft shown at a checkpoint (`draft-questions.md`,
`draft-kinds.md`, `draft-links.md`) has an opening, and each of its questions has the parts
Question, Answer, Why it matters and Example.

**Step 9 — Commit the ontology** · Owner: play · Depends on: Step 8

```
git add -- core/components/memory/standards/schemas/product-os/ontology.md <working>
git commit -m "feat(ontology): v<N> — <the need> (#<issue>)"
```

### Phase: End sequence (injected — D2 position: end)

After the commit, the D2 rule injects the close sequence, each a sub-play with
`parent_run_id`:

**Step E1 — commit-change** · blockedBy: Step 9

    { "play": "commit-change", "parent_run_id": "<this run id>", "inputs": {}, "outputs": { "result": "<working>/commit-change.json" } }

**Step E2 — propose-change** · blockedBy: E1

    { "play": "propose-change", "parent_run_id": "<this run id>", "inputs": {}, "outputs": { "result": "<working>/propose-change.json" } }

**Step E3 — check-change** · blockedBy: E2

    { "play": "check-change", "parent_run_id": "<this run id>", "inputs": {}, "outputs": { "result": "<working>/check-change.json" } }

**Step E4 — merge-change** · blockedBy: E3

    { "play": "merge-change", "parent_run_id": "<this run id>", "inputs": {}, "outputs": { "result": "<working>/merge-change.json" } }

Each end member owns its own evals; a review reject stops the chain before merge.
**SE-9 (F7/C7):** `start-change` ran at the head; the PR's base equals the target
`resolve_target.py` gives for the branch; `merge-change.json` reports the PR merged.
**SE-10 (F8/C8):** the skill's drafts and the ontology write are all under `<working>` and
were made by this run's `product-os-keeper` dispatches (the contracts' `task_id`s); the skill
is not user-invocable.

### Phase: Scenario Validation

**Step 10 — Scenario evals** · Owner: play · Depends on: the end sequence
- **SCE-1 (S1 — product owner, a new kind):** `ontology-check.json` reads `valid: true`, the
  new kind is in `change-check.json` `changed_kinds`, `version_after` equals
  `version_before` + 1, and `merge-change.json` reports the PR merged into the target branch.
- **SCE-2 (S2 — product owner, a change at a checkpoint):** `decisions.json` holds a `yes`
  for each of the three points; any `change` entry comes before that point's `yes`; each
  entry carries the sha256 of the draft that was shown.
- **SCE-3 (S3 — reviewer, scope):** `change-check.json` reads `scope_ok: true` and
  `out_of_scope` is empty.
- **SCE-4 (S4 — reader, plain words):** `change-check.json` reads `names_ok: true`, and each
  new or changed kind has an example.
- **SCE-5 (S5 — product owner, a check that fails):** the last `ontology-check.json` reads
  `valid: true`; no commit was made while an earlier report read not valid.

### Phase: Evidence & Close

**Step 11 — Close** · Owner: play · Depends on: Step 10
Run the Standard Play Close. The close is stop-condition gated: `check_stop_condition.py`
over the baked `stop-condition.yaml` (D1 the ontology check reads valid; D2 all three
checkpoints agreed; D3 scope ok; D4 version ok) must read **held** before any COMPLETED
close.

```bash
# --- Standard Play Close (shared; see ../_shared/play-close.md) ---
# Run the close in ../_shared/play-close.md. Its Step L loads the templates through
# template-manager and sets ts and evidence_dest; then run this play's own lines below;
# then Steps C0-C2.
#   evidence_base, slug (project-scoped play):
#     evidence_base="${stm_base}${issue}/evidence/edit-ontology/"   ; slug="#${issue}"
# Session identity stamp (#463) — close phase; start phase ran at pre-flight
session_stamp=$(python3 scripts/session_stamp.py --phase close \
    --marker "${stm_base}${issue}/status/session-stamp-edit-ontology.json")
# Stop-condition gate (#464) — Step C0: this play carries a baked manifest, so the
# gate is LIVE. Evaluate the Done means here as the close's authoritative input.
python3 scripts/check_stop_condition.py \
    --manifest "<play-dir>/stop-condition.yaml" \
    --base "${stm_base}${issue}/" \
    --out "${stm_base}${issue}/status/stop-condition-edit-ontology.yaml"
sc_exit=$?   # 0 held · 1 unmet · 2 error
```

**Step C0 — bind the verdict.** `sc_exit == 0` (held) permits `status: COMPLETED`. Anything
else closes `HALTED` with `exit_reason: stop_condition_unmet` and the evidence's Stop
Condition section names every unmet clause. An unevaluable verdict is never a pass.

**Step C1 — Write evidence file.** Gated by the resolved `evidence.record` flag (global +
per-play `evidence.plays.edit-ontology`; first match wins, absent ⇒ record). When false, skip
the write and record `evidence skipped (record=false)` in the report's pointer line.
Otherwise fill the `evidence-file.md` slots (play `edit-ontology`, run_id
`edit-ontology-${ts}`, issue, started_at/completed_at, status per C0, exit_reason; artifacts
produced: the ontology, `need.md`, the three drafts, `decisions.json`, `ontology-check.json`,
`change-check.json`, the commit sha; step and scenario eval results SE-1…SE-10 /
SCE-1…SCE-5; the three checkpoint answers in the product owner's words; the session identity
stamp fields from $session_stamp (#463): session_id, ledger_file, ledger_start_offset,
ledger_end_offset (null when unresolved — never blocks the close); and stop_condition per C0)
and write to `$evidence_dest`. Do NOT hand-author the body.

**Step C2 — Render delivery report.** Leave out the **Next** line: this play is
`meta_exempt` and has no entry in the Next-line map (`play-close.md`). Fill the
`delivery-report.md` slots and output the
report: `## edit-ontology Delivered — #${issue}`, the Run Summary table, the Pipeline Steps
table from the task DAG, the Artifacts Produced table (the ontology version, the kinds
changed, the PR), Next Steps (the plays that write the changed kinds may now need edit-play),
and a pointer to `$evidence_dest`. Always emitted; never gated.

```bash
# --- end Standard Play Close ---
```

## Scenario Validation

| Scenario | Persona | Eval |
|----------|---------|------|
| S1 — a new kind | product owner | SCE-1 |
| S2 — a change at a checkpoint | product owner | SCE-2 |
| S3 — scope | reviewer | SCE-3 |
| S4 — plain words | reader | SCE-4 |
| S5 — a check that fails | product owner | SCE-5 |

## Recovery

| For | Trigger | Direction | Handoff |
|-----|---------|-----------|---------|
| F1 | a kind the need does not touch changed | undo the change to that kind, and show it to the product owner as a separate need | autonomous |
| F2 | something was written as agreed without the product owner's yes at one of the three points | take the write back to draft, and ask again at that checkpoint | human |
| F3 | an existing kind changed meaning with no log line | add the log line that names the changed meaning, or undo the change | autonomous |
| F4 | a real name in the text, text a newcomer cannot follow, or a checkpoint draft that does not follow the rule for asking a person | rewrite with personas and plain words, in the shape the rule for asking a person gives, and run the change check again | autonomous |
| F5 | the run would close while the ontology check fails | fix each problem the report lists and run the check again; the run stays open until it reads valid | autonomous |
| F6 | the version, the date or the log line is missing | set the version, the date and the log line, and run the checks again | autonomous |
| F7 | the change landed outside the change plays, or on the wrong branch | stop; land it through the change plays, on the branch `resolve_target.py` gives | human |
| F8 | the ontology skill ran outside this play | throw that result away, and run the need through this play | autonomous |

## Pause and Resume

Steps run top to bottom. On entry, resolve the issue from the branch, check the status marker
and `<working>/decisions.json`, skip completed steps, reset any in-progress step to pending,
and continue. A resume never asks a checkpoint again once `decisions.json` holds its `yes`,
and never re-drafts a stage whose checkpoint is agreed.

## Compilation Metadata

| Field | Value |
|-------|-------|
| fingerprint | sha256:4e68db4acb380e1ec569050dc09fb0961181a2e28c289fa10f452e4374804d4c (of `reference/ice.md`) |
| compiled_by | create-play (#777) |
| pipeline_position | both (start-change head; commit → propose → review → merge close) |
| position_exception | ontology-writing both play — writes the ontology on its started branch and commits it (Step 9) BEFORE the injected end sequence lands it |
| workflow_structure | A (three pinned human checkpoints — the product owner decides; stop-condition gated close) |
| stop_condition | stop-condition.yaml (D1–D4), gate live at Step C0 |
| domain_agents | 1 (product-os-keeper) |
| utility_agents | 0 |
| skills_used | author-product-ontology |
| scripts | 6 (preflight.py, session_stamp.py, check_stop_condition.py, check_ontology.py — copied from the author-product-ontology skill, check_ontology_change.py, record_checkpoint.py) + test_edit_ontology_scripts.py |
| step_evals | 10 (SE-1…SE-10) |
| scenario_evals | 5 (SCE-1…SCE-5) |
| recovery_entries | 8 (one per failure condition; 6 autonomous / 2 human) |

Files in this skill

  • SKILL.md22 KB
  • reference/ice.md6.3 KB
  • scripts/check_ontology.py8.5 KB
  • scripts/check_ontology_change.py3.5 KB
  • scripts/check_stop_condition.py5 KB
  • scripts/preflight.py7 KB
  • scripts/record_checkpoint.py2.4 KB
  • scripts/session_stamp.py4.8 KB
  • scripts/test_edit_ontology_scripts.py6 KB
  • stop-condition.yaml1.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.