Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"name": "diataxis-docs",
"repository": "https://github.com/Statusnone420/Skills",
"source": "./adapters/claude",
"version": "0.1.5"
"version": "0.1.6"
}
]
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ __pycache__/
.venv/
evals/workspace/
evals/results/drafts/
/showcase
2 changes: 1 addition & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The canonical source is `skills/docs/SKILL.md`, routed to `references/commands.m

Discovery owns bounded metadata and selection policy; `init_adoption.py` owns the deterministic, engine-owned first-run adoption (scope selection, corpus accounting, preview construction, and receipt binding); `paths.py` owns confinement, normalization, reparse checks, and prune primitives; `memory.py` is read-only inspection; `lifecycle.py` owns pure authorization/state policy; and `lifecycle_io.py` owns transactional filesystem I/O. The dependency direction is one-way and the CLI façade stays thin. The committed `.diataxis/` control plane stores normalized routes, stable findings, verified hashes, disposition identity, and event history—never document bodies, prompts, hidden reasoning, or local-only filenames.

Every generated adapter packages the complete canonical checker resource tree. Generic web prompts are composed per command from a shared safety core, one selected command contract, and required supporting rules; they do not concatenate the entire playbook. The 0.1.4 historical range was 3,484–24,679 UTF-8 bytes. The measured 0.1.5 range is 3,460–31,966 bytes, with a 42,000-byte generator regression guard and 10,034 bytes of headroom.
Every generated adapter packages the complete canonical checker resource tree. Generic web prompts are composed per command from a shared safety core, one selected command contract, and required supporting rules; they do not concatenate the entire playbook. The 0.1.4 historical range was 3,484–24,679 UTF-8 bytes. The measured 0.1.6 range is 3,460–31,966 bytes, with a 42,000-byte generator regression guard and 10,034 bytes of headroom.

The repository Codex marketplace lives at `.agents/plugins/marketplace.json` and routes to the generated `plugins/diataxis-docs` package. Its folder, marketplace entry, and `.codex-plugin/plugin.json` all use the same `diataxis-docs` identity. The package contains the shared `docs` engine plus 13 thin `docs-<command>` routing skills; focused skills do not copy the checker or command playbooks. Claude receives equivalent thin skills with its explicit-only invocation metadata. The umbrella remains compatible on both hosts.

Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 0.1.6 — Empty-state recovery repair (2026-07-20)

- Let Init discovery and Doctor's zero-write baseline proceed without false missing-state findings when `.diataxis/` is empty or contains only an empty `manifests/` container left by an interrupted or branch-switched initialization.
- Applied the same bounded residue rule during approval-time revalidation so a successful Init preview can complete its approved apply.
- Kept unknown control children, non-empty manifests, recovery artifacts, symlinks, reparse points, and malformed operational state fail-closed for Doctor diagnosis.
- Added public-command regressions for Init discovery, Doctor baseline measurement, full preview/apply adoption, and unsafe-residue rejection.

## 0.1.5 — Native command skills and first-run Doctor (2026-07-18)

- Added a genuine Codex repository marketplace package with aligned `diataxis-docs` marketplace, folder, and manifest identities.
Expand Down
2 changes: 1 addition & 1 deletion INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Diátaxis Docs is a public alpha. Install from a revision you trust, review prop

## Codex marketplace

Diátaxis Docs 0.1.5 publishes as a Codex repository marketplace plugin. Add the marketplace, install the plugin, and verify that Codex reports it:
Diátaxis Docs 0.1.6 publishes as a Codex repository marketplace plugin. Add the marketplace, install the plugin, and verify that Codex reports it:

```text
codex plugin marketplace add Statusnone420/Skills
Expand Down
2 changes: 1 addition & 1 deletion adapters/claude/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
"license": "Apache-2.0",
"name": "diataxis-docs",
"repository": "https://github.com/Statusnone420/Skills",
"version": "0.1.5"
"version": "0.1.6"
}
2 changes: 1 addition & 1 deletion adapters/claude/skills/docs/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: docs
description: Use when a user explicitly invokes repository documentation help for bounded Diátaxis writing, context recall, mapping, auditing, checking, migration, cleanup, Doctor guidance, or evidence-backed updates.
metadata:
author: Statusnone
version: "0.1.5"
version: "0.1.6"
user-invocable: true
disable-model-invocation: true
---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from .scan import discover_markdown, scan_documents


SKILL_VERSION = "0.1.5"
SKILL_VERSION = "0.1.6"


