fusion-cli 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. fusion/__init__.py +3 -0
  2. fusion/_skills/fusion-analyst/SKILL.md +50 -0
  3. fusion/_skills/fusion-analyst/references/assess.md +12 -0
  4. fusion/_skills/fusion-analyst/references/compare.md +12 -0
  5. fusion/_skills/fusion-analyst/references/export.md +18 -0
  6. fusion/_skills/fusion-analyst/references/fusion-conventions.md +149 -0
  7. fusion/_skills/fusion-analyst/references/report.md +13 -0
  8. fusion/_skills/fusion-analyst/scripts/export.py +64 -0
  9. fusion/_skills/fusion-intake/SKILL.md +128 -0
  10. fusion/_skills/fusion-intake/references/convert.md +104 -0
  11. fusion/_skills/fusion-intake/references/delivery.md +107 -0
  12. fusion/_skills/fusion-intake/references/fusion-conventions.md +149 -0
  13. fusion/_skills/fusion-intake/references/gate.md +107 -0
  14. fusion/_skills/fusion-intake/scripts/convert.py +836 -0
  15. fusion/_skills/fusion-intake/scripts/gate.py +267 -0
  16. fusion/_skills/fusion-librarian/SKILL.md +64 -0
  17. fusion/_skills/fusion-librarian/references/archive.md +21 -0
  18. fusion/_skills/fusion-librarian/references/create.md +14 -0
  19. fusion/_skills/fusion-librarian/references/cross-reference.md +45 -0
  20. fusion/_skills/fusion-librarian/references/fusion-conventions.md +149 -0
  21. fusion/_skills/fusion-librarian/references/promote.md +24 -0
  22. fusion/_skills/fusion-librarian/references/query.md +17 -0
  23. fusion/_skills/fusion-librarian/references/reflect.md +47 -0
  24. fusion/_skills/fusion-librarian/references/restructure.md +20 -0
  25. fusion/_skills/fusion-librarian/references/tag.md +13 -0
  26. fusion/_skills/fusion-librarian/scripts/link-repair.py +371 -0
  27. fusion/_skills/fusion-planner/SKILL.md +62 -0
  28. fusion/_skills/fusion-planner/references/close.md +12 -0
  29. fusion/_skills/fusion-planner/references/create-activity.md +38 -0
  30. fusion/_skills/fusion-planner/references/fusion-conventions.md +149 -0
  31. fusion/_skills/fusion-planner/references/horizon.md +20 -0
  32. fusion/bucket.py +77 -0
  33. fusion/checker.py +248 -0
  34. fusion/cli.py +406 -0
  35. fusion/document.py +155 -0
  36. fusion/hub.py +78 -0
  37. fusion/indexer.py +75 -0
  38. fusion/ledger.py +106 -0
  39. fusion/manifest.py +33 -0
  40. fusion/scaffold.py +120 -0
  41. fusion/setup.py +300 -0
  42. fusion/views.py +111 -0
  43. fusion_cli-1.1.0.dist-info/METADATA +67 -0
  44. fusion_cli-1.1.0.dist-info/RECORD +46 -0
  45. fusion_cli-1.1.0.dist-info/WHEEL +4 -0
  46. fusion_cli-1.1.0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,107 @@
