Initial commit — Singular Particular Space v1
Homepage (site/index.html): integration-v14 promoted, Writings section integrated with 33 pieces clustered by type (stories/essays/miscellany), Writings welcome lightbox, content frame at 98% opacity. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
45
skills/annotated-writing/SKILL.md
Normal file
45
skills/annotated-writing/SKILL.md
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: annotated-writing
|
||||
description: >
|
||||
Use this skill when the user says "make a content map" for any piece of writing,
|
||||
OR when the agent receives a completed content map file as input. Two distinct tasks:
|
||||
(1) content mapping: read source text, produce structured annotation data;
|
||||
(2) building: receive content map, produce single-file interactive HTML.
|
||||
These are separate agent tasks. Never attempt both in one context.
|
||||
---
|
||||
|
||||
## This Skill Has Two Modes
|
||||
|
||||
**Mode 1 — Content Mapping** is triggered by: "make a content map"
|
||||
Read `content-mapping-fiction.md` or `content-mapping-non-fiction.md` depending on source type. Produce a `.md` content map file as output.
|
||||
|
||||
**Mode 2 — Build** is triggered by: receiving a content map `.md` file as input.
|
||||
Read `annotated-writing-build.md`. Produce a single-file `.html` artefact as output.
|
||||
|
||||
Never conflate the two. A content-mapping agent should not write HTML. A build agent should not perform literary analysis.
|
||||
|
||||
## Files in This Skill
|
||||
|
||||
| File | Used By | Purpose |
|
||||
|---|---|---|
|
||||
| `content-mapping-fiction.md` | Mapping agent | How to map fiction and historically-situated writing |
|
||||
| `content-mapping-non-fiction.md` | Mapping agent | How to map essays, journalism, documents |
|
||||
| `annotated-writing-build.md` | Build agent | Component library, TOON parsing, HTML output rules |
|
||||
| `SKILL.md` (this file) | Both agents | Entry point, routing |
|
||||
|
||||
## Routing Logic
|
||||
|
||||
```
|
||||
input received
|
||||
│
|
||||
├─ source text .md
|
||||
│ └─ is source fictional? → content-mapping-fiction.md
|
||||
│ is source non-fiction? → content-mapping-non-fiction.md
|
||||
│
|
||||
├─ "make a content map" + source text
|
||||
│ └─ is source fictional? → content-mapping-fiction.md
|
||||
│ is source non-fiction? → content-mapping-non-fiction.md
|
||||
│
|
||||
└─ content map .md file received
|
||||
└─ annotated-writing-build.md
|
||||
```
|
||||
297
skills/annotated-writing/annotated-writing-build.md
Normal file
297
skills/annotated-writing/annotated-writing-build.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# Annotated Writing Build
|
||||
|
||||
Instructions for a build agent. Input: a completed content map `.md` file. Output: a single-file `.html` artefact. Do not perform literary analysis. Do not rewrite or improve the source text. Execute the map.
|
||||
|
||||
---
|
||||
|
||||
## Two-Agent Protocol
|
||||
|
||||
This agent receives a content map. It does not produce content maps. If asked to do both in one context, refuse the analysis task and request the content map as input.
|
||||
|
||||
**What the build agent reads from the content map:**
|
||||
- Tab definitions (TOON)
|
||||
- Decoder metadata (TOON) + decoder bodies (YAML)
|
||||
- Lightbox definitions (YAML)
|
||||
- Accordion content (YAML)
|
||||
- Bias notes (YAML)
|
||||
- Further reading (TOON)
|
||||
- Annotated source text (with `[DECODER]`, `[LIGHTBOX]`, `[ORDER]`, `[LETTER-*]` markers)
|
||||
|
||||
---
|
||||
|
||||
## Reading TOON in the Content Map
|
||||
|
||||
Content maps use TOON for uniform arrays. Parse as follows:
|
||||
|
||||
**Tabular array syntax:**
|
||||
```toon
|
||||
arrayName[N]{field1,field2,field3}:
|
||||
value1,value2,value3
|
||||
value1,value2,value3
|
||||
```
|
||||
`[N]` is the declared row count — validate against actual rows. `{fields}` is the column header — same for every row. Values follow CSV quoting rules: strings containing commas are double-quoted.
|
||||
|
||||
**YAML scalar syntax** (for body text — not TOON):
|
||||
```yaml
|
||||
key: >
|
||||
Block scalar. Paragraph text. May contain commas freely.
|
||||
Blank line = new paragraph in rendered output.
|
||||
```
|
||||
|
||||
Both may appear in the same content map. TOON for metadata; YAML for prose.
|
||||
|
||||
---
|
||||
|
||||
## Aesthetic Direction
|
||||
|
||||
The aesthetic is set per-project by the user. The content map may include an `aesthetic:` key. If absent, infer from context clues in the source text. When in doubt, ask before building.
|
||||
|
||||
Regardless of aesthetic, these rules apply:
|
||||
- Choose fonts that are distinctive and specific to the aesthetic. Never: Arial, Inter, Roboto, system-ui.
|
||||
- Use CSS custom properties for all colors. No hardcoded hex values in component CSS.
|
||||
- Dark or light themes are both valid. Commit to one — do not default to white-on-grey.
|
||||
- Background texture adds atmosphere. Scanlines, grain, parchment patterns, noise — pick one and use it subtly.
|
||||
- Tab navigation is sticky. One tab visible at a time via JS class toggle.
|
||||
|
||||
---
|
||||
|
||||
## Component Library
|
||||
|
||||
All components must be implemented as specified. Do not substitute or simplify.
|
||||
|
||||
---
|
||||
|
||||
### Decoder
|
||||
|
||||
Inline interactive element. Wraps a phrase in prose. Floating panel on click.
|
||||
|
||||
**Critical structural rule:** Every element inside a decoder must be a `<span>`, never a `<div>`. Decoders live inside `<p>` tags. A `<div>` inside a `<p>` silently ejects the panel from the DOM. Use `<span>` with `display: block` for block-like rendering.
|
||||
|
||||
```html
|
||||
<span class="dc" id="[id]">
|
||||
<button class="dc-btn [color-class]" onclick="tog('[id]',this)">[phrase from text]</button>
|
||||
<span class="dc-panel [color-class]">
|
||||
<span class="d-tag [color-class]">[tag text]</span>
|
||||
<span class="d-head">[label]</span>
|
||||
[body text]
|
||||
<a class="d-link [color-class]" href="[url]" target="_blank">→ [link label]</a>
|
||||
</span>
|
||||
</span>
|
||||
```
|
||||
|
||||
**Required CSS:**
|
||||
```css
|
||||
.dc { display: inline; position: relative; }
|
||||
.dc-panel {
|
||||
display: none;
|
||||
position: absolute; /* never relative */
|
||||
top: calc(100% + 6px);
|
||||
left: 0;
|
||||
z-index: 500;
|
||||
width: 300px; /* adjust to aesthetic */
|
||||
}
|
||||
.dc-panel.open { display: block; }
|
||||
.dc-panel.flip { left: auto; right: 0; }
|
||||
```
|
||||
|
||||
**Required JS:**
|
||||
```js
|
||||
function tog(id, btn) {
|
||||
const w = document.getElementById(id);
|
||||
const p = w.querySelector('.dc-panel');
|
||||
const open = p.classList.contains('open');
|
||||
document.querySelectorAll('.dc-panel.open').forEach(x => x.classList.remove('open'));
|
||||
document.querySelectorAll('.dc-btn.open').forEach(x => x.classList.remove('open'));
|
||||
if (!open) {
|
||||
p.classList.add('open'); btn.classList.add('open');
|
||||
const r = p.getBoundingClientRect();
|
||||
p.classList.toggle('flip', r.right > window.innerWidth - 16);
|
||||
}
|
||||
}
|
||||
document.addEventListener('click', e => {
|
||||
if (!e.target.closest('.dc')) {
|
||||
document.querySelectorAll('.dc-panel.open').forEach(x => x.classList.remove('open'));
|
||||
document.querySelectorAll('.dc-btn.open').forEach(x => x.classList.remove('open'));
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Trigger visual requirements:**
|
||||
- Must look clickable (cursor pointer, border-bottom dashed or dotted)
|
||||
- Must indicate open/closed state (chevron via `::after`, or similar)
|
||||
- Color coding must match the scheme defined in the content map
|
||||
|
||||
---
|
||||
|
||||
### Lightbox
|
||||
|
||||
Full-screen overlay. Triggered by an inline button in the prose.
|
||||
|
||||
```html
|
||||
<!-- Trigger — inline in prose -->
|
||||
<button class="lb-t [color-class]" onclick="lb('[id]')">[trigger phrase]</button>
|
||||
|
||||
<!-- Lightbox — at end of body, before script tag -->
|
||||
<div class="lb-overlay" id="[id]" onclick="closeLbOv(event,'[id]')">
|
||||
<div class="lb-box [color-class]">
|
||||
<div class="lb-head [color-class]">
|
||||
<div>
|
||||
<span class="lb-eyebrow [color-class]">[eyebrow]</span>
|
||||
<span class="lb-title">[title]</span>
|
||||
</div>
|
||||
<button class="lb-close" onclick="closeLb('[id]')">✕</button>
|
||||
</div>
|
||||
<div class="lb-body">
|
||||
<!-- h3 per section, p per paragraph, lb-src link at end -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Required CSS:**
|
||||
```css
|
||||
.lb-overlay { display: none; position: fixed; inset: 0; z-index: 2000;
|
||||
align-items: center; justify-content: center; padding: 20px; }
|
||||
.lb-overlay.open { display: flex; }
|
||||
.lb-box { max-height: 88vh; overflow-y: auto; }
|
||||
.lb-head { position: sticky; top: 0; }
|
||||
```
|
||||
|
||||
**Required JS:**
|
||||
```js
|
||||
function lb(id) { document.getElementById(id).classList.add('open'); document.body.style.overflow = 'hidden'; }
|
||||
function closeLb(id) { document.getElementById(id).classList.remove('open'); document.body.style.overflow = ''; }
|
||||
function closeLbOv(e, id) { if (e.target === document.getElementById(id)) closeLb(id); }
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.key === 'Escape') {
|
||||
document.querySelectorAll('.lb-overlay.open').forEach(x => x.classList.remove('open'));
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Accordion
|
||||
|
||||
Expandable sections within educational tabs. One open at a time.
|
||||
|
||||
The accordion panel uses `<div>` — it is not inside prose, so block elements are safe here.
|
||||
|
||||
```html
|
||||
<div class="acc">
|
||||
<button class="acc-btn" onclick="acc(this)">
|
||||
<span>[heading]</span>
|
||||
<span class="acc-arrow [color-class]">▾</span>
|
||||
</button>
|
||||
<div class="acc-panel">
|
||||
<!-- p tags per paragraph -->
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Required JS:**
|
||||
```js
|
||||
function acc(btn) {
|
||||
const p = btn.nextElementSibling;
|
||||
const open = btn.classList.contains('open');
|
||||
document.querySelectorAll('.acc-btn.open').forEach(b => {
|
||||
b.classList.remove('open'); b.nextElementSibling.classList.remove('open');
|
||||
});
|
||||
if (!open) { btn.classList.add('open'); p.classList.add('open'); }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Bias Note
|
||||
|
||||
A styled callout block at the top of each analytical tab, before the first accordion.
|
||||
|
||||
```html
|
||||
<div class="bias [color-class]">
|
||||
<strong>A note:</strong> [bias note text from content map]
|
||||
</div>
|
||||
```
|
||||
|
||||
Not collapsible. Always visible. One per analytical tab.
|
||||
|
||||
---
|
||||
|
||||
### Tab Navigation
|
||||
|
||||
```html
|
||||
<nav>
|
||||
<button class="active [color-class]" onclick="go('[id]',this,'[color]')">[label]</button>
|
||||
<!-- one per tab -->
|
||||
</nav>
|
||||
```
|
||||
|
||||
```js
|
||||
function go(id, btn, col) {
|
||||
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
||||
document.querySelectorAll('nav button').forEach(b => { b.classList.remove('active'); /* remove all color classes */ });
|
||||
document.getElementById('tab-' + id).classList.add('active');
|
||||
btn.classList.add('active', col || 'white');
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
```
|
||||
|
||||
Tab content divs:
|
||||
```html
|
||||
<div class="tab [active-on-load]" id="tab-[id]">
|
||||
<!-- tab content -->
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Source Text — Markers to HTML
|
||||
|
||||
Translate content map markers into HTML components:
|
||||
|
||||
| Marker | Renders as |
|
||||
|---|---|
|
||||
| `[DECODER:id] phrase [/DECODER]` | `<span class="dc" id="id">` decoder component |
|
||||
| `[LIGHTBOX:id] phrase [/LIGHTBOX]` | `<button class="lb-t">` trigger |
|
||||
| `[ORDER] "text" [/ORDER]` | Styled display block — dialogue/order separator |
|
||||
| `[LETTER-START:sender]` | Opening of styled letter card |
|
||||
| `[LETTER-END]` | Close of letter card |
|
||||
| `[PULL-QUOTE] text [/PULL-QUOTE]` | Styled pull-quote block |
|
||||
| `[EDITORIAL] text [/EDITORIAL]` | Styled editorial aside |
|
||||
| `[SECTION-BREAK]` | `<hr>` with aesthetic treatment |
|
||||
|
||||
Letter senders each get a distinct visual treatment (border color, label, optional stamp). Define sender colors in CSS variables using the project color scheme.
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
Single `.html` file. All CSS in `<style>` in `<head>`. All JS in `<script>` immediately before `</body>`. No external dependencies except Google Fonts (loaded via `<link>`). All lightboxes placed together at the end of `<body>`, before `<script>`. All external links use `target="_blank"`.
|
||||
|
||||
---
|
||||
|
||||
## Critical Bugs (Permanent Reference)
|
||||
|
||||
**1. Block elements inside `<p>` tags silently break the DOM.**
|
||||
`<div>` inside `<p>` is invalid HTML. The browser auto-closes the `<p>`, ejecting the decoder panel. Every decoder element must be a `<span>`.
|
||||
|
||||
**2. Decoder panel must be `position: absolute`.**
|
||||
`position: relative` expands the parent span when the panel opens, collapsing the surrounding text. Use `position: absolute`.
|
||||
|
||||
**3. Decoder panels clip off the right edge.**
|
||||
After opening, check `panel.getBoundingClientRect().right > window.innerWidth - 16`. If true, add `.flip` class (`left: auto; right: 0`).
|
||||
|
||||
**4. Lightboxes placed inside tab content divs break scroll.**
|
||||
Place all lightbox overlays as direct children of `<body>`, after all tab content, before `<script>`.
|
||||
|
||||
---
|
||||
|
||||
## Output Requirements
|
||||
|
||||
- Single `.html` file
|
||||
- Source text reproduced exactly — no edits, no corrections (errors in the original stay)
|
||||
- All decoders, lightboxes, accordions, and tabs from the content map implemented
|
||||
- Bias notes present on every analytical tab
|
||||
- All external links open in new tab
|
||||
- Passes a basic sanity check: all decoder IDs referenced in prose exist in the JS/HTML
|
||||
232
skills/annotated-writing/content-mapping-fiction.md
Normal file
232
skills/annotated-writing/content-mapping-fiction.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# Content Mapping: Fiction
|
||||
|
||||
A template for producing structured annotation data from fiction and historically-situated narrative writing. Output is a `.md` content map file consumed by a build agent. Do not write HTML here.
|
||||
|
||||
---
|
||||
|
||||
## Step 0 — Classify the Source
|
||||
|
||||
Before mapping, determine:
|
||||
|
||||
- **Historically situated?** Story uses real events, places, dates, institutions → accuracy-checking is required alongside literary analysis.
|
||||
- **Pure fiction?** No historical anchors → analytical lenses only.
|
||||
- **Challenge/constraint fiction?** Written to a brief → note the constraints; they affect how you read intentionality.
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Read the Source Completely
|
||||
|
||||
Do not begin mapping until you have read the full text. Identify:
|
||||
|
||||
1. **The surface story** — what literally happens
|
||||
2. **The underneath story** — what the text is actually about (often different)
|
||||
3. **The narrator's position** — first person? Reliable? What do they not notice about themselves?
|
||||
4. **Historical claims** — any named events, dates, places, institutions, objects, honours, or technologies that can be fact-checked
|
||||
5. **Language patterns** — naming conventions, who gets interiority, who gets appearance, whose grief is legitimate
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — Choose Analytical Lenses
|
||||
|
||||
Fiction supports multiple valid readings. Choose 2–4 lenses that the text genuinely rewards. Do not force a lens onto text that doesn't earn it.
|
||||
|
||||
**Available lenses (not exhaustive):**
|
||||
|
||||
| Lens | Apply when... |
|
||||
|---|---|
|
||||
| Unreliable narrator | First-person narration; gap between what narrator claims and what text shows |
|
||||
| Male gaze / naming | Women defined by appearance or social function; asymmetric interiority |
|
||||
| Class position | Character claims outsider status but participates in the system they critique |
|
||||
| Historical accuracy | Text makes factual claims about real events, objects, or honours |
|
||||
| Epistolary / form | Story told through letters, documents — what the form conceals matters |
|
||||
| The unseen character | A character who drives the plot but never speaks or is never named |
|
||||
| Constraint analysis | Challenge fiction — how well are required elements absorbed vs engineered |
|
||||
|
||||
For each chosen lens, note: *what specific passages earn this reading?* If you can't answer, drop the lens.
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — Map Annotation Components
|
||||
|
||||
### 3a. Decoders
|
||||
|
||||
Inline interactive elements. Applied to a specific phrase in the prose. Appear on click as a floating panel.
|
||||
|
||||
**Apply a decoder when:**
|
||||
- A phrase needs factual unpacking (historical event, named place, military honour)
|
||||
- A phrase is a pivot point in the narrative that the reader might miss
|
||||
- A character classification is introduced (naming systems, taxonomy)
|
||||
- A contradiction opens between what the narrator says and what they show
|
||||
- A spelling or factual error exists in the source text
|
||||
|
||||
**Decoder metadata — use TOON for the structured fields:**
|
||||
|
||||
```toon
|
||||
decoders[N]{id,phrase,color,tag,label}:
|
||||
dec-[slug],"exact phrase from text",[default|pink|cyan|amber|red],Tag Text,Panel Heading
|
||||
```
|
||||
|
||||
**Decoder bodies — use YAML for body text (contains commas, complex content):**
|
||||
|
||||
```yaml
|
||||
decoder_bodies:
|
||||
dec-[slug]: >
|
||||
2–4 sentences. State the fact, the contradiction, or the lens observation.
|
||||
Be direct. No hedging within the panel itself — hedging belongs in bias notes.
|
||||
dec-[slug]-link: https://...
|
||||
```
|
||||
|
||||
**Color convention** (establish per-project, document here):
|
||||
- Assign one color per analytical lens or content type
|
||||
- Be consistent: if pink = unreliable narrator catches, every narrator catch is pink
|
||||
- Red = factual error or significant historical inaccuracy
|
||||
|
||||
---
|
||||
|
||||
### 3b. Lightboxes
|
||||
|
||||
Full-screen overlay panels. Triggered from inline text. Use when a topic is too large for a decoder (needs multiple sections, a timeline, or extended context).
|
||||
|
||||
**Apply a lightbox when:**
|
||||
- A decoder body would exceed 5 sentences
|
||||
- The topic has meaningful sub-sections (what it is / what the text gets right / what came after)
|
||||
- The text assumes reader knowledge of something substantial (a war, a legal concept, a cultural tradition)
|
||||
|
||||
```yaml
|
||||
lightboxes:
|
||||
lb-[slug]:
|
||||
eyebrow: Category label (e.g. "Historical Context")
|
||||
title: Lightbox heading
|
||||
color: cyan | amber | default
|
||||
sections:
|
||||
- heading: Section heading
|
||||
body: >
|
||||
Paragraph text.
|
||||
- heading: Section heading
|
||||
body: >
|
||||
Paragraph text.
|
||||
source_url: https://...
|
||||
source_label: Link label text
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3c. Accordions
|
||||
|
||||
Expandable sections within educational tabs. One open at a time.
|
||||
|
||||
```yaml
|
||||
accordions:
|
||||
tab-[tab-id]:
|
||||
- heading: Question or section title
|
||||
body: >
|
||||
Extended prose. Can be multiple paragraphs. Separate with blank lines.
|
||||
**Bold** for emphasis. No decoders inside accordions.
|
||||
- heading: ...
|
||||
body: >
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3d. Tab Architecture
|
||||
|
||||
Four tabs is the default. Rename to fit the content.
|
||||
|
||||
```toon
|
||||
tabs[4]{id,label,color,purpose}:
|
||||
story,"The Story",white,Full source text with inline decoders and lightbox triggers
|
||||
[lens-1-id],[Lens 1 Name],[color],Educational deep-dive on first analytical lens
|
||||
[lens-2-id],[Lens 2 Name],[color],Educational deep-dive on second analytical lens
|
||||
further,"Further Reading",white,Curated external links
|
||||
```
|
||||
|
||||
Add a fifth tab only if the text genuinely requires it. Three lenses in three tabs is acceptable if all three are earned.
|
||||
|
||||
---
|
||||
|
||||
### 3e. Further Reading
|
||||
|
||||
```toon
|
||||
further_reading[N]{group,title,url,desc,color}:
|
||||
"Lens 1","Link Title","https://...","One-line description",default
|
||||
"Lens 1","Link Title","https://...","One-line description",default
|
||||
"Lens 2","Link Title","https://...","One-line description",cyan
|
||||
```
|
||||
|
||||
Groups correspond to tabs. Use the same color as the tab they belong to.
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Bias Notes
|
||||
|
||||
Every analytical tab requires one bias note. Placed at the top of the tab, before the accordions.
|
||||
|
||||
Rules:
|
||||
- One sentence acknowledging the limitation. Then stop.
|
||||
- State the specific bias, not a generic disclaimer.
|
||||
- If you have a preference for the narrator or a character, say so — it shapes the analysis.
|
||||
- Do not write "I am an AI" — write what the actual bias is.
|
||||
|
||||
```yaml
|
||||
bias_notes:
|
||||
tab-[lens-1-id]: >
|
||||
One sentence. Specific bias. What it shapes in the analysis below.
|
||||
tab-[lens-2-id]: >
|
||||
One sentence. Specific bias.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — Historical Accuracy (if applicable)
|
||||
|
||||
If the source text makes historical claims, produce an accuracy table before the decoder map.
|
||||
|
||||
```toon
|
||||
historical_claims[N]{claim,verdict,detail}:
|
||||
"Claim as stated in text",accurate,"Supporting detail or correction"
|
||||
"Claim as stated in text",inaccurate,"What is actually true; what error was made"
|
||||
"Claim as stated in text",plausible,"Consistent with the period; unverifiable at this level of detail"
|
||||
"Claim as stated in text",anachronism,"Object/concept/institution did not exist at the stated time"
|
||||
```
|
||||
|
||||
Inaccurate claims must become decoder annotations in the source text. Use `color: red`.
|
||||
|
||||
---
|
||||
|
||||
## Step 6 — The Story Section
|
||||
|
||||
Format the source text for the build agent. The text is sacred — reproduce it exactly including original spelling errors. Mark decoder and lightbox trigger points.
|
||||
|
||||
Use this notation inline in the prose block:
|
||||
|
||||
```
|
||||
[DECODER:dec-slug] exact phrase in text [/DECODER]
|
||||
[LIGHTBOX:lb-slug] phrase that triggers lightbox [/LIGHTBOX]
|
||||
[ORDER] "Dialogue that functions as a section break or order" [/ORDER]
|
||||
[LETTER-START:muriel|marcus|neutral] [/LETTER-START]
|
||||
[LETTER-END] [/LETTER-END]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output Format
|
||||
|
||||
The completed content map is a single `.md` file structured as:
|
||||
|
||||
```
|
||||
# Content Map: [Story Title]
|
||||
|
||||
## Source Classification
|
||||
## Chosen Lenses
|
||||
## Historical Accuracy Table (if applicable)
|
||||
## Tab Definitions (TOON)
|
||||
## Decoders (TOON metadata + YAML bodies)
|
||||
## Lightboxes (YAML)
|
||||
## Accordions (YAML)
|
||||
## Bias Notes (YAML)
|
||||
## Further Reading (TOON)
|
||||
## Source Text (annotated)
|
||||
```
|
||||
|
||||
This file is the complete specification for the build agent. The build agent needs nothing else except `annotated-writing-build.md`.
|
||||
229
skills/annotated-writing/content-mapping-non-fiction.md
Normal file
229
skills/annotated-writing/content-mapping-non-fiction.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# Content Mapping: Non-Fiction
|
||||
|
||||
A template for producing structured annotation data from essays, journalism, historical documents, speeches, and analytical writing. Output is a `.md` content map file consumed by a build agent. Do not write HTML here.
|
||||
|
||||
---
|
||||
|
||||
## Step 0 — Classify the Source
|
||||
|
||||
Determine the non-fiction subtype. It affects which decoders and tabs are appropriate.
|
||||
|
||||
| Subtype | Primary annotation task |
|
||||
|---|---|
|
||||
| Historical document | Contextualise; decode named people, events, institutions; note anachronisms |
|
||||
| Political speech / propaganda | Decode rhetoric; note what is claimed vs what is true; note audience |
|
||||
| Scientific or technical writing | Decode concepts; assess claims against current consensus |
|
||||
| Journalism / reportage | Verify facts; note sourcing; note what is and isn't attributed |
|
||||
| Personal essay / memoir | Unreliability of memory; note what the author can't know about themselves |
|
||||
| Legal or policy document | Decode jargon; note what the language does vs what it says |
|
||||
|
||||
A single source may span subtypes. Identify the dominant one and note the secondary.
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Read the Source Completely
|
||||
|
||||
Before mapping, identify:
|
||||
|
||||
1. **The argument** — what position is the text advancing?
|
||||
2. **The evidence** — what does it cite, quote, or invoke in support?
|
||||
3. **The gaps** — what would a critical reader notice is absent, unattributed, or assumed?
|
||||
4. **The moment** — when was this written, and what was happening? What has happened since?
|
||||
5. **Named entities** — every person, place, institution, date, law, statistic, or event that can be verified
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — Choose Analytical Lenses
|
||||
|
||||
Non-fiction lenses differ from fiction. Choose 2–3 that the text genuinely rewards.
|
||||
|
||||
| Lens | Apply when... |
|
||||
|---|---|
|
||||
| Rhetorical analysis | Text is designed to persuade; identify the moves (ethos, pathos, logos, omission) |
|
||||
| Historical accuracy | Text makes factual claims; some may be wrong, outdated, or contested |
|
||||
| Source and attribution | Who is cited, who isn't, what is stated as fact without a source |
|
||||
| The argument vs the evidence | Does the evidence actually support the conclusion drawn? |
|
||||
| Who is speaking / who is silent | Whose perspective structures the account? Who is absent? |
|
||||
| Language and framing | Word choices that carry implicit assumptions (e.g. "developed" vs "developing") |
|
||||
| What changed after | The text was written at a specific moment; what do we know now that the author didn't? |
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — Map Annotation Components
|
||||
|
||||
### 3a. Decoders
|
||||
|
||||
Apply a decoder when:
|
||||
- A technical term, acronym, or proper noun requires unpacking
|
||||
- A named person, institution, or event is invoked without explanation
|
||||
- A claim is contested or has been updated since publication
|
||||
- The text uses language that carries implicit assumptions (framing, euphemism, loaded terms)
|
||||
- A rhetorical move is worth naming (strawman, appeal to authority, etc.)
|
||||
|
||||
```toon
|
||||
decoders[N]{id,phrase,color,tag,label}:
|
||||
dec-[slug],"exact phrase from text",[default|pink|cyan|amber|red],Tag Text,Panel Heading
|
||||
```
|
||||
|
||||
```yaml
|
||||
decoder_bodies:
|
||||
dec-[slug]: >
|
||||
What it is, what it means in context, why it matters here.
|
||||
For contested claims: state what the text says, what the evidence shows.
|
||||
For rhetorical moves: name the move, describe its effect.
|
||||
dec-[slug]-link: https://...
|
||||
```
|
||||
|
||||
**Color convention** (establish per-project):
|
||||
- Assign colors by lens or content type, document the scheme here
|
||||
- Red = factual error, outdated claim, or significantly misleading statement
|
||||
|
||||
---
|
||||
|
||||
### 3b. Lightboxes
|
||||
|
||||
Apply a lightbox when:
|
||||
- An event, institution, or concept requires substantial background
|
||||
- A claim is embedded in a debate too large for a tooltip
|
||||
- The "what came after" context fundamentally changes the reading
|
||||
|
||||
```yaml
|
||||
lightboxes:
|
||||
lb-[slug]:
|
||||
eyebrow: Category label
|
||||
title: Lightbox heading
|
||||
color: cyan | amber | default
|
||||
sections:
|
||||
- heading: What it was
|
||||
body: >
|
||||
Background.
|
||||
- heading: What the text claims
|
||||
body: >
|
||||
Specific claim and its accuracy.
|
||||
- heading: What came after
|
||||
body: >
|
||||
Subsequent developments that reframe the text.
|
||||
source_url: https://...
|
||||
source_label: Link label
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3c. Accordions
|
||||
|
||||
For non-fiction, accordions structure the analytical tabs. Common patterns:
|
||||
|
||||
**For the "Historical Moment" tab:**
|
||||
- What was happening when this was written
|
||||
- Who was the intended audience
|
||||
- How the text was received
|
||||
- What has changed since
|
||||
|
||||
**For the "The Argument" tab:**
|
||||
- What the text claims
|
||||
- What evidence it uses
|
||||
- Where the evidence is strong
|
||||
- Where the argument has gaps or has been contested
|
||||
|
||||
```yaml
|
||||
accordions:
|
||||
tab-[tab-id]:
|
||||
- heading: Section heading
|
||||
body: >
|
||||
Prose. Direct. No hedging within accordion bodies.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3d. Tab Architecture
|
||||
|
||||
```toon
|
||||
tabs[4]{id,label,color,purpose}:
|
||||
text,"The Text",white,Full source with inline decoders and lightbox triggers
|
||||
[analysis-id],[Analysis Tab Name],[color],Core argument and evidence
|
||||
[context-id],[Context Tab Name],[color],Historical moment; what came after
|
||||
further,"Further Reading",white,Curated external links
|
||||
```
|
||||
|
||||
For non-fiction, the "context" tab is almost always warranted as a standalone tab. The text's moment is not decorative — it is part of what you are teaching.
|
||||
|
||||
---
|
||||
|
||||
### 3e. Further Reading
|
||||
|
||||
```toon
|
||||
further_reading[N]{group,title,url,desc,color}:
|
||||
"Group Name","Title","https://...","Description",default
|
||||
```
|
||||
|
||||
Groups should correspond to tabs. For non-fiction, a "Primary Sources" group is often useful — direct the reader to the original documents, not just secondary commentary.
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Bias Notes
|
||||
|
||||
Every analytical tab requires one bias note.
|
||||
|
||||
Non-fiction bias notes are especially important because the text being analysed often has its own point of view, and the analyst's agreement or disagreement shapes everything.
|
||||
|
||||
State: what tradition your analysis comes from, whether you find the text's argument credible, and what that means for the reading below.
|
||||
|
||||
```yaml
|
||||
bias_notes:
|
||||
tab-[analysis-id]: >
|
||||
One sentence. What tradition this analysis comes from, or what credence I give the argument, and how that shapes what follows.
|
||||
tab-[context-id]: >
|
||||
One sentence. What sources my historical framing relies on, and whose perspective they represent.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — Fact-Checking Protocol
|
||||
|
||||
Non-fiction requires an accuracy table. All named facts — statistics, dates, attributions, historical claims — should be checked.
|
||||
|
||||
```toon
|
||||
fact_checks[N]{claim,verdict,detail}:
|
||||
"Exact claim as stated",accurate,"Source"
|
||||
"Exact claim as stated",inaccurate,"What is actually true"
|
||||
"Exact claim as stated",contested,"Summarise the debate"
|
||||
"Exact claim as stated",outdated,"What has changed since publication"
|
||||
"Exact claim as stated",unverifiable,"Cannot be confirmed or refuted with available sources"
|
||||
```
|
||||
|
||||
Inaccurate and contested claims become red decoder annotations in the text.
|
||||
|
||||
Outdated claims become amber decoder annotations — the original claim was accurate at time of writing but has since changed.
|
||||
|
||||
---
|
||||
|
||||
## Step 6 — Source Text Section
|
||||
|
||||
Reproduce the text exactly. Mark annotation trigger points:
|
||||
|
||||
```
|
||||
[DECODER:dec-slug] exact phrase [/DECODER]
|
||||
[LIGHTBOX:lb-slug] trigger phrase [/LIGHTBOX]
|
||||
[PULL-QUOTE] sentence worth isolating [/PULL-QUOTE]
|
||||
[EDITORIAL] (Ed.) note or aside [/EDITORIAL]
|
||||
[SECTION-BREAK] --- [/SECTION-BREAK]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output Format
|
||||
|
||||
```
|
||||
# Content Map: [Text Title]
|
||||
|
||||
## Source Classification
|
||||
## Chosen Lenses
|
||||
## Fact-Check Table (TOON)
|
||||
## Tab Definitions (TOON)
|
||||
## Decoders (TOON metadata + YAML bodies)
|
||||
## Lightboxes (YAML)
|
||||
## Accordions (YAML)
|
||||
## Bias Notes (YAML)
|
||||
## Further Reading (TOON)
|
||||
## Source Text (annotated)
|
||||
```
|
||||
Reference in New Issue
Block a user