def canonical_request_bytes(value):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
MAX_FINDINGS_BYTES,
STATE_DIRECTORY,
STATE_SCHEMA_VERSION,
_is_benign_initialization_residue,
build_initialization_state,
inspect_operational_memory,
load_operational_events,
Expand Down Expand Up @@ -1270,11 +1271,14 @@ def inspect_initialization_preflight(root, *, control_present=False):
incomplete or conflicting control plane fails closed to Doctor.
"""
root = Path(root).absolute()
if not control_present and not os.path.lexists(root / STATE_DIRECTORY):
control = root / STATE_DIRECTORY
if not control_present and not os.path.lexists(control):
return None

state = None
try:
if _is_benign_initialization_residue(root):
return None
memory_findings = inspect_operational_memory(
root, inspect_protected_intent=False
)
Expand Down
39 changes: 39 additions & 0 deletions adapters/claude/skills/docs/scripts/_docs_checker/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
)
from .paths import (
_assert_no_reparse_components,
_is_reparse,
normalize_repo_relative,
safe_path,
shared_text_exposes_route,
Expand Down Expand Up @@ -172,6 +173,32 @@ def _operational_control(root):
return control


def _benign_initialization_residue(control):
"""Return whether control contains only bounded empty Init containers."""
if _is_reparse(control) or not control.is_dir():
return False
with os.scandir(control) as entries:
first = next(entries, None)
if first is None:
return True
if next(entries, None) is not None:
return False
manifests = Path(first.path)
if (
first.name != "manifests"
or _is_reparse(manifests)
or not first.is_dir(follow_symlinks=False)
):
return False
with os.scandir(manifests) as entries:
return next(entries, None) is None


def _is_benign_initialization_residue(root):
control = _operational_control(root)
return control is not None and _benign_initialization_residue(control)


def _operational_file(root, filename):
control = _operational_control(root)
if control is None:
Expand Down Expand Up @@ -2137,6 +2164,18 @@ def inspect_operational_memory(root, *, inspect_protected_intent=True):
]
if control is None:
return []
try:
if _benign_initialization_residue(control):
return []
except OSError as exc:
return [
_memory_finding(
"state-conflict",
"P0",
STATE_DIRECTORY,
_sanitized_memory_detail(exc, "operational control entries"),
)
]

findings, observed_control = _inspect_control_plane_files(control)
state = None
Expand Down
2 changes: 1 addition & 1 deletion adapters/copilot/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: docs
description: Use when a user explicitly invokes repository documentation help for bounded Diátaxis writing, context recall, mapping, auditing, checking, migration, cleanup, Doctor guidance, or evidence-backed updates.
metadata:
author: Statusnone
version: "0.1.5"
version: "0.1.6"
user-invocable: true
disable-model-invocation: true
---
Expand Down
2 changes: 1 addition & 1 deletion adapters/copilot/scripts/_docs_checker/init_adoption.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from .scan import discover_markdown, scan_documents


SKILL_VERSION = "0.1.5"
SKILL_VERSION = "0.1.6"


def canonical_request_bytes(value):
Expand Down
6 changes: 5 additions & 1 deletion adapters/copilot/scripts/_docs_checker/init_closeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
MAX_FINDINGS_BYTES,
STATE_DIRECTORY,
STATE_SCHEMA_VERSION,
_is_benign_initialization_residue,
build_initialization_state,
inspect_operational_memory,
load_operational_events,
Expand Down Expand Up @@ -1270,11 +1271,14 @@ def inspect_initialization_preflight(root, *, control_present=False):
incomplete or conflicting control plane fails closed to Doctor.
"""
root = Path(root).absolute()
if not control_present and not os.path.lexists(root / STATE_DIRECTORY):
control = root / STATE_DIRECTORY
if not control_present and not os.path.lexists(control):
return None

state = None
try:
if _is_benign_initialization_residue(root):
return None
memory_findings = inspect_operational_memory(
root, inspect_protected_intent=False
)
Expand Down
39 changes: 39 additions & 0 deletions adapters/copilot/scripts/_docs_checker/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
)
from .paths import (
_assert_no_reparse_components,
_is_reparse,
normalize_repo_relative,
safe_path,
shared_text_exposes_route,
Expand Down Expand Up @@ -172,6 +173,32 @@ def _operational_control(root):
return control


def _benign_initialization_residue(control):
"""Return whether control contains only bounded empty Init containers."""
if _is_reparse(control) or not control.is_dir():
return False
with os.scandir(control) as entries:
first = next(entries, None)
if first is None:
return True
if next(entries, None) is not None:
return False
manifests = Path(first.path)
if (
first.name != "manifests"
or _is_reparse(manifests)
or not first.is_dir(follow_symlinks=False)
):
return False
with os.scandir(manifests) as entries:
return next(entries, None) is None


def _is_benign_initialization_residue(root):
control = _operational_control(root)
return control is not None and _benign_initialization_residue(control)


def _operational_file(root, filename):
control = _operational_control(root)
if control is None:
Expand Down Expand Up @@ -2137,6 +2164,18 @@ def inspect_operational_memory(root, *, inspect_protected_intent=True):
]
if control is None:
return []
try:
if _benign_initialization_residue(control):
return []
except OSError as exc:
return [
_memory_finding(
"state-conflict",
"P0",
STATE_DIRECTORY,
_sanitized_memory_detail(exc, "operational control entries"),
)
]

