Metadata-Version: 2.4
Name: sdcoh
Version: 0.1.1
Summary: Story Design Coherence — manage dependency graphs between story design documents
Author: ysttsu
License-Expression: MIT
Keywords: fiction,writing,coherence,dependency-graph,claude-code
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Text Processing :: Markup :: Markdown
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: python-frontmatter>=1.0
Provides-Extra: openviking
Requires-Dist: httpx>=0.27; extra == "openviking"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-tmp-files>=0.0.2; extra == "dev"
Dynamic: license-file

# sdcoh — Story Design Coherence

[![PyPI](https://img.shields.io/pypi/v/sdcoh?style=flat-square&color=blue&v=1)](https://pypi.org/project/sdcoh/)
[![Python](https://img.shields.io/pypi/pyversions/sdcoh?style=flat-square&v=1)](https://pypi.org/project/sdcoh/)
[![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)](LICENSE)
[![Stars](https://img.shields.io/github/stars/ysttsu/sdcoh?style=flat-square)](https://github.com/ysttsu/sdcoh/stargazers)

[日本語版 README](README.ja.md)

**Manage dependency graphs between story design documents.** Detect change impact and stale downstream files.

When writing novels with AI, you end up with dozens of interconnected design documents: character sheets, beat sheets, foreshadowing ledgers, style guides, briefs, and episode drafts. Change one, and you need to update five others. Forget one, and your story has inconsistencies.

sdcoh makes these dependencies explicit and trackable.

## The Problem

```
You update the character sheet...
  → but forget to update the beat sheet
  → which means the brief is based on stale info
  → which means the AI writes the episode with wrong details
  → which means you spend an hour finding why the draft feels off
```

## The Solution

```bash
$ sdcoh status

⚠️ Updates needed (3):
  design:continuity      last updated 3/15 ← episode:ep07 updated 3/28
  design:expression-log  last updated 3/10 ← episode:ep05 updated 3/27
  brief:ep08             last updated 3/13 ← design:beat-sheet updated 3/25

✅ In sync (12)
```

## Install

```bash
pip install sdcoh
```

Optional OpenViking integration:
```bash
pip install sdcoh[openviking]
```

## Quick Start

### 1. Initialize your project

```bash
cd your-novel-project/
sdcoh init --name "My Novel" --alias my-novel
```

This creates `sdcoh.yml` and `.sdcoh/` directory.

### 2. Add frontmatter to your documents

Add YAML frontmatter to each Markdown file declaring its dependencies:

```yaml
---
sdcoh:
  id: "design:beat-sheet"
  depends_on:
    - id: "design:characters"
      relation: derives_from
---

# Beat Sheet
...
```

### 3. Scan and check

```bash
sdcoh scan        # Build the dependency graph
sdcoh graph       # Visualize it
sdcoh validate    # Check for broken references
sdcoh status      # Find stale documents
```

### 4. Check impact before editing

```bash
$ sdcoh impact design/characters.md

Affected (4):
  🟡 design:beat-sheet          ← derives_from
  🟡 design:foreshadowing       ← references
  🟡 brief:ep02                 ← references
  🟡 episode:ep01               ← implements
```

## Project Config (sdcoh.yml)

```yaml
project:
  name: "My Novel"
  alias: "my-novel"

# Directories to scan for Markdown files
scan:
  - design/
  - drafts/
  - briefs/
  - reviews/
  - research/
  - docs/

# Node types with layer hierarchy (lower = upstream)
node_types:
  research: { layer: -1 }  # Most upstream
  design:   { layer: 0 }
  brief:    { layer: 1 }
  episode:  { layer: 2 }
  review:   { layer: 3 }   # Most downstream

# Optional: OpenViking semantic search integration
openviking:
  enabled: false
  endpoint: "http://localhost:1933"
  auto_register: true
```

## Default Directory Structure

```
novel-project/
├── sdcoh.yml        # Project config
├── design/          # Character sheets, beat sheets, style guides, etc.
├── drafts/          # Episode manuscripts
├── briefs/          # Writing briefs for AI agents
├── reviews/         # Review results
├── research/        # Research materials
└── docs/            # Workflow documentation
```

## Frontmatter Spec

### Fields

| Field | Required | Description |
|-------|----------|-------------|
| `id` | Yes | Node ID in `{type}:{name}` format |
| `depends_on` | No | Upstream dependencies (if they change, I'm affected) |
| `updates` | No | Downstream targets (if I change, they need updating) |

### Relation Types

| Relation | Meaning | Example |
|----------|---------|---------|
| `derives_from` | Derived from this document | beat sheet ← characters |
| `implements` | Implements this design | episode ← beat sheet |
| `constrained_by` | Must follow these rules | episode ← style guide |
| `references` | References this document | brief ← foreshadowing ledger |
| `extracts_from` | Extracted from this source | expression log ← episode |
| `triggers_update` | Change triggers update | continuity ← episode |

### Glob Patterns

Use fnmatch-style glob patterns to declare dependencies on multiple nodes at once:

```yaml
# design/characters.md — updates all episodes and briefs when changed
sdcoh:
  id: "design:characters"
  updates:
    - id: "episode:*"
      relation: triggers_update
    - id: "brief:*"
      relation: triggers_update
    - id: "design:voice-*"
      relation: triggers_update
```

Patterns are expanded at scan time — `graph.json` contains only concrete edges. Supported glob syntax: `*` (any string), `?` (single char), `[seq]` (character set).

This lets you declare dependencies from the design doc side, keeping episode/brief frontmatter minimal:

```yaml
# drafts/ep05.md — only exception-specific dependencies needed
sdcoh:
  id: "episode:ep05"
  depends_on:
    - id: "design:foreshadow-ledger"
      relation: references
```

A glob pattern that matches zero nodes produces a warning during `sdcoh scan`.

### Bidirectional Dependencies

Some relationships go both ways. Use `depends_on` for upstream and `updates` for downstream:

```yaml
# episode extracts expressions into the log
# drafts/ep01.md
sdcoh:
  id: "episode:ep01"
  updates:
    - id: "design:expression-log"
      relation: extracts_from

# the log is referenced by briefs to avoid repetition
# design/expression-log.md
sdcoh:
  id: "design:expression-log"
  depends_on:
    - id: "episode:ep01"
      relation: extracts_from
```

## CLI Reference

| Command | Description |
|---------|-------------|
| `sdcoh init` | Initialize project (`sdcoh.yml` + `.sdcoh/`) |
| `sdcoh scan` | Parse frontmatter, build dependency graph |
| `sdcoh impact <path>` | Show what's affected by changing a file |
| `sdcoh graph` | Display dependency tree |
| `sdcoh validate` | Check for broken refs, cycles, orphans |
| `sdcoh status` | Find stale downstream documents |

### Options

```
sdcoh scan --quiet          # Minimal output (for hooks)
sdcoh scan --warn           # List files without frontmatter
sdcoh impact <path> --depth N  # Limit traversal depth
sdcoh status --warn-only    # Only output if warnings exist
sdcoh status --json         # JSON output
```

## Claude Code Integration

### Install as Plugin

```bash
/plugin marketplace add ysttsu/sdcoh
/plugin install sdcoh@sdcoh
```

### Skills

| Skill | Trigger | Action |
|-------|---------|--------|
| `/sdcoh-scan` | "scan", "graph update" | `sdcoh scan` + `sdcoh validate` |
| `/sdcoh-impact` | "what's affected?" | `sdcoh impact` on recent file |
| `/sdcoh-status` | "stale check" | `sdcoh status` |

### PostToolUse Hook (auto-scan on edit)

Add to `.claude/settings.json`:

```jsonc
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Write|Edit",
      "if": "Write(*/design/*)|Edit(*/design/*)",
      "hooks": [{
        "type": "command",
        "command": "sdcoh scan --quiet && sdcoh status --warn-only",
        "timeout": 10
      }]
    }]
  }
}
```

## Background: Why This Exists

This tool was inspired by [CoDD (Coherence-Driven Development)](https://zenn.dev/shio_shoppaize/articles/shogun-codd-coherence), which manages coherence between software design documents. sdcoh adapts the same principle for fiction writing workflows, where AI-assisted novel projects can accumulate 20-30+ interconnected design documents.

Built as part of an AI-assisted novel writing workflow where the author acts as "director" and AI agents handle drafting. The dependency graph ensures that when a design decision changes, all downstream documents are flagged for review — preventing the subtle inconsistencies that plague long-form fiction.

## License

MIT
