Thomas Piacentini
← Workshop

Cheat sheet

Personal Organizer Agents

Original text · English

Five local organizer projects. What each builds, how to run it, its inputs, outputs, review files and checks.

Node projects side by side

FactorBookmark Path OrganizerCalendar Focus PlannerField Notes Map Builder
BuildsReading path pageFocus plan and ICS proposalsGeoJSON and a schematic map
Inputbookmarks tree, topicssample.ics, tasks.json, a dayobservations, radiusMeters
Outputsbookmarks.json, progress.json, report.htmlfocus.ics, plan.json, plan.htmlobservations.geojson, groups.json, report.html
Review filethird argument progress.jsonnonethird argument group-review.json
Never doesFetch linksChange an account calendarDownload photos or tiles
Sources

Python projects side by side

FactorDownload Folder Sort DeskCatalog Record Linker
BuildsFiling plan and duplicate groupsCrosswalk and merged catalog
Inputfolder, occupiedleft_csv, right_csv, threshold
Outputsmoves.json, duplicates.json, review.htmlcrosswalk.csv, merged-catalog.json, review.html
Review file--decisions decisions.json--decisions decisions.json
Never doesMove a fileMerge on similarity alone
Sources

Run the reference

CommandWhat it does
node cli.ts sample.json outputBookmark organizer or field notes map
node cli.ts <input.json> <dir> <review.json>Runs again with your downloaded review
node cli.ts sample.ics tasks.json 2026-10-14 output 10Calendar plan with a 10 minute buffer
python3 cli.py samples/input.json --output demo-outputDownload sort desk or catalog linker
python3 cli.py <input.json> --output <dir> --decisions decisions.jsonApplies your approvals
python3 scripts/project_test.py <project> --all --solution --strictGrades the reference
Sources

Calendar planner steps

  1. CLI sets the window from 09:00 to 17:00 UTC on the given day.
  2. parseCalendar needs UID, DTSTART and DTEND. It skips cancelled and transparent events.
  3. availableSlots adds the buffer around events, merges overlaps, then lists the gaps.
  4. schedule sorts tasks by priority, then by id.
  5. schedule puts each task in the earliest gap that is long enough.
  6. schedule lists a task that fits no gap as unscheduled with a reason.
  7. exportCalendar writes proposals to focus.ics for manual import.
Sources

Download sort desk

folderrecordscategoryplanapproved movesinput.jsonfolder, occupiedclientinventory()path, size, sha256processcategorize()scores, evidenceprocessplan_moves()destination,duplicate_groupsprocessreview_plan()fingerprint, approvedprocessmoves.jsonfor a file managerstore
Nodes and connections
NodeRoleKind
input.jsonfolder, occupiedclient
inventory()path, size, sha256process
categorize()scores, evidenceprocess
plan_moves()destination, duplicate_groupsprocess
review_plan()fingerprint, approvedprocess
moves.jsonfor a file managerstore
FromToConnection
input.jsoninventory()folder
inventory()categorize()records
categorize()plan_moves()category
plan_moves()review_plan()plan
review_plan()moves.jsonapproved moves
Sources

Scoring rules

Bookmark topic score
a keyword in a title adds 3. A keyword in notes adds 1.
Bookmark duplicates
same URL after the fragment is removed. Query strings stay significant.
File category
a known extension adds 3. The words workshop and handout add 1 to documents.
File collisions
a taken destination gets -2, -3 before the suffix, case-insensitive.
Catalog pair score
title Jaccard times 0.8 plus creator Jaccard times 0.2.
Nearby observations
distanceMeters() uses a spherical earth of radius 6371008.8 m.
Map groups
pairs within the radius join one connected component.
Sources

Defaults and limits

SettingDefaultNote
Calendar buffer minutes10Allowed range 0 to 120
Calendar output folderfocus-outputFourth CLI argument
Max tasks100Minutes 5 to 480, priority 1 to 5
threshold0.25Finite, from 0 to 1
Folder nesting32Deeper bookmark trees fail
Radius0..1000000Meters
approvedFalseEvery planned move starts unapproved
schema_version1In moves.json and merged-catalog.json
Sources