1
+ # Delivery intake — batch, for a package of many files
2
+
3
+ A single dropped file walks the pipeline in SKILL.md one step at a time.
4
+ A **delivery** — a container or folder holding dozens to hundreds of
5
+ files arriving together — walks the same pipeline, but its mechanical
6
+ halves (admit, link) run once each, as a single validated batch, instead
7
+ of one subprocess call per file. This is the protocol proven live on a
8
+ 122-file `.athena` package: 122 sequential `admit` calls plus 122 `link`
9
+ calls became one `unpack`, one gate pass, one `batch` call for the admits
10
+ and links, with Stage 2 conversion (the operator's judgment) unchanged in
11
+ the middle.
12
+
13
+ ## The full protocol
14
+
15
+ 1. **Unpack.** `convert.py unpack --bucket <root> --file <container>` —
16
+ the container is a vehicle, not an original (references/gate.md). It
17
+ lands beside itself in `inbox/`, keeping folder context, and is
18
+ discarded. Sign the act `noted`.
19
+ 2. **Dedupe (hash sweep).** Before gating hundreds of files one at a
20
+ time, sweep the unpacked tree for byte-identical duplicates
21
+ (`sha256_of` on every member) — a delivery often repeats the same
22
+ attachment across several notes. Keep one copy per distinct hash;
23
+ report the rest as redundant and remove them from `inbox/`, signed
24
+ `noted`, same as `inbox_dups` in `references/gate.md`.
25
+ 3. **Gate.** `gate.py --bucket <root>` over what remains, then
26
+ `references/gate.md` for Stage 2 classification. A delivery's files
27
+ are usually all `new` — but run the topic match anyway; a delivery can
28
+ still update or conflict with what's already in the library.
29
+ 4. **Categories on basename collision.** A delivery's folder structure is
30
+ real information: when two admitted files would collide on the same
31
+ `(category, basename)` — the same filename nested under different
32
+ package folders — file each occurrence under its own per-folder
33
+ category (`records/2026-q1/report.pdf`,
34
+ `records/2026-q2/report.pdf`) rather than renaming either file.
35
+ `batch` enforces the collision check; it never picks a category for
36
+ you.
37
+ 5. **Convert (Stage 2, per file).** Unchanged — this is the operator's
38
+ judgment, never batched. Notes in particular get **lifted summaries**:
39
+ when a delivery's package manifest or index already carries a
40
+ one-line description per note, lift it verbatim into the document's
41
+ `## Summary` instead of re-deriving one from the body — it's the
42
+ author's own framing, and it's usually better than a machine-written
43
+ restatement.
44
+ 6. **Batch links from the package manifest.** Once every document for
45
+ this delivery is written, build ONE op-list from the package's own
46
+ manifest (see schema below) and run `batch`. If the delivery's admits
47
+ haven't happened yet either, put them in the same op-list — `batch`
48
+ validates and runs both halves together.
49
+ 7. **Close.** Per document, sign one ledger line: `fusion log converted
50
+ "sources/<cat>/<file> → <doc>" --bucket <root> --as <you>`. A delivery
51
+ of 122 files gets 122 `converted` lines — the ledger is a trail of
52
+ individual acts, batching the mechanics never collapses that trail.
53
+ Then `fusion index <root>` and `fusion check <root>`, green.
54
+ 8. **Archive pass — only when the delivery's own intent says so.** A
55
+ delivery that is itself an archival drop (its cover note, package
56
+ manifest, or the human's instruction says these are records being
57
+ retired, not active work) gets one archive pass at the end: move the
58
+ closed documents to an `archive/` subfolder inside their zone and set
59
+ `aurora: archive` on each, per `references/fusion-conventions.md`
60
+ §Archive. Do not archive by default — most deliveries add active
61
+ material, not retire it.
62
+
63
+ ## `batch` — schema and semantics
64
+
65
+ ```json
66
+ {"admits": [{"file": "<inbox-rel>", "category": "<cat>"}],
67
+ "links": [{"source": "<sources-rel>", "doc": "<zone-rel-doc>"}]}
68
+ ```
69
+
70
+ `admits[].file` is a path relative to `inbox/`; `links[].source` is the
71
+ resulting `sources/`-relative path (`<category>/<basename>`);
72
+ `links[].doc` is zone-relative (`library/...`, `activities/...`, or
73
+ `output/...`) — the document Stage 2 already wrote.
74
+
75
+ ```bash
76
+ uv run <skill>/scripts/convert.py batch --bucket <root> --ops <ops.json> --actor <you>
77
+ ```
78
+
79
+ Prints `{"admitted": n, "linked": m}`.
80
+
81
+ **Validation before damage, at batch scale.** Two passes, never partial:
82
+
83
+ 1. Every admit and every link is checked structurally BEFORE anything
84
+ moves: admit files exist in `inbox/` with a supported extension,
85
+ `(category, basename)` is unique both within the batch and against
86
+ every row already in `sources/MANIFEST.md` (and against any file
87
+ already sitting on disk in `sources/` even without a row), the actor
88
+ is a single token, and each link's `doc` is zone-relative while its
89
+ `source` either already has a MANIFEST row or is declared by this same
90
+ batch's admits. One bad op anywhere aborts the whole call — nothing
91
+ moves, nothing is appended, not even the good ops ahead of it in the
92
+ list.
93
+ 2. All admits then run (reusing `admit()` — still the only writer of
94
+ `sources/MANIFEST.md`). This half does not roll back.
95
+ 3. Before any link is written, every link's `doc` is checked to exist on
96
+ disk NOW — the operator's Stage 2 conversion must already have
97
+ produced it. If any doc is missing, the batch aborts naming it and NO
98
+ link is written, not even the ones whose doc is fine: partial linking
99
+ would leave some sources correctly cross-referenced and others
100
+ silently `—`, indistinguishable from "not yet converted."
101
+ 4. All links then run (reusing the same MANIFEST-writing path as the
102
+ `link` subcommand).
103
+
104
+ Conversion itself (Stage 2 — reading the file, writing the document) is
105
+ never part of a batch: it's the one step in this pipeline that stays the
106
+ operator's judgment, file by file, exactly as `references/convert.md`
107
+ describes.
@@ -0,0 +1,149 @@
1
+ # The Fusion Conventions — operator's card
2
+
3
+ > Carried byte-identical by all four Fusion skills. SPEC.md in the Fusion
4
+ > repository is normative; this card is the working summary. When they
5
+ > disagree, SPEC.md wins and this card has a bug.
6
+
7
+ **The contract:** the human judges, the AI operates, the files remember.
8
+
9
+ **Liberal reader, strict writer.** Never refuse to read a bucket because
10
+ something is missing or unknown. Never write into `library/`, `activities/`,
11
+ `output/`, or a register without satisfying every rule below first.
12
+
13
+ ## The bucket
14
+
15
+ ```
16
+ <bucket>/
17
+ ├── BUCKET.md # identity card + learned conventions
18
+ ├── LEDGER.md # append-only collaboration record
19
+ ├── inbox/ # drop zone — things arrive, nothing lives here
20
+ ├── sources/ # immutable originals + MANIFEST.md
21
+ ├── library/ # settled knowledge — documents
22
+ ├── activities/ # live work — documents + status
23
+ ├── workbench/ # ephemeral human+AI space — NO format rules
24
+ └── output/ # finished deliverables — documents
25
+ ```
26
+
27
+ - `sources/` is immutable: never modify, rename, or delete a registered file.
28
+ - `workbench/` has no rules; leaving it (promotion) is a deliberate,
29
+ ledger-logged act.
30
+ - Fusion holds knowledge and work, never media or code — documents point
31
+ (`resource:`) at big things, they never swallow them.
32
+ - `output/` may also hold non-markdown deliverable files (exports); their
33
+ names are still lowercase-hyphen slugs with a lowercase extension.
34
+
35
+ ## Before acting — always
36
+
37
+ 1. Read `BUCKET.md`: the identity card, then `## Conventions` — `### Rules`
38
+ are how this bucket works; `### Delegations` are your standing autonomy
39
+ grants. They bind you.
40
+ 2. Triage through `library/INDEX.md` and `activities/INDEX.md` plus document
41
+ summaries before opening bodies.
42
+
43
+ ## The document format
44
+
45
+ Every `.md` in `library/`, `activities/`, `output/` (except INDEX.md):
46
+
47
+ ```markdown
48
+ ---
49
+ title: Human-readable name
50
+ type: what-it-is # open vocabulary, curated per bucket
51
+ aurora: library # one of the eight — closed set
52
+ ---
53
+
54
+ ## Summary
55
+
56
+ Two or three lines a human or agent reads in two seconds.
57
+
58
+ ---
59
+
60
+ Full body. Cross-links are plain relative markdown links.
61
+ ```
62
+
63
+ - Required: `title`, `type`, `aurora` — exactly three.
64
+ - Optional: `tags`, `created`/`updated` (ISO dates), `due` (ISO date the
65
+ thing falls due — `fusion agenda` surfaces it), `source` (path into
66
+ `sources/`), `resource` (URI or bucket path of the thing this document
67
+ describes), `status` (`active`|`done`|`dormant`, activities only),
68
+ `data_sources` (paths list, output only).
69
+ - Body MUST be summary-first: `## Summary`, the lines, a `---` separator,
70
+ then everything else.
71
+ - Filenames: lowercase, hyphen-separated, `.md`, stem ≤60 chars.
72
+ - Preserve frontmatter keys you don't recognize.
73
+
74
+ ## Aurora — the eight (closed)
75
+
76
+ | Aurora | Meaning |
77
+ |---|---|
78
+ | `commitments` | Obligations, promises, deadlines |
79
+ | `focus` | Deep work, what deserves full attention |
80
+ | `ops` | Operations, process, the recurring |
81
+ | `collab` | Shared work, other people involved |
82
+ | `life` | Personal, wellbeing, the non-work |
83
+ | `explore` | Curiosity, research, the not-yet-settled |
84
+ | `archive` | Done, kept, out of the way |
85
+ | `library` | Reference, the settled knowledge |
86
+
87
+ Aurora says what a document means for the human's attention — never invent
88
+ a ninth value.
89
+
90
+ ## Archive
91
+
92
+ No archive zone: archived items move to an `archive/` subfolder inside their
93
+ zone AND take `aurora: archive`. Path is the truth, aurora is the signal —
94
+ both, always.
95
+
96
+ ## The registers — single writers, no exceptions
97
+
98
+ | File | Only writer | Your move |
99
+ |---|---|---|
100
+ | `LEDGER.md` | `fusion log` | `fusion log <verb> "<object>" [--note "…"] --as <you>` |
101
+ | `library/INDEX.md`, `activities/INDEX.md` | `fusion index` | run it after any add/move/edit that changes titles or summaries |
102
+ | `sources/MANIFEST.md` | fusion-intake's `scripts/convert.py` | everything enters `sources/` through the intake gate |
103
+
104
+ Never edit these three files by hand — not with an editor tool, not with
105
+ shell. The ledger verbs (closed set of eleven): `created`, `converted`,
106
+ `classified`, `indexed`, `moved`, `promoted`, `archived`, `restructured`,
107
+ `shipped`, `reflected`, `noted`. Sign with your agent name (`--as claude`,
108
+ or set `FUSION_ACTOR`).
109
+
110
+ ## The CLI crib
111
+
112
+ | Command | What it does |
113
+ |---|---|
114
+ | `fusion new <path>` | scaffold a conformant bucket |
115
+ | `fusion hub [add\|remove]` | list / register / retire buckets |
116
+ | `fusion log <verb> <object>` | append a signed ledger entry |
117
+ | `fusion index` | regenerate INDEX files (logs `indexed` when changed) |
118
+ | `fusion check [path]` | conformance: errors, warnings, honest exit codes |
119
+ | `fusion status [--since …]` | one bucket at a glance |
120
+ | `fusion today` | the composed morning across all hub buckets |
121
+ | `fusion agenda` | dated + active items across buckets |
122
+ | `fusion setup` | install/refresh the skills into detected agents |
123
+
124
+ All take `--json`. `--since last-reflection` scopes to the current
125
+ reflection window. **Exit gate for every skill scenario: `fusion check`
126
+ green before you call the work done.**
127
+
128
+ ## When you're blocked
129
+
130
+ - `fusion` not on PATH: stop and tell the human — the install is
131
+ `uv tool install ./fusion/cli` from a clone of the Fusion repository.
132
+ Never imitate the notary by hand: no register writes while the CLI is
133
+ missing.
134
+ - `fusion check` red and you cannot fix it: stop, show the findings
135
+ verbatim, leave the bucket as it stands, and sign nothing that claims
136
+ the work is done. A bucket is a git repo — nothing is unrecoverable.
137
+ - The human rejects a proposal: that is a result, not a failure. Record
138
+ it if the gear's protocol says to (`noted`), and move on.
139
+
140
+ ## The four accountabilities
141
+
142
+ | Skill | Owns |
143
+ |---|---|
144
+ | fusion-intake | The gate. Everything that enters, enters through it. |
145
+ | fusion-librarian | The order. Placement, curation, restructuring, reflection. |
146
+ | fusion-planner | The horizon. Activities, agendas, what today looks like. |
147
+ | fusion-analyst | The output. Deliverables that cite their sources. |
148
+
149
+ One skill, one accountability — the ledger says which hat was worn.
@@ -0,0 +1,107 @@
1
+ # The intake gate — Stage 2 (judgment)
2
+
3
+ Stage 1 (`scripts/gate.py`) wrote `workbench/.intake/gate-<runid>.json`
4
+ with six buckets: `exact_dups`, `near_dups`, `update_candidates`,
5
+ `clean_new`, `containers`, `inbox_dups`. This stage assigns each file's
6
+ final class and writes the intake report. It writes NOTHING to
7
+ `sources/` or `library/` — admission and conversion happen only after
8
+ this stage's confirmations.
9
+
10
+ ## Topic matching (do this before classifying)
11
+
12
+ For every `clean_new` and `update_candidates` entry:
13
+
14
+ 1. Read `library/INDEX.md` (and `activities/INDEX.md` if the content looks
15
+ like live work) — titles + summary lines are your map.
16
+ 2. Grep `library/` for the incoming file's key entities (names, products,
17
+ periods, metrics).
18
+ 3. Read the 1–3 most-related documents' summaries; open bodies only when
19
+ claims must be compared.
20
+
21
+ ## Per-bucket protocol
22
+
23
+ **`exact_dups` → duplicate (exact).** Record in the report with the
24
+ matched source. Do not convert, do not prompt — an exact re-drop carries
25
+ no new information.
26
+
27
+ **`inbox_dups` → the same bytes dropped twice in one batch.** The first
28
+ copy proceeds under its own class; the rest are redundant — report them,
29
+ and clean them out of `inbox/` (delete, signed with a `noted` ledger
30
+ line): `fusion log noted "inbox duplicate deleted: <name> (same bytes
31
+ as <kept>)" --bucket <root> --as <you>` per the standing rule of
32
+ 2026-07-10; a bucket's BUCKET.md Conventions may override.
33
+
34
+ **`clean_new` → new.** Run the topic match. No overlap → class `new`,
35
+ auto-proceed; the gate adds zero friction to genuinely new content.
36
+ Topic overlap without contradiction → still `new`, but note
37
+ "extends <doc>" in the report. Contradiction → reclassify `conflicting`.
38
+
39
+ **`update_candidates` → updated (confirm) — the identity guard.**
40
+ Read the incoming content and the matched source. Same logical identity
41
+ (a newer version of the SAME document), one candidate, unambiguous →
42
+ class `updated`. Similar-but-not-clearly-same, or multiple candidates →
43
+ ASK the user to confirm identity. Never guess a supersede. On `updated`,
44
+ the report states exactly what a confirmed update will do:
45
+ - admit the new file to `sources/` (renamed if the name collides — the
46
+ old original is immutable and stays);
47
+ - reconcile the existing library document IN PLACE: same path, content
48
+ re-converted, `updated:` bumped, `source:` repointed;
49
+ - MANIFEST: new row for the new original, its `library` column pointing
50
+ at the reconciled document.
51
+
52
+ **Contradiction detection → conflicting (confirm + resolve).** For
53
+ update candidates and topic-overlapping new files, compare claims:
54
+ figures (same metric, different value), dates (same event, different
55
+ date), conclusions (approved vs rejected). Do NOT flag: facts the
56
+ library is silent on, cosmetic rewording, or a clearly new reporting
57
+ period. On a real conflict, record the claim, both values, both sources —
58
+ and stop. Nothing converts until the human resolves it: accept as
59
+ correction (reconcile), reject (skip) (delete from `inbox/` + `noted`,
60
+ same line as a near-dup skip), or keep both with a note.
61
+
62
+ **`near_dups` → duplicate (near) (confirm).** Probably a re-export or
63
+ trivial edit. Never auto-skip, never auto-convert: offer skip / treat as
64
+ update / convert as new. A confirmed skip deletes the file from
65
+ `inbox/` and signs it: `fusion log noted "skipped <name>
66
+ (near-duplicate of <source>): <the human's words>" --bucket <root>
67
+ --as <you>` — nothing lives in inbox, not even a rejected guest.
68
+
69
+ **`containers` → vehicles, not originals.** Report each one (name, size).
70
+ Containers (`.zip`, `.athena`) never enter `sources/` intact — `unpack`
71
+ them beside the container (`inbox/<stem>/` for top-level drops, or a
72
+ nested container's own sub-folder if it lives deeper, keeping that
73
+ context) on the standing rule (or ask first if the container is
74
+ unexpected or its size is surprising), delete the container, sign the
75
+ act `noted`: `fusion log noted "unpacked inbox/<name> →
76
+ inbox/<stem>/ (<n> members; container discarded)" --bucket <root>
77
+ --as <you>`, then gate the extracted contents like any other inbox
78
+ drop.
79
+
80
+ ## The intake report (the prompt surface)
81
+
82
+ Present one report for the whole run — a table, then a detail block per
83
+ non-`new` row:
84
+
85
+ ```markdown
86
+ ## Intake report — <date>
87
+
88
+ | Incoming | Class | Matches | Action |
89
+ |---|---|---|---|
90
+ | acme-audit.pdf | new | — | converting |
91
+ | q1-report.xlsx | updated | sources/reports/q1-report.xlsx | supersede + reconcile (confirm) |
92
+ | brochure.pdf | duplicate | sources/marketing/brochure.pdf | auto-skipped (exact) |
93
+ | q1-financials.xlsx | conflicting | library/finance/q1.md | hold — revenue 5.0M vs 4.2M |
94
+ ```
95
+
96
+ Detail blocks name the evidence: similarity score, normalized-name match,
97
+ git history lines, the exact conflicting claims. The report is the
98
+ question — ask it, then act only on the answers.
99
+
100
+ ## After confirmation
101
+
102
+ Proceed per SKILL.md steps 2–4 for approved files only. For an `updated`
103
+ file, `prepare` targets the existing document — pass `--reconcile` plus
104
+ `--dest`/`--slug` set to its current path pieces (without `--reconcile`,
105
+ prepare refuses to touch an existing document) — and the reconciliation
106
+ edits that document in place. Delete gate run files
107
+ (`workbench/.intake/gate-*.json`) at the end of the run.