findings, observed_control = _inspect_control_plane_files(control)
state = None
Expand Down
2 changes: 1 addition & 1 deletion adapters/cursor/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: docs
description: Use when a user explicitly invokes repository documentation help for bounded Diátaxis writing, context recall, mapping, auditing, checking, migration, cleanup, Doctor guidance, or evidence-backed updates.
metadata:
author: Statusnone
version: "0.1.5"
version: "0.1.6"
user-invocable: true
disable-model-invocation: true
---
Expand Down
2 changes: 1 addition & 1 deletion adapters/cursor/scripts/_docs_checker/init_adoption.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from .scan import discover_markdown, scan_documents


SKILL_VERSION = "0.1.5"
SKILL_VERSION = "0.1.6"


def canonical_request_bytes(value):
Expand Down
6 changes: 5 additions & 1 deletion adapters/cursor/scripts/_docs_checker/init_closeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
MAX_FINDINGS_BYTES,
STATE_DIRECTORY,
STATE_SCHEMA_VERSION,
_is_benign_initialization_residue,
build_initialization_state,
inspect_operational_memory,
load_operational_events,
Expand Down Expand Up @@ -1270,11 +1271,14 @@ def inspect_initialization_preflight(root, *, control_present=False):
incomplete or conflicting control plane fails closed to Doctor.
"""
root = Path(root).absolute()
if not control_present and not os.path.lexists(root / STATE_DIRECTORY):
control = root / STATE_DIRECTORY
if not control_present and not os.path.lexists(control):
return None

state = None
try:
if _is_benign_initialization_residue(root):
return None
memory_findings = inspect_operational_memory(
root, inspect_protected_intent=False
)
Expand Down
39 changes: 39 additions & 0 deletions adapters/cursor/scripts/_docs_checker/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
)
from .paths import (
_assert_no_reparse_components,
_is_reparse,
normalize_repo_relative,
safe_path,
shared_text_exposes_route,
Expand Down Expand Up @@ -172,6 +173,32 @@ def _operational_control(root):
return control


def _benign_initialization_residue(control):
"""Return whether control contains only bounded empty Init containers."""
if _is_reparse(control) or not control.is_dir():
return False
with os.scandir(control) as entries:
first = next(entries, None)
if first is None:
return True
if next(entries, None) is not None:
return False
manifests = Path(first.path)
if (
first.name != "manifests"
or _is_reparse(manifests)
or not first.is_dir(follow_symlinks=False)
):
return False
with os.scandir(manifests) as entries:
return next(entries, None) is None


def _is_benign_initialization_residue(root):
control = _operational_control(root)
return control is not None and _benign_initialization_residue(control)


def _operational_file(root, filename):
control = _operational_control(root)
if control is None:
Expand Down Expand Up @@ -2137,6 +2164,18 @@ def inspect_operational_memory(root, *, inspect_protected_intent=True):
]
if control is None:
return []
try:
if _benign_initialization_residue(control):
return []
except OSError as exc:
return [
_memory_finding(
"state-conflict",
"P0",
STATE_DIRECTORY,
_sanitized_memory_detail(exc, "operational control entries"),
)
]

findings, observed_control = _inspect_control_plane_files(control)
state = None
Expand Down
2 changes: 1 addition & 1 deletion adapters/gemini/docs.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# /docs wrapper

Diátaxis Docs v0.1.5
Diátaxis Docs v0.1.6

Instruction-enforced invocation: activate the shared `docs` skill explicitly, then parse one command and forward the raw trailing text verbatim (without shell interpolation).
Usage: `/docs <command> [raw trailing text]`.
2 changes: 1 addition & 1 deletion adapters/grok/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: docs
description: Use when a user explicitly invokes repository documentation help for bounded Diátaxis writing, context recall, mapping, auditing, checking, migration, cleanup, Doctor guidance, or evidence-backed updates.
metadata:
author: Statusnone
version: "0.1.5"
version: "0.1.6"
user-invocable: true
disable-model-invocation: true
---
Expand Down
2 changes: 1 addition & 1 deletion adapters/grok/scripts/_docs_checker/init_adoption.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from .scan import discover_markdown, scan_documents


SKILL_VERSION = "0.1.5"
SKILL_VERSION = "0.1.6"


def canonical_request_bytes(value):
Expand Down
Loading