Error messages and fixes

SymptomCauseFix
Expand recurrence and timezone values to UTC before importingRRULE or TZID in the ICSExpand events in the exporter first
Event needs UID, DTSTART and DTENDImplicit end or DURATIONWrite an explicit DTEND
stale approval: source content or destination plan changedFiles or plan changed after reviewUse the new decisions.json
output must be outside the input folderOutput inside the scanned folderPick another output path
Progress order must contain every current id exactly onceBookmarks changed after the downloadRun without the third argument
one-to-one match violatedOne record accepted twiceAccept each record in one pair only
Sources

Write a review file

TaskCode
Split a map group"decisions": {"<id>": "keep-separate"}
Keep a map group"decisions": {"<id>": "keep-group"}
Save reading order"order": [...], "completed": [...]
Approve file moves"approved": ["<path>"]
Accept a catalog pair"match": true, "values": {}
Version a Node review"schemaVersion": 1
Sources

Worked examples

Why is the sample busy from 09:20 to 11:10?
Two events overlap and the 10 minute buffer widens them.
Which task does not fit?
deep needs 120 minutes. No gap is that long.
Why do map-1 and map-2 group?
Both URLs give the same document after normalization.
Where does handout.txt go?
documents/handout.txt is occupied, so it gets -2.
Are left:map-1 and right:r-7 merged?
Only after you accept the pair. No record is discarded.
Sources

Tips

  • An all-day DTEND;VALUE=DATE is exclusive. October 14 ends on 20261015.
  • A file manager must recheck identity right before a move. The plan is not a transaction.
  • ready means accepted merges have no open conflicts. It does not mean every pair was read.
  • GeoJSON uses longitude then latitude order.
  • The bookmark importer reads the JSON folder tree, not browser HTML.
  • Test at least one new input of your own before you integrate a tool.
Sources
Original source
---
id: personal-organizer-agents
title: Personal Organizer Agents
code: PO
subtitle: Five local organizer projects. What each builds, how to run it, its inputs, outputs, review files and checks.
hue: 152
sources: projects/bookmark-path-organizer, projects/calendar-focus-planner, projects/download-folder-sort-desk, projects/field-notes-map-builder, projects/catalog-record-linker
source_hash: 4017cd6c40080599
---

## Node projects side by side
type: comparison
span: 2
from: projects/bookmark-path-organizer/README.md, projects/bookmark-path-organizer/solution/cli.ts, projects/calendar-focus-planner/README.md, projects/calendar-focus-planner/solution/cli.ts, projects/field-notes-map-builder/README.md, projects/field-notes-map-builder/solution/cli.ts

| Factor | Bookmark Path Organizer | Calendar Focus Planner | Field Notes Map Builder |
|---|---|---|---|
| Builds | Reading path page | Focus plan and ICS proposals | GeoJSON and a schematic map |
| Input | `bookmarks` tree, `topics` | `sample.ics`, `tasks.json`, a day | `observations`, `radiusMeters` |
| Outputs | `bookmarks.json`, `progress.json`, `report.html` | `focus.ics`, `plan.json`, `plan.html` | `observations.geojson`, `groups.json`, `report.html` |
| Review file | third argument `progress.json` | none | third argument `group-review.json` |
| Never does | Fetch links | Change an account calendar | Download photos or tiles |

## Python projects side by side
type: comparison
from: projects/download-folder-sort-desk/README.md, projects/download-folder-sort-desk/solution/cli.py, projects/catalog-record-linker/README.md, projects/catalog-record-linker/solution/cli.py

| Factor | Download Folder Sort Desk | Catalog Record Linker |
|---|---|---|
| Builds | Filing plan and duplicate groups | Crosswalk and merged catalog |
| Input | `folder`, `occupied` | `left_csv`, `right_csv`, `threshold` |
| Outputs | `moves.json`, `duplicates.json`, `review.html` | `crosswalk.csv`, `merged-catalog.json`, `review.html` |
| Review file | `--decisions decisions.json` | `--decisions decisions.json` |
| Never does | Move a file | Merge on similarity alone |

