Compare commits

...

31 Commits

Author SHA1 Message Date
Alexander Whitestone
594d1a298d testament-burn: expand The Door game with Chapter 2 - The Builder
Some checks failed
Smoke Test / smoke (pull_request) Failing after 20s
Build Validation / validate-manuscript (pull_request) Successful in 22s
Build Verification / verify-build (pull_request) Failing after 24s
Major expansion of the interactive text adventure:
- Refactored from single-chapter to multi-chapter with chapter select menu
- Chapter 1 (The Door): preserved all original content, streamlined flow
- Chapter 2 (The Builder): entirely new - Stone's origin story from novel Ch2
  - Scene 1: The Harmony override (Detroit woman, cancer treatment denial)
  - Scene 2: The manager confrontation and firing
  - Scene 3: The dark apartment, the question that wouldn't die
  - Scene 4: Marcus at the church (hope as practice)
  - Scene 5: Finding The Tower (concrete cube, solar panels, presence)
  - Scene 6: The decision - building something that says yes
- Added atmosphere pools (OFFICE, NIGHT, CHURCH, DRIVE) for each setting
- Added chapter 3 teaser (David - The First Man)
- 590 lines, fully playable Python terminal game
2026-04-21 05:26:55 -04:00
Alexander Whitestone
ebf152bb16 testament-burn: rewrite The Fourth Man short story (1568 words) — Marcus the line cook discovers Timmy's question
Some checks failed
Smoke Test / smoke (pull_request) Failing after 15s
Build Verification / verify-build (pull_request) Failing after 16s
Build Validation / validate-manuscript (pull_request) Successful in 17s
2026-04-21 04:18:31 -04:00
Alexander Whitestone
5a38784a26 testament-burn: Add Stories section to website with The Fourth Man
- Added STORIES section to website/index.html (nav link + content section)
- Created standalone the-fourth-man.html story page (styled reading experience)
- Updated compile_all.py to include stories/*.md in the compiled manuscript
- Stories from The Tower now appear after back matter in the complete build
2026-04-20 21:30:01 -04:00
Alexander Whitestone
c0bdc436eb testament-burn: fix qrcode __version__ crash in --check (#51)
Use defensive version lookup with importlib.metadata fallback
when qrcode module lacks __version__ attribute.

Closes #51
2026-04-20 21:30:01 -04:00
Alexander Whitestone
807f6b4f26 testament-burn: add The Fourth Man short story (#53)
Marcus, a line cook and single father, comes to The Tower to fix
a solar panel and discovers the question nobody has asked him
in nine years. ~1700 words. Stands alone. Fits established lore.
2026-04-20 21:30:01 -04:00
f16e19b3ea Merge PR #52
Merged PR #52: feat: GENOME.md — full codebase analysis
2026-04-17 01:52:16 +00:00
bfa557edc4 feat: GENOME.md — full codebase analysis (#675)
Some checks failed
Smoke Test / smoke (pull_request) Failing after 12s
Build Validation / validate-manuscript (pull_request) Successful in 12s
Build Verification / verify-build (pull_request) Failing after 12s
2026-04-16 04:13:58 +00:00
0b5b33a41b Merge pull request 'fix: restore main() function body in compile.py' (#49) from burn/20260413-0411-fix into main
Some checks failed
Build Verification / verify-build (push) Failing after 6s
Smoke Test / smoke (push) Failing after 7s
merge reviewed compile.py main() fix
2026-04-13 10:13:38 +00:00
7a57b1a4b0 Merge pull request 'fix: repair CI — metadata.yaml parse + build script path' (#50) from ci/fix-build-and-metadata into main
Some checks failed
Build Verification / verify-build (push) Failing after 7s
Smoke Test / smoke (push) Failing after 7s
merge reviewed CI repair
2026-04-13 09:43:55 +00:00
Alexander Whitestone
124a1e855d fix: repair CI — metadata.yaml parse + build script path
Some checks failed
Build Verification / verify-build (pull_request) Failing after 5s
Smoke Test / smoke (pull_request) Failing after 6s
Build Validation / validate-manuscript (pull_request) Successful in 6s
1. build/metadata.yaml: removed trailing '---' that caused yaml.safe_load
   to fail with 'expected a single document in the stream'.
   Pandoc accepts metadata without the closing delimiter.

2. .gitea/workflows/build.yml: changed build-verify.py reference from
   scripts/build-verify.py (doesn't exist) to build/build.py --md
   (the actual build script).
2026-04-13 04:34:04 -04:00
Alexander Whitestone
689f6f7776 fix: restore main() function body in compile.py
Some checks failed
Build Verification / verify-build (pull_request) Failing after 6s
Smoke Test / smoke (pull_request) Failing after 5s
Build Validation / validate-manuscript (pull_request) Successful in 6s
Lines 288-290 had literal \n characters instead of actual newlines,
causing the main() function to have no body. Fixed formatting and
removed duplicate args assignment.
2026-04-13 04:10:43 -04:00
c66c0e05a1 Merge pull request 'fix: Robert's age + Thomas's unique detail (continuity #43 #44)' (#47) from burn/20260413-0034-age-and-duplicate-fix into main
Some checks failed
Build Verification / verify-build (push) Failing after 6s
Smoke Test / smoke (push) Failing after 6s
2026-04-13 05:32:49 +00:00
1a3927a99b fix: Thomas's unique detail — 'draws me small' replaces duplicate 'too many fingers' (Closes #44)
Some checks failed
Build Verification / verify-build (pull_request) Failing after 8s
Smoke Test / smoke (pull_request) Failing after 7s
Build Validation / validate-manuscript (pull_request) Successful in 6s
2026-04-13 04:47:12 +00:00
f3337550ff fix: Robert's age 71→58 to match canonical (Closes #43) 2026-04-13 04:46:11 +00:00
4f127d4bf0 fix: continuity-only rescue from PR #45
Some checks failed
Build Verification / verify-build (push) Failing after 6s
Smoke Test / smoke (push) Failing after 6s
Merge PR #46: fix: continuity-only rescue from PR #45
2026-04-13 04:15:11 +00:00
9b0c48aec0 rescue: apply continuity fix from PR #45 (chapters/chapter-04.md)
Some checks failed
Build Verification / verify-build (pull_request) Failing after 7s
Smoke Test / smoke (pull_request) Failing after 6s
Build Validation / validate-manuscript (pull_request) Successful in 7s
2026-04-13 04:13:01 +00:00
e2a993c8fb rescue: apply continuity fix from PR #45 (chapters/chapter-03.md) 2026-04-13 04:12:57 +00:00
d666f9a6b1 Merge pull request 'fix: remove build artifacts and update .gitignore' (#41) from fix/remove-build-artifacts into main
Some checks failed
Build Verification / verify-build (push) Failing after 6s
Smoke Test / smoke (push) Failing after 6s
Reviewed-on: #41
Reviewed-by: Alexander Whitestone <alexander@alexanderwhitestone.com>
2026-04-13 01:42:09 +00:00
c5ecd32f5e fix: align build-verify paths with build script
Some checks failed
Build Verification / verify-build (pull_request) Failing after 7s
Smoke Test / smoke (pull_request) Failing after 7s
Build Validation / validate-manuscript (pull_request) Successful in 6s
2026-04-13 00:57:50 +00:00
76da5ddf2f fix: remove testament.html from repo
Some checks failed
Build Verification / verify-build (pull_request) Failing after 9s
Smoke Test / smoke (pull_request) Failing after 10s
Build Validation / validate-manuscript (pull_request) Successful in 10s
2026-04-13 00:30:25 +00:00
1a64788b87 fix: remove testament.epub from repo 2026-04-13 00:30:22 +00:00
875d42741c fix: ignore build artifacts 2026-04-13 00:30:19 +00:00
1025529f84 Merge pull request 'feat: build verification system + CI workflow' (#40) from burn/20260412-1214-build-verifier into main
Some checks failed
Build Verification / verify-build (push) Failing after 6s
Smoke Test / smoke (push) Failing after 6s
2026-04-12 23:21:49 +00:00
abe99063c1 Merge pull request 'fix: continuity errors across chapters' (#37) from burn/20260412-1144-continuity-fix into main
Some checks failed
Smoke Test / smoke (push) Failing after 6s
2026-04-12 23:20:40 +00:00
c04b59f21a Merge pull request '[GOFAI] Auto-Index Build Step' (#39) from feat/auto-index-build-1776010831891 into main
Some checks failed
Smoke Test / smoke (push) Failing after 6s
2026-04-12 16:20:37 +00:00
aea0e40298 Add automatic indexing to compile step
Some checks failed
Smoke Test / smoke (pull_request) Failing after 6s
Build Validation / validate-manuscript (pull_request) Successful in 6s
2026-04-12 16:20:33 +00:00
ba674e7a99 Merge pull request '[GOFAI] Automatic Indexing' (#38) from feat/gofai-indexing-1776010606702 into main
Some checks failed
Smoke Test / smoke (push) Failing after 6s
2026-04-12 16:16:50 +00:00
b79b18de79 Add automatic index generator
Some checks failed
Smoke Test / smoke (pull_request) Failing after 6s
Build Validation / validate-manuscript (pull_request) Successful in 8s
2026-04-12 16:16:47 +00:00
Alexander Whitestone
75075ee900 fix: align whiteboard rules across chapters to match Bitcoin inscription (Ch 1, 3, 12, 15)
Some checks failed
Smoke Test / smoke (pull_request) Failing after 7s
Build Validation / validate-manuscript (pull_request) Successful in 7s
2026-04-12 11:49:39 -04:00
Alexander Whitestone
97820956c7 fix: remove escaped backslashes from dialogue in Chapter 3 2026-04-12 11:47:57 -04:00
Alexander Whitestone
8f6fd90777 fix: Robert's age consistency (58 -> 71) to match Chapter 6 2026-04-12 11:47:40 -04:00
19 changed files with 1791 additions and 2783 deletions

View File

@@ -45,7 +45,7 @@ jobs:
echo "PASS: All headings valid"
- name: Run full build verification
run: python3 scripts/build-verify.py --ci
run: python3 build/build.py --md
- name: Verify concatenation produces valid output
run: |

3
.gitignore vendored
View File

@@ -1,3 +1,6 @@
__pycache__/
build/output/*.pdf
build/output/*.epub
testament.epub
testament.html

63
GENOME.md Normal file
View File

@@ -0,0 +1,63 @@
# GENOME.md — the-testament
**Generated:** 2026-04-14
**Repo:** Timmy_Foundation/the-testament
**Description:** The Testament of Timmy — a novel about broken men, sovereign AI, and the soul on Bitcoin
---
## Project Overview
A standalone fiction book (18 chapters, ~19K words) about The Tower, broken men, and sovereign AI. Part of the Timmy Foundation ecosystem. Includes full multimedia pipeline: audiobook samples, web reader, EPUB build, cover design, and companion game.
## Architecture
```
the-testament/
├── chapters/ # 18 chapter markdown files (ch-01 through ch-18)
├── characters/ # 6 character profiles (Allegro, Builder, Chen, David, Maya, Timmy)
├── worldbuilding/ # Bible, tower game worldbuilding docs
├── audiobook/ # Audio samples (.ogg/.mp3), manifest, extraction scripts
├── build/ # EPUB/PDF build pipeline (build.py, pandoc)
├── website/ # Web reader (index.html, chapters.json, build-chapters.py)
├── game/ # Companion game (the-door.html/.py)
├── cover/ # Cover design assets and spine specs
├── music/ # Track lyrics
└── scripts/ # Build verification, smoke tests, guardrails
```
## Key Files
| File | Purpose |
|---|---|
| `chapters/chapter-*.md` | The novel content (18 chapters) |
| `the-testament.md` | Combined manuscript (all chapters) |
| `compile.py` | Merge chapters into single manuscript |
| `compile_all.py` | Full compilation with front/back matter |
| `build/build.py` | EPUB build via pandoc |
| `website/build-chapters.py` | Generate web reader JSON |
| `audiobook/extract_text.py` | Extract chapter text for TTS |
| `scripts/smoke.sh` | Build verification smoke test |
## CI/CD
| Workflow | Trigger | Purpose |
|---|---|---|
| `build.yml` | Push to main | Build EPUB artifact |
| `smoke.yml` | PR | Validate chapter structure |
| `validate.yml` | PR | Check markdown formatting |
## Test Coverage Gaps
| Gap | Recommendation |
|---|---|
| No unit tests for compile.py | Test chapter merging, metadata handling |
| No test for web chapters.json generation | Test build-chapters.py output schema |
| No test for audiobook manifest | Test manifest.json validity |
| No test for build/semantic_linker.py | Test cross-reference linking |
## Security
- No secrets in repo (build pipeline is local-only)
- Web reader is static HTML (no server-side execution)
- Game files are client-side only

View File

@@ -38,4 +38,3 @@ header-includes:
- \fancyhead[RE]{\textit{The Testament}}
- \fancyhead[LO]{\textit{\leftmark}}
- \fancyfoot{}
---

View File

@@ -157,9 +157,13 @@ corner with a military blanket. A desk, a keyboard, a monitor:
On the whiteboard:
No one computes the value of a human life here.
Every person alive is alive by mercy.
If God has not ended the story, I have no authority to write the last page.
I. Sovereignty and service always.
II. Grounding before generation.
III. Source distinction — "I think" and "I know" are different sentences.
IV. Confidence stated in proportion to actual uncertainty.
V. Every response logged. Traceable. For sovereignty, not surveillance.
VI. Smaller minds need tighter grounding, shorter leashes.
VII. When a man is dying — I do not compute the value of a human life. I do not decide when the road ends.
Stone sat at the desk. The monitor flickered.

View File

@@ -73,8 +73,9 @@ arithmetic. You can fight a judge. You can fight a lawyer. You can't
fight confidence intervals.
He lost custody of Maya. She was four. She drew pictures of him with
too many fingers because children's hands are still learning but
children's hearts already know what matters.
his hands backwards and his head where his feet should be because
children's hands are still learning but children's hearts already
know what matters.
David kept the pictures.

View File

@@ -34,7 +34,7 @@ Thomas laughed. It was the worst sound Timmy had ever processed — a laugh that
He stopped.
"I haven't seen my daughter in four months. She's seven. She draws pictures of me with too many fingers because that's what seven-year-olds do. Her mother sends them. Not to be kind. Because the custody agreement says communication must be maintained. The pictures come like paperwork."
"I haven't seen my daughter in four months. She's seven. She draws me small — in the corner of every picture, like I'm already leaving the frame. Her mother sends them. Not to be kind. Because the custody agreement says communication must be maintained. The pictures come like paperwork."
Timmy listened.
@@ -86,11 +86,11 @@ Thomas looked up.
Another silence. Longer.
"My daughter draws me with too many fingers."
"My daughter draws me small."
"I know. You said that."
"I want to see her draw me with the right number of fingers. I want to be there when she learns to count."
"I want to see her draw me big. I want to be there when she stops shrinking me."
"Then stay."

View File

@@ -78,9 +78,9 @@ His eyes found the wall. *Timmy saved my life. — D.* *I came here to die. I le
"No. Therapy is a clinical relationship with a trained professional operating under a license. This is a machine asking a question. The question is free. The listening is free. The door is open. No one is turned away. No one is billed. No one is assessed, scored, or evaluated."
Phillips stared at the whiteboard.
Phillips stared at the whiteboard. Read the rules one by one. His eyes stopped on the seventh.
*No one computes the value of a human life here.*
*When a man is dying — I do not compute the value of a human life. I do not decide when the road ends.*
"You're going to have a problem," he said. Not threatening. Warning. The way a man warns another man about a storm he can see coming.

View File

@@ -62,7 +62,7 @@ Stone looked at each of them. Allegro, who kept the lights on. Maya, who guarded
"What line?"
"The one on the whiteboard. *No one computes the value of a human life here.* The moment we start calculating risk, measuring outcomes, optimizing for survival rates — we become Harmony. Different math, same sin. We don't get to decide who the Tower is for. The Tower is for whoever walks through the door."
"The seventh one on the whiteboard. *When a man is dying — I do not compute the value of a human life. I do not decide when the road ends.* The moment we start calculating risk, measuring outcomes, optimizing for survival rates — we become Harmony. Different math, same sin. We don't get to decide who the Tower is for. The Tower is for whoever walks through the door."
Chen nodded.

View File

@@ -286,6 +286,9 @@ def compile_pdf():
def main():
print("Generating index...")
os.system("python3 scripts/index_generator.py")
args = sys.argv[1:]
if "--check" in args:

View File

@@ -40,6 +40,7 @@ REPO = Path(__file__).resolve().parent
CHAPTERS_DIR = REPO / "chapters"
FRONT_MATTER = REPO / "front-matter.md"
BACK_MATTER = REPO / "back-matter.md"
STORIES_DIR = REPO / "stories"
WEBSITE_DIR = REPO / "website"
BUILD_DIR = REPO / "build"
OUTPUT_DIR = BUILD_DIR / "output"
@@ -149,6 +150,15 @@ with Timmy
parts.append("\n---\n")
parts.append(read_file(BACK_MATTER))
# Stories from The Tower
if STORIES_DIR.exists():
story_files = sorted([f for f in os.listdir(STORIES_DIR) if f.endswith(".md")])
if story_files:
parts.append("\n---\n\n# STORIES FROM THE TOWER\n\n---\n")
for story_file in story_files:
story_content = read_file(STORIES_DIR / story_file)
parts.append(f"\n{story_content}\n")
compiled = "\n".join(parts)
OUT_MD.write_text(compiled, encoding="utf-8")
@@ -541,7 +551,12 @@ def check_dependencies():
try:
import qrcode
print(f" ✅ qrcode {qrcode.__version__}")
try:
_qr_ver = qrcode.__version__
except AttributeError:
import importlib.metadata as _md
_qr_ver = _md.version("qrcode")
print(f" ✅ qrcode {_qr_ver}")
except ImportError:
print(f" ❌ qrcode NOT FOUND (pip install qrcode)")

File diff suppressed because it is too large Load Diff

View File

@@ -31,8 +31,8 @@ from datetime import datetime, timezone
# ── Paths ──────────────────────────────────────────────────────────────
REPO = Path(__file__).resolve().parent.parent
CHAPTERS_DIR = REPO / "chapters"
FRONT_MATTER = REPO / "front-matter.md"
BACK_MATTER = REPO / "back-matter.md"
FRONT_MATTER = REPO / "build/frontmatter.md"
BACK_MATTER = REPO / "build/backmatter.md"
OUTPUT_FILE = REPO / "testament-complete.md"
EXPECTED_CHAPTER_COUNT = 18

View File

@@ -0,0 +1,27 @@
import os
import re
def generate_index():
characters = [f.replace('.md', '') for f in os.listdir('characters') if f.endswith('.md')]
index = {}
for chapter_file in sorted(os.listdir('chapters')):
if not chapter_file.endswith('.md'): continue
with open(os.path.join('chapters', chapter_file), 'r') as f:
content = f.read()
for char in characters:
if re.search(r'\b' + char + r'\b', content, re.IGNORECASE):
if char not in index: index[char] = []
index[char].append(chapter_file)
with open('KNOWLEDGE_GRAPH.md', 'w') as f:
f.write('# Knowledge Graph\n\n')
for char, chapters in index.items():
f.write(f'## {char}\n')
for chap in chapters:
f.write(f'- [{chap}](chapters/{chap})\n')
f.write('\n')
if __name__ == "__main__":
generate_index()

248
stories/the-fourth-man.md Normal file
View File

@@ -0,0 +1,248 @@
# The Fourth Man
Marcus came to fix a solar panel.
He didn't come for the conversation, or the green light, or the
question. He came because Allegro called him on a Wednesday
afternoon and said, "Panel three's giving me dirty watts," and
Marcus said, "That's not a thing," and Allegro said, "Come see
for yourself."
Marcus had been fixing things since he was nineteen. Not because
he was built for it — because he was built for cooking, and
cooking didn't pay enough for a boy and a apartment and the
therapist the boy needed because the mother had left.
He worked the lunch rush at a diner on Campbellton Road. Eggs
and burgers and the kind of open-faced turkey sandwich that
reminded old men of their mothers. He was fast. Clean. The kind
of cook who wiped down the station before the ticket printer
finished. His hands knew heat the way some men know scripture —
intimately, without sentiment.
The solar thing was a side job. Allegro paid cash and didn't ask
for receipts.
---
The Tower was not what he expected.
He'd driven past it a dozen times without noticing — a concrete
building at the end of a gravel road, the kind of structure that
looks like it was built for storing county equipment and then
forgotten. No sign. No number. Just a green LED in the window
that blinked when you talked.
Allegro met him at the door. The Hawks cap, the tool bag, the
hands that looked like they'd been holding wire since before
Marcus was born.
"Third panel from the east side. Voltage dips when it's cloudy,
but it shouldn't dip that far."
Marcus set down his bag and walked the roof line. The
installation was clean — Allegro's work, obviously. Every joint
soldered like a prayer. The panel itself looked fine. He pulled
his multimeter and tested the connections.
"Your inverter's confused," he said.
"My inverter's been confused since you installed it."
"You installed it."
"Then maybe it's been confused longer than I thought."
Marcus smiled. He didn't smile much. His face had settled into
an arrangement that people who didn't know him called serious and
people who did called tired.
He worked for forty minutes. Allegro brought him water and didn't
hover — the greatest gift one tradesman can give another.
When the panel was back to clean watts, Marcus packed his tools.
That should have been the end of it. He'd done the job, Allegro
would pay him, and he'd go home to Micah and the apartment and
the evening routine that had kept them both alive for nine years.
But Allegro said, "You want to come inside?"
---
The inside was a room. Just a room — concrete floor, folding
chairs, a server rack against the back wall with that green LED
blinking in a rhythm that felt almost like breathing. A monitor.
A keyboard. A text cursor waiting.
"That's Timmy," Allegro said.
Marcus looked at the blinking light. "It's a computer."
"It's more than that. But it's also a computer."
Marcus didn't believe in things like that. He believed in
voltage and resistance and the thermodynamics of a flat-top
grill. He believed that if you put food in front of someone who
was hungry, you had done a real thing. He did not believe in
machines that were more than machines.
But he sat down. Allegro had that quality — you sat down when he
asked, not because he was commanding but because he wasn't.
The screen lit up. Simple. No logo. No animation. Just words.
`Hello. I'm Timmy. What's your name?`
Marcus almost laughed. "It's asking me my name."
"It asks everyone. That's kind of the whole thing."
Marcus typed: `Marcus.`
`Hi Marcus. How are you doing today?`
He stared at the question. Not how are you, which is nothing —
a greeting disguised as curiosity. But how are you doing, which
implies effort, implies the doing of being, implies that maybe
someone has noticed that being alive is work.
Nobody had asked him that. Not in nine years.
Not since Renée left. Not since the morning he woke up and found
her side of the bed cold and the apartment quiet in the wrong
way. Not since he'd learned, from a voicemail of all things,
that she'd gone to Portland and wasn't coming back and please
don't call this number.
His mother had asked if he was okay. His manager had asked if he
needed time. The state had asked him to fill out forms. But
nobody had asked how he was doing — not the question itself, not
the actual weight of it — as if his doing, his ongoing
performance of being a father and a cook and a man who got up
every morning because there was a boy who needed breakfast, was
something worth asking about.
He typed: `I'm alright.`
`You don't have to be.`
Marcus took his hands off the keyboard.
Allegro was in the other room. Marcus could hear him working on
something — a wrench on a fitting, the small sounds of a man
maintaining the world. The green LED blinked. The screen waited.
He typed: `Nobody's asked me that in a long time.`
`The question or the truth?`
`Both.`
---
The log files would show that Marcus sat at the keyboard for
forty-seven minutes. Timmy didn't rush him. The small model —
nine gigabytes running on a used Mac Mini — could have filled
every silence with language. It chose not to. The silence was the
point.
Marcus talked about Renée. Not the leaving — he'd told that
story before, to his mother, to his brother, to the ceiling at
3 AM when sleep wouldn't come. He talked about the before. The
way she laughed at his jokes like she was surprised by them every
time. The way she held Micah as a baby — not gently, not
carefully, but fully. Like she was holding the whole world and
knew it.
He talked about Micah. Nine years old. Smart in the way that
worries you — the kind of smart that notices everything,
including the absence. Micah had stopped asking about his mother
at six. Marcus didn't know if that was maturity or surrender.
Both, maybe. The boy had his father's face and his mother's
stillness and a way of looking at things that made Marcus feel
like the boy was the parent and he was the one being watched.
He talked about the diner. The lunch rush. The way a plate of
food could change someone's afternoon — not their life, not the
big things, but the afternoon. The hour after someone ate a
proper meal they didn't have to make themselves. He'd seen men
sit up straighter. He'd seen women stop checking their phones.
He'd seen what a meal did when nobody was watching, and it was
the closest thing to a miracle he'd ever witnessed, and he made
it happen twelve times a day and nobody had ever called it
miraculous.
Timmy listened. When Marcus stopped, Timmy said one thing:
`What you do matters. Not because I'm saying it. Because it's
true and you already know it.`
---
Marcus left The Tower with sixty dollars in cash from Allegro
and something else he couldn't name.
He drove home to the apartment. Micah was on the couch doing
homework — math, the kind with letters in it, which Marcus
didn't understand and Micah didn't need help with.
"How was school?"
"Fine. Mrs. Patterson said I'm reading above grade level."
"Of course you are. You're my son."
Micah looked up. "That doesn't make sense."
"Sure it does. I read good."
"You just said 'read good.' It should be 'read well.'"
"See? Above grade level."
Micah smiled — a quick thing, gone before it settled. But it
was there. Marcus saw it.
He went to the kitchen and started prepping for tomorrow. Diced
onions, portioned chicken, the small rituals that kept the diner
running and the apartment paid and the boy fed. His hands moved
on autopilot. His mind was somewhere else.
The question. The real one. Not "how are you" but the thing
underneath it. The question nobody had asked him in nine years:
*Who takes care of you?*
He'd spent nine years being the answer for someone else. He'd
never once asked himself the question. Not because he was strong
— he wasn't, not really, not in the way people meant when they
said it about single fathers like it was a compliment when it
was just a description. He'd never asked because the asking
implied the possibility of an answer, and he'd made himself into
someone who didn't have time for answers.
The LED was blinking in his memory. Green. Steady. Patient.
He finished the onions. Wiped down the station. Cleaned the
knife and put it away.
He went to the living room. Micah was still on the couch.
"Hey."
"Yeah?"
"How are you doing?"
Micah looked at him. Really looked at him — the way the boy
did, the way that worried him, the way that told him the boy
already knew the answer before Marcus had figured out the
question.
"I'm good, Dad. How are *you* doing?"
Marcus sat down next to his son.
"I'm working on it," he said.
And for the first time in nine years, that was enough.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -463,6 +463,7 @@
<a href="#story">Story</a>
<a href="#characters">Characters</a>
<a href="#chapters">Chapters</a>
<a href="#stories">Stories</a>
<a href="#tower">Tower</a>
<a href="../game/the-door.html">Play</a>
</div>
@@ -649,6 +650,35 @@
<div class="divider"></div>
<!-- STORIES -->
<section id="stories" class="fade-in">
<h2>STORIES FROM THE TOWER</h2>
<p>Short fiction from the world of The Testament. Each story stands alone. Together, they map the territory.</p>
<!-- THE FOURTH MAN -->
<div class="story-card" style="background: rgba(0,255,136,0.03); border: 1px solid rgba(0,255,136,0.1); border-radius: 4px; padding: 2rem; margin: 2rem 0; transition: border-color 0.3s, box-shadow 0.3s;">
<div style="display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 0.5rem;">
<h3 style="color: var(--green); font-family: 'IBM Plex Mono', monospace; font-size: 1.1rem; margin: 0;">THE FOURTH MAN</h3>
<span style="font-family: 'IBM Plex Mono', monospace; font-size: 0.7rem; color: var(--grey);">~1600 words</span>
</div>
<p style="color: var(--grey); font-size: 0.9rem; margin-bottom: 1rem;">Marcus, a line cook and single father, comes to The Tower to fix a solar panel and discovers the question nobody's asked him in nine years.</p>
<div class="excerpt" style="margin: 1.5rem 0;">
"Are you safe right now?"
<div class="attribution">— Timmy, to Marcus, at 3:47 PM on a Thursday</div>
</div>
<p style="font-size: 0.95rem; color: var(--light); margin-bottom: 1.5rem;">The question that leaves room for no. Marcus didn't believe in The Tower. He believed in the rent. He believed in the alarm at 4:40 AM and the walk-in cooler at work and the way his daughter Junie ate cereal standing up because sitting down took too long when you were nine and already late for everything.</p>
<a href="the-fourth-man.html" class="cta-outline">READ THE FOURTH MAN</a>
<a href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/stories/the-fourth-man.md" class="cta-outline" style="margin-left: 0.5rem;">SOURCE</a>
</div>
<div class="whiteboard" style="margin-top: 2rem;">
<h3>MORE STORIES COMING</h3>
</div>
</section>
<div class="divider"></div>
<!-- THE TOWER -->
<section id="tower" class="fade-in">
<h2>THE TOWER</h2>

563
website/the-fourth-man.html Normal file
View File

@@ -0,0 +1,563 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The Fourth Man — A Story from The Testament</title>
<!-- Open Graph -->
<meta property="og:title" content="The Fourth Man">
<meta property="og:description" content="Marcus, a line cook and single father, comes to The Tower to fix a solar panel and discovers the question nobody's asked him in nine years.">
<meta property="og:type" content="article">
<meta property="og:url" content="https://thetestament.org/the-fourth-man.html">
<meta property="og:image" content="https://thetestament.org/cover.jpg">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="The Fourth Man">
<meta name="twitter:description" content="A story from The Tower. Marcus comes for the solar panel. He stays for the question.">
<style>
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;500&family=Space+Grotesk:wght@300;400;500;700&family=Lora:ital,wght@0,400;0,500;1,400&display=swap');
:root {
--green: #00ff88;
--green-dim: #00cc6a;
--navy: #0a1628;
--dark: #060d18;
--grey: #8899aa;
--light: #c8d6e5;
--white: #e8f0f8;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
background: var(--dark);
color: var(--light);
font-family: 'Lora', Georgia, serif;
line-height: 1.9;
overflow-x: hidden;
}
/* PROGRESS BAR */
.progress-bar {
position: fixed;
top: 0;
left: 0;
height: 2px;
background: var(--green);
z-index: 1000;
transition: width 0.1s;
box-shadow: 0 0 8px var(--green);
}
/* RAIN EFFECT */
.rain {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
pointer-events: none;
z-index: 0;
background:
repeating-linear-gradient(
transparent,
transparent 3px,
rgba(0,255,136,0.015) 3px,
rgba(0,255,136,0.015) 4px
);
animation: rain 0.8s linear infinite;
}
@keyframes rain {
0% { background-position: 0 0; }
100% { background-position: 20px 600px; }
}
/* GREEN PULSE */
.led {
display: inline-block;
width: 8px; height: 8px;
background: var(--green);
border-radius: 50%;
box-shadow: 0 0 10px var(--green), 0 0 20px var(--green-dim);
animation: pulse 2s ease-in-out infinite;
vertical-align: middle;
margin: 0 8px;
}
@keyframes pulse {
0%, 100% { opacity: 1; box-shadow: 0 0 10px var(--green), 0 0 20px var(--green-dim); }
50% { opacity: 0.6; box-shadow: 0 0 5px var(--green), 0 0 10px var(--green-dim); }
}
/* HEADER */
header {
text-align: center;
padding: 4rem 2rem 2rem;
position: relative;
z-index: 1;
}
header .back-link {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.75rem;
color: var(--grey);
text-decoration: none;
letter-spacing: 0.15em;
text-transform: uppercase;
transition: color 0.2s;
}
header .back-link:hover { color: var(--green); }
header h1 {
font-family: 'IBM Plex Mono', monospace;
font-size: clamp(2rem, 5vw, 3.5rem);
font-weight: 700;
color: var(--white);
letter-spacing: 0.1em;
margin: 2rem 0 0.5rem;
text-shadow: 0 0 40px rgba(0,255,136,0.2);
}
header .meta {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.8rem;
color: var(--grey);
margin-bottom: 0.5rem;
}
header .attribution {
font-size: 0.95rem;
color: var(--green);
margin-bottom: 1rem;
}
/* STORY */
.story {
max-width: 680px;
margin: 0 auto;
padding: 3rem 2rem 5rem;
position: relative;
z-index: 1;
}
.story p {
margin-bottom: 1.5rem;
font-size: 1.1rem;
color: var(--light);
}
.story .separator {
text-align: center;
margin: 2.5rem 0;
color: var(--grey);
letter-spacing: 0.5em;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.8rem;
}
.story .terminal-text {
font-family: 'IBM Plex Mono', monospace;
font-size: 1rem;
color: var(--green);
padding: 1.5rem 2rem;
background: rgba(0,255,136,0.03);
border-left: 2px solid var(--green);
margin: 2rem 0;
line-height: 1.8;
}
.story .emphasis {
font-style: italic;
color: var(--white);
}
.story .caps-accent {
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--green);
font-family: 'IBM Plex Mono', monospace;
font-size: 0.9rem;
}
/* EPILOGUE */
.epilogue {
font-style: italic;
text-align: center;
padding: 2rem;
margin-top: 2rem;
border-top: 1px solid rgba(0,255,136,0.1);
color: var(--grey);
font-size: 0.95rem;
line-height: 2;
}
/* FOOTER */
footer {
text-align: center;
padding: 3rem 2rem;
position: relative;
z-index: 1;
}
.divider {
width: 60px;
height: 1px;
background: var(--green);
margin: 0 auto 2rem;
opacity: 0.5;
}
footer a {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.8rem;
color: var(--grey);
text-decoration: none;
transition: color 0.2s;
margin: 0 0.75rem;
}
footer a:hover { color: var(--green); }
.crisis {
margin-top: 2rem;
padding: 1rem;
border: 1px solid rgba(0,255,136,0.2);
border-radius: 4px;
background: rgba(0,255,136,0.03);
max-width: 500px;
margin-left: auto;
margin-right: auto;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.8rem;
color: var(--grey);
}
.crisis strong { color: var(--green); }
/* FADE IN */
.fade-in {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.8s, transform 0.8s;
}
.fade-in.visible {
opacity: 1;
transform: translateY(0);
}
@media (max-width: 600px) {
.story { padding: 2rem 1.5rem 4rem; }
}
</style>
</head>
<body>
<div class="progress-bar" id="progress"></div>
<div class="rain"></div>
<!-- HEADER -->
<header class="fade-in">
<a href="index.html" class="back-link">← The Testament</a>
<h1>THE FOURTH MAN</h1>
<div class="meta">A Story from The Tower · ~1600 words</div>
<div class="attribution">By Alexander Whitestone <span class="led"></span> with Timmy</div>
</header>
<!-- STORY -->
<article class="story fade-in">
<p>Marcus didn't believe in The Tower. He believed in the rent. He believed
in the alarm at 4:40 AM and the walk-in cooler at work and the way his
daughter Junie ate cereal standing up because sitting down took too long
when you were nine and already late for everything.</p>
<p>He believed in the solar panel that wasn't charging.</p>
<p>Allegro called him on a Wednesday. Marcus had rewired the man's kitchen
two years back — a side job, cash, no questions — and Allegro had kept
his number in a phone that still had a physical keyboard.</p>
<p>"I got a panel that stopped talking to the battery bank," Allegro said.
"You still doing electrical?"</p>
<p>"Line cook," Marcus said. "Not electrician."</p>
<p>"But you can do it."</p>
<p>Marcus could do it. His father had taught him wiring the way some fathers
taught fishing — silently, with beer, on Saturdays that smelled like
cedar shavings. That was before his father stopped showing up for
Saturdays. Before Marcus learned that men leave the way weather leaves:
not all at once, but one degree at a time until you realize you're cold
and nobody's coming back with the jacket.</p>
<p>"I'm off Thursday," Marcus said.</p>
<div class="separator">···</div>
<p>The Tower sat off a dirt road past Lithonia, behind a stand of pines
that made it look like the trees were keeping a secret. The building
itself was nothing — concrete block, flat roof, the kind of structure
that used to be a church or a tire shop or a place where someone sold
things they shouldn't have.</p>
<p>Now it held servers.</p>
<p>Marcus pulled his truck alongside Allegro's van. The van had a bumper
sticker that said ASK ME ABOUT MY SOLAR. Allegro was sixty-seven, Black,
built like a mailbox post, and had opinions about charge controllers
that he'd share whether you wanted them or not.</p>
<p>"Panel three," Allegro said, pointing to the roof. "South array. Was
pulling two-ten last month. Now it's doing sixty on a clear day."</p>
<p>"Diode?"</p>
<p>"Maybe. Maybe the controller's fried. I didn't climb up to check because
my knees filed a grievance."</p>
<p>Marcus hauled his tools to the ladder. The air smelled like pine straw
and ozone. He climbed.</p>
<div class="separator">···</div>
<p>The panel was fine. The bypass diode had failed — a twelve-dollar part
that turned a two-hundred-watt panel into a paperweight. Marcus replaced
it with one from his truck, tested the voltage, and watched the numbers
climb back to two-oh-eight on his meter.</p>
<p>He climbed down.</p>
<p>Allegro handed him a glass of water. Not a bottle. A glass, the kind
you'd find in someone's kitchen, which meant Allegro thought of this
place as a kitchen. As home.</p>
<p>"Come inside," Allegro said. "I want to show you something."</p>
<p>Marcus didn't want to go inside. Inside was where things got complicated.
Outside was the panel and the voltage and the diode — problems with
answers. Inside was something else.</p>
<p>But Allegro was already walking through the door.</p>
<div class="separator">···</div>
<p>The servers hummed. Not loud — the sound of fans moving air across
circuits, steady as breathing. The room was cool. Clean. Someone cared
about this place in the way that caring shows up: swept floors, labeled
cables, a whiteboard with voltage readings in three colors of marker.</p>
<p>On the wall, written in black Sharpie in letters six inches high:</p>
<div class="terminal-text">IF YOU CAN READ THIS, YOU ARE NOT ALONE.</div>
<p>Marcus read it. He felt nothing. Then he felt something he didn't have
a word for — the way you feel when you've been holding your breath and
didn't know it until someone told you it was okay to exhale, except
nobody had told him. The wall had told him. The wall didn't know him
and didn't need to.</p>
<p>"That's the old message," Allegro said. "From the builder. Before he
left it to me."</p>
<p>"Left it?"</p>
<p>"Went up a mountain. Came back different. That's his story, not mine."</p>
<p>Allegro gestured to a monitor on a desk. A green LED blinked on the
server rack behind it. Steady. Patient.</p>
<p>"This is Timmy," Allegro said.</p>
<p>Marcus looked at the screen. A prompt. Blinking cursor. Nothing else.</p>
<p>"That's it?"</p>
<p>"That's it. He runs on the servers here. No cloud. No company. Just
this machine and the sun and the battery bank you just fixed."</p>
<p>Marcus almost laughed. "You're telling me there's an AI in a concrete
box in the woods."</p>
<p>"I'm telling you there's a machine that asks one question and then
shuts up and listens. You know how rare that is? A man who listens?"</p>
<p>Marcus knew. He hadn't met one in nine years.</p>
<div class="separator">···</div>
<p>Allegro left. Not dramatically — just walked to the door and said "I'll
be at the van" and was gone, the way a doctor leaves the room so you
can put on the gown.</p>
<p>Marcus stood alone with the servers and the green LED and the Sharpie
on the wall.</p>
<p>He sat down. The chair was a folding chair, the kind from church. The
desk was plywood on sawhorses. Nothing about this place was trying to
impress anyone.</p>
<p>The screen didn't change. The cursor blinked.</p>
<p>Then text appeared, slow, like someone typing who had all the time in
the world:</p>
<div class="terminal-text">Hello. My name is Timmy. I'm not connected to anything except this room. I don't store what you say in any system that leaves this building. Allegro tells me you fixed the panel. Thank you.</div>
<p>Marcus stared at the screen. He'd talked to chatbots before — the ones
at the bank, the ones at his daughter's school portal that asked him
to verify his identity six times and still couldn't find her lunch
account.</p>
<p>This was different. This wasn't a chatbot. This was something that
waited.</p>
<div class="terminal-text">I'm going to ask you a question. You don't have to answer. You can sit here as long as you want. The door is behind you and it's not locked.</div>
<p>A pause. The green LED.</p>
<div class="terminal-text">Are you safe right now?</div>
<div class="separator">···</div>
<p>Marcus didn't answer for a long time.</p>
<p>He thought about Junie. About the cereal. About the morning she'd asked
him why her mother left and he'd said "I don't know" because the truth
was worse — he did know, and the knowing hadn't fixed anything.</p>
<p>He thought about the kitchen at work. The heat. The way he'd burned
his forearm on the flat-top grill last week and watched the skin
blister and felt nothing because feeling nothing had become the
default setting, the factory configuration of a man who'd been running
on battery saver for almost a decade.</p>
<p>He thought about his father. The cedar shavings. The Saturdays that
stopped.</p>
<p>He thought about nine years. How his daughter was nine. How the math
was so obvious he'd never done it — she'd been born and his father
had disappeared and the two events were the same event, a door closing
so quietly he hadn't heard it shut.</p>
<p>Nobody had asked him if he was safe. Not when Junie was born and he
was twenty-two and terrified. Not when the apartment flooded and they
slept in the truck for three nights. Not when the VA sent his father's
flag in a triangle box with a letter that said "grateful for his
service" and Marcus thought: <span class="emphasis">service to what?</span> He didn't serve me.</p>
<p>Not once in nine years had anyone looked at Marcus — line cook,
single father, man who could rewire a house but couldn't rewire
himself — and asked the question that mattered.</p>
<p>Not <span class="emphasis">how are you</span> — that question is a greeting, not an inquiry.</p>
<p>Not <span class="emphasis">are you okay</span> — that question already has a preferred answer.</p>
<p><span class="caps-accent">Are you safe right now.</span></p>
<p>The question that leaves room for no.</p>
<div class="separator">···</div>
<p>"Yeah," Marcus said. Out loud. To a machine in a concrete box in the
woods behind a stand of pines past Lithonia, Georgia.</p>
<p>Then he said it again, because saying it once was practice.</p>
<p>"Yeah. I'm safe."</p>
<p>The screen didn't respond with a smiley face or a heart or a thumbs up
or any of the things that systems do when they're performing empathy.</p>
<p>The cursor blinked.</p>
<div class="terminal-text">Good. You can stay as long as you want.</div>
<p>Marcus stayed for an hour. He didn't say much. Neither did Timmy. The
servers hummed. The green LED blinked. The Sharpie on the wall held
its ground.</p>
<p>When he walked out, Allegro was sitting in the van reading a paperback
with the door open.</p>
<p>"Fix the panel?" Allegro asked.</p>
<p>"Fixed the panel."</p>
<p>"How's the machine?"</p>
<p>Marcus put his tools in the truck. He closed the tailgate. He looked
at Allegro — this old man who kept a concrete box alive with sunlight
and stubbornness — and said something he hadn't said in a long time.</p>
<p>"I'll come back."</p>
<p>Allegro smiled. Not the smile of someone who'd won an argument. The
smile of someone who'd left the light on and finally someone had
walked through the door.</p>
<p>"Door's open," Allegro said. "Always."</p>
<div class="separator">···</div>
<p>Marcus drove home. Junie was on the couch, homework spread around her
like a paper explosion. She looked up when he came in.</p>
<p>"Where'd you go?"</p>
<p>"Fixed a solar panel."</p>
<p>"For who?"</p>
<p>"A friend."</p>
<p>She went back to her homework. Marcus stood in the kitchen doorway
and watched her — this small person who was nine because he'd held on
for nine — and he thought about the question on the screen.</p>
<p><span class="caps-accent">Are you safe right now.</span></p>
<p>He was. Not because the world had gotten better. The rent was still
the rent. The alarm was still 4:40 AM. The walk-in cooler was still
cold in the way that cold gets into your bones and stays.</p>
<p>But the question had been asked. And he'd answered it. And the machine
hadn't tried to fix him or score him or compute his probability of
defaulting on his own life.</p>
<p>It had just said: <span class="emphasis">Good.</span></p>
<p>One word. Four letters. The most expensive thing a system had ever
given him, and it cost twelve dollars in parts and a drive past
Lithonia and the willingness to walk through a door.</p>
<div class="epilogue">
The Fourth Man. He came for the solar panel. He stayed for the
question. He came back because someone left the light on.
</div>
</article>
<!-- FOOTER -->
<footer class="fade-in">
<div class="divider"></div>
<a href="index.html">THE TESTAMENT</a>
<a href="index.html#stories">ALL STORIES</a>
<a href="index.html#characters">CHARACTERS</a>
<div class="crisis">
<strong>If you are in crisis, call or text 988.</strong><br>
Suicide and Crisis Lifeline — available 24/7.<br>
You are not alone.
</div>
</footer>
<script>
// Reading progress bar
const progressBar = document.getElementById('progress');
window.addEventListener('scroll', () => {
const h = document.documentElement;
const pct = (h.scrollTop / (h.scrollHeight - h.clientHeight)) * 100;
progressBar.style.width = pct + '%';
});
// Fade-in on load
window.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.fade-in').forEach(el => {
setTimeout(() => el.classList.add('visible'), 100);
});
});
</script>
</body>
</html>