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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,11 @@ audience: everyone
section: original-essays
comments: enabled
---

Start the article body here. Do not repeat the front-matter title or subtitle as
the first heading or paragraph; those values are written to Substack's dedicated
header fields. The CLI defensively removes exact leading repetitions, but users
and authoring agents should emit each title and subtitle only once.
```

Media examples:
Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.3/schema.json",
"$schema": "https://biomejs.dev/schemas/2.5.7/schema.json",
"assist": { "actions": { "source": { "organizeImports": "off" } } },
"linter": {
"enabled": true,
Expand Down
7 changes: 7 additions & 0 deletions conductor/archive/T18-01/contracts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"schemaVersion": 1,
"trackId": "T18-01",
"contractIds": ["PARSER-AST-006", "FEATURE-FIDELITY-008", "UX-CLI-CONTRACT-005"],
"programmeIssue": 184,
"project": 38
}
18 changes: 18 additions & 0 deletions conductor/archive/T18-01/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Design T18-01

```mermaid
flowchart LR
A["Markdown source"] --> B["Parse front matter and body"]
B --> C["Resolve title"]
C --> D{"Leading block exactly matches title?"}
D -->|Yes| E["Remove title block"]
D -->|No| F["Preserve block"]
E --> G{"Next block exactly matches subtitle?"}
F --> G
G -->|Yes| H["Remove subtitle block"]
G -->|No| I["Preserve body"]
H --> J["Synchronized prepared post"]
I --> J
```

Matching uses rendered block text with surrounding whitespace trimmed. Removal is limited to the first eligible title block and immediately leading subtitle block.
7 changes: 7 additions & 0 deletions conductor/archive/T18-01/implementation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Implementation T18-01

- Exact leading explicit title headings or paragraphs are removed.
- Heading-derived title fallback remains supported when front matter has no title.
- Exact leading subtitle headings or paragraphs are removed after title normalization.
- Markdown, HTML, and ProseMirror representations remain synchronized.
- Canonical examples and agent/user guidance no longer repeat header metadata.
9 changes: 9 additions & 0 deletions conductor/archive/T18-01/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# T18-01 Metadata/body de-duplication correctness

- [Specification](./spec.md)
- [Requirements](./requirements.md)
- [Design](./design.md)
- [Plan](./plan.md)
- [Verification](./verification.md)
- [Metadata](./metadata.json)
- [GitHub issue #537](https://github.com/edithatogo/substack-cli-ts/issues/537)
12 changes: 12 additions & 0 deletions conductor/archive/T18-01/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"trackId": "T18-01",
"title": "Metadata/body de-duplication correctness",
"type": "bug",
"status": "archived",
"parentIssue": 538,
"issue": 537,
"project": 38,
"createdAt": "2026-08-10T23:30:00+10:00",
"updatedAt": "2026-08-10T23:55:00+10:00",
"archivedAt": "2026-08-10T23:55:00+10:00"
}
23 changes: 23 additions & 0 deletions conductor/archive/T18-01/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Plan T18-01

## Phase 1: Reproduction and contract

- [x] Task: Reproduce title/subtitle metadata duplication and identify all shared preparation paths.
- [x] Task: Define MoSCoW requirements, risks, and Mermaid design.
- [x] Task: Register P18/T18-01 and nested task issues.
- [x] Task: Phase verification and checkpoint per `conductor/workflow.md`.

## Phase 2: Test-driven correction

- [x] Task: Add exact title/subtitle and formatting regression tests.
- [x] Task: Add mismatch, later-match, and fallback preservation tests.
- [x] Task: Normalize leading metadata blocks at `preparePost()`.
- [x] Task: Phase verification and checkpoint per `conductor/workflow.md`.

## Phase 3: Guidance and closeout

- [x] Task: Correct checked-in examples and document canonical agent/user input.
- [x] Task: Apply review finding for explicit paragraph title duplication.
- [x] Task: Run focused and required hosted verification.
- [x] Task: Review Actions and comments, merge, archive, and clean up.
- [x] Task: Phase verification and checkpoint per `conductor/workflow.md`.
21 changes: 21 additions & 0 deletions conductor/archive/T18-01/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Requirements T18-01

## Must

- Remove exact leading metadata repetitions at the shared preparation boundary.
- Keep Markdown, HTML, and ProseMirror representations synchronized.
- Add deterministic regression and preservation tests.
- Correct examples and document the agent authoring contract.

## Should

- Treat inline formatting as presentation rather than a text mismatch.
- Preserve title fallback when title front matter is absent.

## Could

- Add future diagnostics for near-matching title/deck content.

## Won't

- Remove content based on fuzzy, semantic, or LLM judgment.
5 changes: 5 additions & 0 deletions conductor/archive/T18-01/risks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Risks T18-01

- Over-broad deletion could remove legitimate editorial content; exact rendered-text equality and leading-position constraints mitigate this.
- Divergence between Markdown, HTML, and ProseMirror forms could affect validation; all three are normalized together and tested.
- Agent guidance alone is insufficient; the shared runtime boundary remains defensive.
19 changes: 19 additions & 0 deletions conductor/archive/T18-01/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Track T18-01: Metadata/body de-duplication correctness

## Overview

Prevent front-matter title and subtitle values from appearing again at the start of the article body while preserving legitimate editorial content and heading-derived title fallback.

## Acceptance criteria

- Exact leading title headings and subtitle paragraphs/headings are absent from prepared Markdown, HTML, and ProseMirror content.
- Formatting does not prevent exact rendered subtitle matching.
- Non-matching headings, standfirsts, and later matching text remain untouched.
- Title fallback from a leading heading without front matter remains supported.
- Examples and agent-facing guidance use one canonical metadata/body shape.

## Out of scope

- Fuzzy or semantic deletion of similar content.
- Editing already-created Substack drafts.
- Changing Substack title or subtitle field selectors.
11 changes: 11 additions & 0 deletions conductor/archive/T18-01/verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Verification T18-01

- Issue reproduction: confirmed.
- Focused regression tests: 14 passed.
- Full test suite: 117 files and 933 tests passed.
- TypeScript typecheck: passed.
- Contract generation check: passed.
- Programme drift check before closeout: passed.
- Conductor review: one paragraph-title gap found, fixed, and reverified.
- Required hosted checks: pending PR.
- Review comments: pending PR.
127 changes: 127 additions & 0 deletions conductor/contracts/substack-cli-maturity.contract.json
Original file line number Diff line number Diff line change
Expand Up @@ -1701,6 +1701,15 @@
"T11-03"
],
"status": "planned"
},
{
"phaseId": "P18",
"title": "Metadata/body de-duplication correctness",
"releaseTarget": "next patch",
"tracks": [
"T18-01"
],
"status": "contract_verified"
}
],
"tracks": [
Expand Down Expand Up @@ -2571,6 +2580,26 @@
"url": "https://github.com/edithatogo/substack-cli-ts/issues/457",
"title": "T11-03 Prompt retirement and canonical-system handover"
}
},
{
"id": "T18-01",
"phaseId": "P18",
"title": "Metadata/body de-duplication correctness",
"status": "contract_verified",
"contractIds": [
"PARSER-AST-006",
"FEATURE-FIDELITY-008",
"UX-CLI-CONTRACT-005"
],
"requiredTaskCount": 3,
"existingIssues": [
537
],
"issue": {
"number": 537,
"url": "https://github.com/edithatogo/substack-cli-ts/issues/537",
"title": "Prevent title and subtitle duplication in published post bodies"
}
}
],
"tasks": [
Expand Down Expand Up @@ -7095,6 +7124,75 @@
"GOV-PROMPT-RETIREMENT-006"
],
"release": "1.0 and beyond"
},
{
"id": "T18-01-TASK-01",
"title": "Add metadata-prefix regression coverage",
"trackId": "T18-01",
"phaseId": "P18",
"status": "contract_verified",
"contractIds": [
"PARSER-AST-006",
"FEATURE-FIDELITY-008",
"UX-CLI-CONTRACT-005"
],
"issue": {
"number": 539,
"url": "https://github.com/edithatogo/substack-cli-ts/issues/539",
"title": "Add metadata-prefix regression coverage"
},
"mustContractIds": [
"PARSER-AST-006",
"FEATURE-FIDELITY-008",
"UX-CLI-CONTRACT-005"
],
"release": "next patch"
},
{
"id": "T18-01-TASK-02",
"title": "Normalize exact title and subtitle prefixes",
"trackId": "T18-01",
"phaseId": "P18",
"status": "contract_verified",
"contractIds": [
"PARSER-AST-006",
"FEATURE-FIDELITY-008",
"UX-CLI-CONTRACT-005"
],
"issue": {
"number": 540,
"url": "https://github.com/edithatogo/substack-cli-ts/issues/540",
"title": "Normalize exact title and subtitle prefixes"
},
"mustContractIds": [
"PARSER-AST-006",
"FEATURE-FIDELITY-008",
"UX-CLI-CONTRACT-005"
],
"release": "next patch"
},
{
"id": "T18-01-TASK-03",
"title": "Correct examples and agent authoring guidance",
"trackId": "T18-01",
"phaseId": "P18",
"status": "contract_verified",
"contractIds": [
"PARSER-AST-006",
"FEATURE-FIDELITY-008",
"UX-CLI-CONTRACT-005"
],
"issue": {
"number": 541,
"url": "https://github.com/edithatogo/substack-cli-ts/issues/541",
"title": "Correct examples and agent authoring guidance"
},
"mustContractIds": [
"PARSER-AST-006",
"FEATURE-FIDELITY-008",
"UX-CLI-CONTRACT-005"
],
"release": "next patch"
}
],
"issueMap": {
Expand Down Expand Up @@ -7175,6 +7273,11 @@
"url": "https://github.com/edithatogo/substack-cli-ts/issues/446",
"title": "P11 1.0 governance and post-1.0 roadmap",
"parentPhaseLink": "already"
},
"P18": {
"number": 538,
"url": "https://github.com/edithatogo/substack-cli-ts/issues/538",
"title": "P18 Metadata/body de-duplication correctness"
}
},
"trackIssues": {
Expand Down Expand Up @@ -7453,6 +7556,12 @@
"url": "https://github.com/edithatogo/substack-cli-ts/issues/457",
"title": "T11-03 Prompt retirement and canonical-system handover",
"parentTrackLink": "already"
},
"T18-01": {
"number": 537,
"url": "https://github.com/edithatogo/substack-cli-ts/issues/537",
"title": "Prevent title and subtitle duplication in published post bodies",
"parentTrackLink": "already"
}
},
"taskIssues": {
Expand Down Expand Up @@ -8601,6 +8710,24 @@
"url": "https://github.com/edithatogo/substack-cli-ts/issues/461",
"title": "T11-03 T11-03-TASK-04",
"parentTaskLink": "already"
},
"T18-01-TASK-01": {
"number": 539,
"url": "https://github.com/edithatogo/substack-cli-ts/issues/539",
"title": "Add metadata-prefix regression coverage",
"parentTaskLink": "already"
},
"T18-01-TASK-02": {
"number": 540,
"url": "https://github.com/edithatogo/substack-cli-ts/issues/540",
"title": "Normalize exact title and subtitle prefixes",
"parentTaskLink": "already"
},
"T18-01-TASK-03": {
"number": 541,
"url": "https://github.com/edithatogo/substack-cli-ts/issues/541",
"title": "Correct examples and agent authoring guidance",
"parentTaskLink": "already"
}
}
},
Expand Down
38 changes: 38 additions & 0 deletions conductor/programme-state.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@
"issue": 446,
"state": "OPEN",
"status": "Todo"
},
{
"id": "P18",
"issue": 538,
"state": "CLOSED",
"status": "Done"
}
],
"tracks": [
Expand Down Expand Up @@ -454,6 +460,14 @@
"state": "OPEN",
"status": "Todo",
"evidence": "conductor/tracks/T11-03/verification.md"
},
{
"id": "T18-01",
"phase": "P18",
"issue": 537,
"state": "CLOSED",
"status": "Done",
"evidence": "conductor/archive/T18-01/verification.md"
}
],
"tasks": [
Expand Down Expand Up @@ -1984,6 +1998,30 @@
"state": "OPEN",
"status": "Todo",
"evidence": "conductor/tracks/T11-03/verification.md"
},
{
"id": "T18-01-TASK-01",
"track": "T18-01",
"issue": 539,
"state": "CLOSED",
"status": "Done",
"evidence": "conductor/archive/T18-01/verification.md"
},
{
"id": "T18-01-TASK-02",
"track": "T18-01",
"issue": 540,
"state": "CLOSED",
"status": "Done",
"evidence": "conductor/archive/T18-01/verification.md"
},
{
"id": "T18-01-TASK-03",
"track": "T18-01",
"issue": 541,
"state": "CLOSED",
"status": "Done",
"evidence": "conductor/archive/T18-01/verification.md"
}
],
"supplemental": [
Expand Down
Loading
Loading