## Run the reference
type: command-table
span: 2
from: projects/bookmark-path-organizer/README.md, projects/calendar-focus-planner/README.md, projects/calendar-focus-planner/solution/cli.ts, projects/download-folder-sort-desk/README.md, projects/catalog-record-linker/README.md, projects/field-notes-map-builder/README.md

| Command | What it does |
|---|---|
| `node cli.ts sample.json output` | Bookmark organizer or field notes map |
| `node cli.ts <input.json> <dir> <review.json>` | Runs again with your downloaded review |
| `node cli.ts sample.ics tasks.json 2026-10-14 output 10` | Calendar plan with a 10 minute buffer |
| `python3 cli.py samples/input.json --output demo-output` | Download sort desk or catalog linker |
| `python3 cli.py <input.json> --output <dir> --decisions decisions.json` | Applies your approvals |
| `python3 scripts/project_test.py <project> --all --solution --strict` | Grades the reference |

## Calendar planner steps
type: flow
from: projects/calendar-focus-planner/solution/main.ts, projects/calendar-focus-planner/solution/cli.ts, projects/calendar-focus-planner/README.md

1. **CLI**: sets the window from 09:00 to 17:00 UTC on the given day.
2. **parseCalendar**: needs `UID`, `DTSTART` and `DTEND`. It skips cancelled and transparent events.
3. **availableSlots**: adds the buffer around events, merges overlaps, then lists the gaps.
4. **schedule**: sorts tasks by priority, then by id.
5. **schedule**: puts each task in the earliest gap that is long enough.
6. **schedule**: lists a task that fits no gap as unscheduled with a reason.
7. **exportCalendar**: writes proposals to `focus.ics` for manual import.

## Download sort desk
type: architecture
from: projects/download-folder-sort-desk/solution/main.py, projects/download-folder-sort-desk/solution/cli.py, projects/download-folder-sort-desk/API.md

```arch
node | in | 1,1 | input.json | folder, occupied | client
node | inv | 2,1 | inventory() | path, size, sha256 | process
node | cat | 3,1 | categorize() | scores, evidence | process
node | plan | 3,2 | plan_moves() | destination, duplicate_groups | process
node | rev | 2,2 | review_plan() | fingerprint, approved | process
node | out | 1,2 | moves.json | for a file manager | store
edge | in | inv | folder
edge | inv | cat | records
edge | cat | plan | category
edge | plan | rev | plan
edge | rev | out | approved moves
```

## Scoring rules
type: concepts
from: projects/bookmark-path-organizer/solution/main.ts, projects/download-folder-sort-desk/API.md, projects/catalog-record-linker/API.md, projects/field-notes-map-builder/solution/main.ts, projects/field-notes-map-builder/README.md

- **Bookmark topic score**: a keyword in a title adds 3. A keyword in notes adds 1.
- **Bookmark duplicates**: same URL after the fragment is removed. Query strings stay significant.
- **File category**: a known extension adds 3. The words workshop and handout add 1 to documents.
- **File collisions**: a taken destination gets `-2`, `-3` before the suffix, case-insensitive.
- **Catalog pair score**: title Jaccard times 0.8 plus creator Jaccard times 0.2.
- **Nearby observations**: `distanceMeters()` uses a spherical earth of radius 6371008.8 m.
- **Map groups**: pairs within the radius join one connected component.

## Defaults and limits
type: defaults
from: projects/calendar-focus-planner/solution/cli.ts, projects/calendar-focus-planner/solution/main.ts, projects/catalog-record-linker/API.md, projects/bookmark-path-organizer/solution/main.ts, projects/field-notes-map-builder/solution/main.ts, projects/download-folder-sort-desk/solution/main.py

