Our Story So Far
What This Is
An Obsidian-based workflow automation system. It generates structured, multi-step workflow templates with rotation-based lookups, phrase injection, parallel tracks (splits/joins), and output-to-input carry-forward. Everything runs inside Obsidian using Templater and a custom workflow-tools plugin.
The project grew out of “The Review,” a newspaper-style editorial workflow with 20 mega-categories and 7 story angles rotating daily via day-of-year modulo. The system is now generic — any workflow with sequential and parallel steps can be generated from a config object.
Current State (Session 12, 2026-02-17)
- 506 tests across 26 suites, all passing
- Runtime modules in
scripts/workflow/(8 files) - Build tool + tests in
tests/(27 files) - workflow-creator.js lives in BOTH
scripts/workflow/ANDtests/(see Known Issues) - Trial workflow
tr1-select-articlespartially working:- Step templates generate and auto-strip correctly
- Carry-forward works (output→input)
- Home template crashes with
yamlStr is not defined(old template needs deletion + regeneration) - Rotation files were accidentally deleted; recreated from original doySentence.js data
- Phrase files not yet created for this workflow
Mistakes We Made and How to Avoid Them
This section exists so we stop repeating ourselves. Every entry is a real mistake that cost real time.
1. Templater executes <% tags everywhere, including inside code fences
What happened: The Quick Reference callout in the home template had code examples with <% yamlStr(...) %>. Templater executed them as real code even though they were inside markdown code blocks inside a callout.
Cost: Multiple failed workflow runs across multiple sessions. The home template crashed every time.
Rule: Never put <% or %> in ANY generated template content, even in code blocks, comments, or documentation callouts. Use backtick-escaped descriptions instead, or point to a separate static .md file.
2. Testing in Node ≠ running in Obsidian/Templater
What happened: Tests pass in Node.js because Node handles require(), module.exports, and standard JavaScript normally. Obsidian’s Templater has different module loading, different error handling, and executes template tags that Node never sees.
Cost: Repeatedly shipping code that passes all tests but crashes in Obsidian.
Rule: Node tests catch logic errors. They cannot catch Templater parsing errors. After ANY change to generated template content, the very next step is to test in Obsidian — not just run Node tests. We need a checklist item for this.
3. The require() path problem
What happened: workflow-creator.js needs to live in scripts/workflow/ (for Templater) AND in tests/ (because test files do require('./workflow-creator')). When we “fixed” the placement by removing it from one location, we broke the other.
Cost: 11 test files failed with “Cannot find module” errors. On the other side, create-workflow.md couldn’t find the module.
Rule: workflow-creator.js lives in both places until we fix the test require paths (backlog item). When updating, copy to both. The proper fix is changing tests to require('../scripts/workflow/workflow-creator').
4. Generated templates persist after the generator is fixed
What happened: Fixed the yamlStr bug in workflow-creator.js. Regenerated the workflow. But hit Enter (not “yes”) on the home template overwrite prompt, so the OLD buggy home template stayed in the vault.
Cost: Multiple more failed runs while debugging a “fixed” bug.
Rule: When regenerating a workflow, always say “yes” to EVERY overwrite prompt. If you accidentally skip one, delete that specific template file and re-run. Better yet: delete all master templates first (see Clean Reset below), then generate fresh.
5. Deleting too much during a reset
What happened: While cleaning up to reset tr1-select-articles, deleted the entire directory including the rotation lookup files (mega-categories, angles) which were hand-authored data, not generated templates.
Cost: Had to recreate rotation files from the original doySentence.js source.
Rule: Know what’s generated vs. what’s authored. The Clean Reset section below spells this out. Rotation files and phrase files are YOUR DATA. Template files are generated and disposable.
6. Saying a file is “safe” without tracing dependencies
What happened: Confidently stated workflow-creator.js could be removed from tests/ because “it has no require() statements.” Didn’t check that 11 test files require IT.
Cost: 11 broken tests, user frustration, loss of trust.
Rule: Before moving or removing ANY file, run grep -r "require.*filename" tests/ scripts/ to find all dependents. Add this to the pre-flight checklist.
7. The overwrite prompt defaults to “no”
What happened: Obsidian’s file creation prompt defaults to not overwriting. Hitting Enter without reading means “keep the old file.” With 40+ files in a workflow, it’s easy to accidentally keep stale templates.
Cost: Stale templates mixed with new ones. Inconsistent behavior. Hard to debug.
Rule: Until we build “Yes to All” (backlog), go slowly through overwrite prompts. Or better: delete all master templates first, then generate clean.
Pre-Flight Checklist
Run this before declaring any change “done”:
[ ] All Node tests pass (node tests/*.test.js)
[ ] workflow-creator.js copied to BOTH scripts/workflow/ AND tests/
[ ] No <% or %> tags in any generated template content (except step setup blocks)
[ ] grep -r "require.*changed-file" to find all dependents
[ ] If template content changed: test in Obsidian (not just Node)
[ ] If generated files changed: delete old templates, regenerate, say YES to all overwrites
[ ] Restart Obsidian after changing anything in scripts/workflow/
How to Clean-Reset a Workflow
When things get tangled and you need to start fresh.
Delete (generated files — disposable)
- The entire instance subfolder:
{workflow-name}/{yyyy-mm}/ - All master templates:
{workflow-name}-{dateStamp}-*.md*-workflow.md(orchestrator)*-home.md(dashboard)*-01.md,*-02a.md, etc. (step templates)*-phrases.md(instance phrase file, if dated)
KEEP (your authored data — not disposable)
{workflow-name}-rotation-*.md(rotation lists YOU wrote){workflow-name}-phrases.md(master phrase file YOU wrote, no dateStamp in name)- Everything in
scripts/workflow/(runtime modules) - Everything in
tests/(test suite)
Then
- Run create-workflow.md
- Say YES to every overwrite prompt
- Restart Obsidian
- Re-run the workflow template to generate instance files
Timeline
Session 1 — Obsidian Workflow Dated Paths (2026-02-12)
- TDD approach established
- Dated folder structure:
workflow-name/yyyy-mm/ - Path-building utilities, Templater collision handling
Session 2 — Dated Paths Integration (2026-02-12)
- Integrated dated folders into workflow-creator.js
- Filename collision prevention, recursive folder creation
- 79 tests across 5 suites
Session 3 — Plugin TDD Loop (2026-02-13)
- workflow-tools plugin: silent load failures, ES6 compat
- Auto-strip functionality for template artifacts
Session 4 — Step Tracking Bidirectional Tests (2026-02-15)
- Status/started/completed frontmatter fields
- Dataview dashboard, plugin commands for status updates
- Bidirectional testing, scripts folder reorganization
Session 5 — Splits/Joins Planning (2026-02-16)
- Design session for parallel tracks and carry-forward
- Confirmed join behavior (concatenate outputs labeled by track)
Session 6 — Splits/Joins Implementation (2026-02-16)
- computeStepShape for track fan-out/fan-in
- Integration with generateWorkflow
Session 7 — Carry-Forward Implementation (2026-02-16)
- Output → input carry-forward module
- Plugin wiring for file-watch triggers
Session 8 — Phrase Lookup & Date Utils (2026-02-16)
- parsePhraseFile with scoped pools
- date-numbers.js, create-workflow.md tracks support
Session 9 — Rotation Resolver & Phrase Wiring (2026-02-17)
- rotation-resolver.js: modulo-based item selection from markdown
- 10-track workflow support, migration from doySentence.js
Session 10 — Templater Fix & Date Folders (2026-02-17)
- Fixed require() incompatibility in Templater
- yyyy-mm-dd master template folders with dynamic instance subfolders
Session 11 — Phrase Sub-Categories & Rotation Mode (2026-02-17)
- Sub-headed categories (### Goal, Motivation)
- Per-workflow phraseMode config (random vs rotate)
- Obsidian boot loop debugging (workspaces-plus plugin)
Session 12 — How-To Doc, Consolidation, Mistakes (2026-02-17)
- workflow-lookup-howto.md reference document
- our-story-so-far.md with mistakes documentation
- Fixed yamlStr in home template (Templater executing code examples)
- Confirmed workflow-creator.js is safe in scripts/workflow/
- Identified dual-location requirement (scripts/ + tests/)
- Recreated rotation files from original doySentence.js
- 506 tests across 26 suites
Architecture
Runtime Modules (scripts/workflow/ — loaded by Templater)
| Module | Purpose |
|---|---|
| rotation-resolver.js | Parse rotation markdown, select items by day-of-year modulo |
| phrase-lookup.js | Parse phrase markdown, scoped pools, random or modulo selection |
| date-numbers.js | Day-of-year calculation |
| dependency-checker.js | Validate required modules at startup |
| author-config.js | Author name/email for YAML |
| carry-forward.js | Output → input content propagation |
| core-utils.js | Shared utilities |
| template-factory.js | Template generation helpers |
| workflow-creator.js | Generates all template files from config |
Test Suite (tests/ — Node.js only)
| File | Purpose |
|---|---|
| workflow-creator.js | COPY of the same file (tests require it locally) |
| 26 *.test.js files | Full regression suite, 506 tests |
Key Concepts
Two selection modes: Modulo rotation (deterministic cycling) and random. Rotation is the default for lookups, random is the default for phrases.
Phrase cascade: Workflow → Instance → Base step → Exact step (track). All matching scopes merge into one pool.
Phrase sub-categories: ### Goal under ## Step 01 creates context.phrases["Goal"].
Splits/joins: Steps can fan out to parallel tracks (02a-02h) and fan back in.
Carry-forward: When a step completes, its output section flows into the next step’s input.
Backlog
High Priority
-
Reset workflow command — Plugin command to delete all generated files for a workflow while preserving rotation/phrase data. Shows file list, asks for confirmation.
-
“Yes to all” on overwrite prompts — Plus a “Back” option for accidental Enter presses.
-
Fix test require paths — Change all 11 test files from
require('./workflow-creator')torequire('../scripts/workflow/workflow-creator'). Eliminates the dual-location problem.
Medium Priority
-
Folder pre-creation — Workflow template should create the instance subfolder before writing the home file. Currently step 01 creates the folder as a side-effect, but home runs first and fails.
-
Rotation file naming guard — Warn when rotation files don’t match the workflow name pattern.
-
Obsidian smoke test script — A template that exercises all the template features (rotations, phrases, yamlStr, etc.) and reports pass/fail in the console. Catches Templater-specific bugs that Node can’t.
Low Priority / Future
- Configurable rotation seed — Allow any integer as the modulo input, not just day-of-year.
- Workflow diff/compare — Show what changed between generated versions.
- Git integration — Auto-commit after major workflow operations.
- Step template hot-swap — Replace a step’s setup block in-place.
Ideas (Unscoped)
- Web-based workflow visualizer (static HTML, loads JSON)
- Workflow-level phrase mode override per-step
- Instance-level rotation overrides
Known Issues
-
workflow-creator.js dual location — Must exist in BOTH
scripts/workflow/(for Templater) ANDtests/(for test suite). When updating, copy to both. Fix: change test require paths (backlog item). -
workspaces-plus plugin — Can corrupt workspace state and cause Obsidian boot loops. If Obsidian won’t start and console shows
applyCss is not a function, delete.obsidian/plugins/workspaces-plusandworkspace.json. -
Old template artifacts — Templates generated before recent fixes may have stale code (missing yamlStr, executable code examples in callouts). Fix: delete the specific template file and regenerate.
-
rotation-lookup.js vs rotation-resolver.js — rotation-lookup.js is the old module. rotation-resolver.js is the new one. Both may exist in scripts/workflow/. The old one should eventually be removed.
-
Overwrite prompt defaults to “no” — Hitting Enter without reading keeps the old file. Always explicitly type “yes” until we build “Yes to All.”
-
Node tests can’t catch Templater bugs — Template parsing errors (executing
<%in unexpected places) only manifest in Obsidian, not in Node test runs.
File Inventory for tr1-select-articles
Authored data (KEEP)
tr1-select-articles-rotation-mega-categories.md— 20 mega-categories from original doySentence.jstr1-select-articles-rotation-angles.md— 7 story angles from original doySentence.jstr1-select-articles-phrases.md— Master phrases (create when ready)
Generated templates (DISPOSABLE — regenerate with create-workflow.md)
tr1-select-articles-2026-02-workflow.mdtr1-select-articles-2026-02-home.mdtr1-select-articles-2026-02-01.mdtr1-select-articles-2026-02-02a.mdthrough02htr1-select-articles-2026-02-03a.mdthrough03htr1-select-articles-2026-02-04a.mdthrough04htr1-select-articles-2026-02-05a.mdthrough05htr1-select-articles-2026-02-06a.mdthrough06htr1-select-articles-2026-02-07.md- Plus: data, lookup, step-sections, step-content, step-custom .js files
Generated instances (DISPOSABLE)
- Everything in
tr1-select-articles/2026-02/
Transcripts
All session transcripts: /mnt/transcripts/
Journal index: /mnt/transcripts/journal.txt