Skip to content
Back to skills

Openspec Journal

ASecurity

Owns the append-only interaction journal for an OpenSpec change — `openspec/changes/<change>/journal.jsonl` — and the fixed event vocabulary written to it (change.created, artifact.added/revised, mode.chosen, task.start/complete/blocked, verifier.result, decision, handoff, archive, skill.invoked, agent.spawned, context.compacted, turn.start/end). Invoked by name from the openspec-* skills whenever one of those events happens; not a user-facing entry point on its own. Use for "log this to the ...

  • 18 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
ai-agentspythonbash

Works with

  • claude code

Security analysis

A100/100

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

Scanned September 3, 2026

npx -y skills add redhat-developer/rhdh-skill --skill openspec-journal --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Openspec Journal?

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

Security grade badge for Openspec Journal
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/redhat-developer-openspec-journal/badge)](https://www.skillsdirectory.com/skills/redhat-developer-openspec-journal)

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: openspec-journal
description: >-
  Owns the append-only interaction journal for an OpenSpec change —
  `openspec/changes/<change>/journal.jsonl` — and the fixed event vocabulary
  written to it (change.created, artifact.added/revised, mode.chosen,
  task.start/complete/blocked, verifier.result, decision, handoff, archive,
  skill.invoked, agent.spawned, context.compacted, turn.start/end). Invoked by
  name from the openspec-* skills whenever one of those events happens; not a
  user-facing entry point on its own. Use for "log this to the journal",
  "emit a journal event", "what fields does task.complete need", or "why did
  the journal helper reject my write".
compatibility: "Python 3.9+ on PATH. No network access. Self-contained; discovers the OpenSpec workspace root by walking up for an openspec/changes/ directory."
---

# OpenSpec journal

Write one line of structured, append-only history per load-bearing interaction
inside an OpenSpec change, so a change's `journal.jsonl` becomes a session log
that survives context compaction and long-running work — not a full
transcript, and not optional narration.

## Route

Run the bundled helper that ships with this skill. Resolve
`scripts/openspec-journal.py` next to this skill's `SKILL.md` (the host skill
install path). Do **not** look for it under the product repo's `scripts/` —
that path is never installed. Keep the product repo as the working directory
so the helper can find `openspec/changes/`:

```bash
python3 <skill-dir>/scripts/openspec-journal.py <change> <event> [k=v ...]
python3 <skill-dir>/scripts/openspec-journal.py <change> show [--limit N]
python3 <skill-dir>/scripts/openspec-journal.py <change> doctor
python3 <skill-dir>/scripts/openspec-journal.py --schema
```

Run with no arguments for the full usage contract, and `--schema` for the
authoritative event-name -> required-field table. Read those outputs instead
of memorizing the vocabulary — the script is the single source of truth for
it, so a caller who invents its own field name or event name gets a rejection,
not a silent write.

## Turn bookending is the default discipline

Whenever the active working directory is inside an OpenSpec change, bookend
every user turn with two writes, independent of whether any file changed:

1. **Before starting work**, log `turn.start input="<paraphrase of the ask,
   <=200 chars>"`.
2. **After finishing**, log `turn.end output="<what changed, was decided, or
   was answered>"`.

Writing the input *before* doing the work is a commitment device against
post-hoc rationalization. This applies to every prompt, including pure Q&A
turns with no file changes.

## Ordering and length

Events describe things that already happened — log `change.created` after
`openspec new change <name>` succeeds, not before. `input`/`output` are
rejected (exit 2) above 200 characters so the caller rewrites shorter rather
than truncating silently; move long content into `design.md` or an ADR and
point at it (`output="See design.md §3 for full rationale."`).

`--input-file` / `--output-file` paths must resolve under the change
directory. Change names `.` and `archive` are rejected. Reserved fields
`ts`, `event`, and `phase` cannot be forged via `k=v`.

## Precompact hook

`scripts/openspec-journal-precompact-hook.sh` emits `context.compacted` for
the most recently active change when an agent host fires a pre-compaction
lifecycle hook (for example Claude Code's `PreCompact`). It is self-contained,
silent on any failure, and never blocks compaction. Wire it once per host;
skills never call it directly.

## Completion

Complete when the event was accepted (exit 0) and, for `show`/`doctor`, the
requested output was returned. A rejected write (exit 1 usage error, exit 2
validation error) is not silently swallowed — surface the helper's exact error
to the caller so it can fix the event name, field, or length and retry.

Files in this skill

  • SKILL.md3.8 KB
  • agents/openai.yaml145 B
  • scripts/openspec-journal-precompact-hook.sh2.7 KB
  • scripts/openspec-journal.py24 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…