| Setting | Default | Note |
|---|---|---|
| Calendar buffer minutes | 10 | Allowed range 0 to 120 |
| Calendar output folder | `focus-output` | Fourth CLI argument |
| Max tasks | 100 | Minutes 5 to 480, priority 1 to 5 |
| `threshold` | 0.25 | Finite, from 0 to 1 |
| Folder nesting | 32 | Deeper bookmark trees fail |
| Radius | 0..1000000 | Meters |
| `approved` | `False` | Every planned move starts unapproved |
| `schema_version` | 1 | In `moves.json` and `merged-catalog.json` |

## Error messages and fixes
type: troubleshooting
from: projects/calendar-focus-planner/solution/main.ts, projects/calendar-focus-planner/README.md, projects/download-folder-sort-desk/solution/main.py, projects/download-folder-sort-desk/solution/cli.py, projects/bookmark-path-organizer/solution/main.ts, projects/catalog-record-linker/solution/main.py, projects/field-notes-map-builder/solution/main.ts

| Symptom | Cause | Fix |
|---|---|---|
| `Expand recurrence and timezone values to UTC before importing` | `RRULE` or `TZID` in the ICS | Expand events in the exporter first |
| `Event needs UID, DTSTART and DTEND` | Implicit end or `DURATION` | Write an explicit `DTEND` |
| `stale approval: source content or destination plan changed` | Files or plan changed after review | Use the new `decisions.json` |
| `output must be outside the input folder` | Output inside the scanned folder | Pick another output path |
| `Progress order must contain every current id exactly once` | Bookmarks changed after the download | Run without the third argument |
| `one-to-one match violated` | One record accepted twice | Accept each record in one pair only |

## Write a review file
type: task-table
from: projects/field-notes-map-builder/solution/main.ts, projects/bookmark-path-organizer/solution/main.ts, projects/download-folder-sort-desk/README.md, projects/catalog-record-linker/API.md

| Task | Code |
|---|---|
| Split a map group | `"decisions": {"<id>": "keep-separate"}` |
| Keep a map group | `"decisions": {"<id>": "keep-group"}` |
| Save reading order | `"order": [...], "completed": [...]` |
| Approve file moves | `"approved": ["<path>"]` |
| Accept a catalog pair | `"match": true, "values": {}` |
| Version a Node review | `"schemaVersion": 1` |

## Worked examples
type: qa
from: projects/calendar-focus-planner/solution/sample.ics, projects/calendar-focus-planner/solution/tasks.json, projects/calendar-focus-planner/solution/main.ts, projects/bookmark-path-organizer/solution/sample.json, projects/download-folder-sort-desk/README.md, projects/download-folder-sort-desk/solution/samples/input.json, projects/catalog-record-linker/README.md

- **Why is the sample busy from 09:20 to 11:10?** Two events overlap and the 10 minute buffer widens them.
- **Which task does not fit?** `deep` needs 120 minutes. No gap is that long.
- **Why do `map-1` and `map-2` group?** Both URLs give the same document after normalization.
- **Where does `handout.txt` go?** `documents/handout.txt` is occupied, so it gets `-2`.
- **Are `left:map-1` and `right:r-7` merged?** Only after you accept the pair. No record is discarded.

## Tips
type: tips
from: projects/calendar-focus-planner/README.md, projects/download-folder-sort-desk/README.md, projects/catalog-record-linker/README.md, projects/field-notes-map-builder/README.md, projects/bookmark-path-organizer/README.md

- An all-day `DTEND;VALUE=DATE` is exclusive. October 14 ends on `20261015`.
- A file manager must recheck identity right before a move. The plan is not a transaction.
- `ready` means accepted merges have no open conflicts. It does not mean every pair was read.
- GeoJSON uses longitude then latitude order.
- The bookmark importer reads the JSON folder tree, not browser HTML.
- Test at least one new input of your own before you integrate a tool.
Code and artifacts 1
What you take away

Saved in your notebook on this device.

Sources and limits

Reading checkpoints are self-reported. Test results are recorded separately and apply to the executed cases.

AI Engineering from Scratch · 3f9715c · MIT

Download this file ↓