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.
- fusion/__init__.py +3 -0
- fusion/_skills/fusion-analyst/SKILL.md +50 -0
- fusion/_skills/fusion-analyst/references/assess.md +12 -0
- fusion/_skills/fusion-analyst/references/compare.md +12 -0
- fusion/_skills/fusion-analyst/references/export.md +18 -0
- fusion/_skills/fusion-analyst/references/fusion-conventions.md +149 -0
- fusion/_skills/fusion-analyst/references/report.md +13 -0
- fusion/_skills/fusion-analyst/scripts/export.py +64 -0
- fusion/_skills/fusion-intake/SKILL.md +128 -0
- fusion/_skills/fusion-intake/references/convert.md +104 -0
- fusion/_skills/fusion-intake/references/delivery.md +107 -0
- fusion/_skills/fusion-intake/references/fusion-conventions.md +149 -0
- fusion/_skills/fusion-intake/references/gate.md +107 -0
- fusion/_skills/fusion-intake/scripts/convert.py +836 -0
- fusion/_skills/fusion-intake/scripts/gate.py +267 -0
- fusion/_skills/fusion-librarian/SKILL.md +64 -0
- fusion/_skills/fusion-librarian/references/archive.md +21 -0
- fusion/_skills/fusion-librarian/references/create.md +14 -0
- fusion/_skills/fusion-librarian/references/cross-reference.md +45 -0
- fusion/_skills/fusion-librarian/references/fusion-conventions.md +149 -0
- fusion/_skills/fusion-librarian/references/promote.md +24 -0
- fusion/_skills/fusion-librarian/references/query.md +17 -0
- fusion/_skills/fusion-librarian/references/reflect.md +47 -0
- fusion/_skills/fusion-librarian/references/restructure.md +20 -0
- fusion/_skills/fusion-librarian/references/tag.md +13 -0
- fusion/_skills/fusion-librarian/scripts/link-repair.py +371 -0
- fusion/_skills/fusion-planner/SKILL.md +62 -0
- fusion/_skills/fusion-planner/references/close.md +12 -0
- fusion/_skills/fusion-planner/references/create-activity.md +38 -0
- fusion/_skills/fusion-planner/references/fusion-conventions.md +149 -0
- fusion/_skills/fusion-planner/references/horizon.md +20 -0
- fusion/bucket.py +77 -0
- fusion/checker.py +248 -0
- fusion/cli.py +406 -0
- fusion/document.py +155 -0
- fusion/hub.py +78 -0
- fusion/indexer.py +75 -0
- fusion/ledger.py +106 -0
- fusion/manifest.py +33 -0
- fusion/scaffold.py +120 -0
- fusion/setup.py +300 -0
- fusion/views.py +111 -0
- fusion_cli-1.1.0.dist-info/METADATA +67 -0
- fusion_cli-1.1.0.dist-info/RECORD +46 -0
- fusion_cli-1.1.0.dist-info/WHEEL +4 -0
- fusion_cli-1.1.0.dist-info/entry_points.txt +2 -0
fusion/views.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""fusion status / today / agenda — the composed day (design spec §5)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from collections import Counter
|
|
5
|
+
from dataclasses import asdict
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from . import bucket, hub, ledger
|
|
9
|
+
from .document import AURORAS
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def filter_since(entries: list[ledger.Entry], since: str | None):
|
|
13
|
+
if not since:
|
|
14
|
+
return entries
|
|
15
|
+
if since == "last-reflection":
|
|
16
|
+
last = max(
|
|
17
|
+
(i for i, e in enumerate(entries) if e.verb == "reflected"),
|
|
18
|
+
default=None,
|
|
19
|
+
)
|
|
20
|
+
return entries if last is None else entries[last + 1 :]
|
|
21
|
+
return [e for e in entries if e.date >= since]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def status(root: Path, since: str | None = None) -> dict:
|
|
25
|
+
b = bucket.load(root)
|
|
26
|
+
auroras: Counter = Counter()
|
|
27
|
+
types: Counter = Counter()
|
|
28
|
+
activities: Counter = Counter()
|
|
29
|
+
total = 0
|
|
30
|
+
for zone, rel, doc in bucket.iter_documents(root):
|
|
31
|
+
total += 1
|
|
32
|
+
auroras[doc.aurora or "—"] += 1
|
|
33
|
+
types[doc.type or "—"] += 1
|
|
34
|
+
if zone == "activities":
|
|
35
|
+
activities[doc.status or "unset"] += 1
|
|
36
|
+
entries = filter_since(ledger.read(root), since)
|
|
37
|
+
return {
|
|
38
|
+
"bucket": b.name or root.name,
|
|
39
|
+
"documents": total,
|
|
40
|
+
"auroras": dict(sorted(auroras.items())),
|
|
41
|
+
"types": dict(sorted(types.items())),
|
|
42
|
+
"activities": dict(sorted(activities.items())),
|
|
43
|
+
"ledger": [asdict(e) for e in entries[-10:]],
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _hub_buckets():
|
|
48
|
+
"""Yield (bucket_name, root) for every readable hub bucket — read means
|
|
49
|
+
a BUCKET.md exists, not that the bucket holds any documents yet."""
|
|
50
|
+
for entry in hub.load():
|
|
51
|
+
root = hub.resolve(entry)
|
|
52
|
+
if not (root / "BUCKET.md").is_file():
|
|
53
|
+
continue
|
|
54
|
+
b = bucket.load(root)
|
|
55
|
+
yield (b.name or entry.name), root
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _hub_documents():
|
|
59
|
+
"""Yield (bucket_name, zone, rel, doc) across every readable hub bucket."""
|
|
60
|
+
for name, root in _hub_buckets():
|
|
61
|
+
for zone, rel, doc in bucket.iter_documents(root):
|
|
62
|
+
yield name, zone, rel, doc
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _item(name: str, zone: str, rel, doc, date=None) -> dict:
|
|
66
|
+
return {
|
|
67
|
+
"bucket": name,
|
|
68
|
+
"title": doc.title or rel.stem,
|
|
69
|
+
"path": f"{zone}/{rel.as_posix()}",
|
|
70
|
+
"type": doc.type,
|
|
71
|
+
"aurora": doc.aurora,
|
|
72
|
+
"status": doc.status,
|
|
73
|
+
"date": date,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def today() -> dict:
|
|
78
|
+
groups: dict[str, list] = {}
|
|
79
|
+
buckets: list[str] = []
|
|
80
|
+
for name, root in _hub_buckets():
|
|
81
|
+
buckets.append(name)
|
|
82
|
+
for zone, rel, doc in bucket.iter_documents(root):
|
|
83
|
+
if "archive" in rel.parts or doc.aurora == "archive":
|
|
84
|
+
continue
|
|
85
|
+
is_active_activity = zone == "activities" and doc.status == "active"
|
|
86
|
+
is_commitment = doc.aurora == "commitments"
|
|
87
|
+
if is_active_activity or is_commitment:
|
|
88
|
+
groups.setdefault(doc.aurora or "—", []).append(
|
|
89
|
+
_item(name, zone, rel, doc)
|
|
90
|
+
)
|
|
91
|
+
ordered = {a: groups[a] for a in AURORAS if a in groups}
|
|
92
|
+
for aurora, items in groups.items():
|
|
93
|
+
if aurora not in ordered:
|
|
94
|
+
ordered[aurora] = items
|
|
95
|
+
return {"buckets": buckets, "groups": ordered}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def agenda() -> dict:
|
|
99
|
+
dated: list[dict] = []
|
|
100
|
+
active: list[dict] = []
|
|
101
|
+
for name, zone, rel, doc in _hub_documents():
|
|
102
|
+
if "archive" in rel.parts or doc.aurora == "archive":
|
|
103
|
+
continue
|
|
104
|
+
fm = doc.frontmatter or {}
|
|
105
|
+
raw = fm.get("due") or fm.get("date")
|
|
106
|
+
if raw is not None:
|
|
107
|
+
dated.append(_item(name, zone, rel, doc, date=str(raw)[:10]))
|
|
108
|
+
elif zone == "activities" and doc.status == "active":
|
|
109
|
+
active.append(_item(name, zone, rel, doc))
|
|
110
|
+
dated.sort(key=lambda i: i["date"])
|
|
111
|
+
return {"dated": dated, "active": active}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fusion-cli
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: The Fusion reference CLI — the notary of the Fusion Convention.
|
|
5
|
+
Author: Bluewaves Boutique
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Requires-Dist: pyyaml>=6.0
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# fusion — the notary of the Fusion Convention
|
|
12
|
+
|
|
13
|
+
The reference CLI. It records, checks, and composes; it never judges —
|
|
14
|
+
judgment belongs to the skill family. Buckets that follow
|
|
15
|
+
[the convention](../SPEC.md) are Fusion whether or not this tool ever
|
|
16
|
+
touches them.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
One line, installs the CLI and the four skills into every agent that
|
|
21
|
+
reads them:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
curl -fsSL https://raw.githubusercontent.com/bluewaves-creations/fusion/main/install.sh | sh
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Just the CLI, from PyPI:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
uv tool install fusion-cli
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
From a clone:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
git clone https://github.com/bluewaves-creations/fusion.git
|
|
37
|
+
uv tool install ./fusion/cli
|
|
38
|
+
fusion --version
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## The nine commands (there is no tenth)
|
|
42
|
+
|
|
43
|
+
| Command | Does |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `fusion new <path>` | Scaffold a complete bucket + register it in the hub |
|
|
46
|
+
| `fusion hub` | List / register (`add <path>`) / retire (`remove <name>`) buckets |
|
|
47
|
+
| `fusion log <verb> <object>` | Append a ledger entry — the only writer. No args: read the ledger |
|
|
48
|
+
| `fusion index [path]` | Regenerate `INDEX.md` in `library/` and `activities/` |
|
|
49
|
+
| `fusion check [path]` | Audit a bucket against SPEC §11 — exit 1 on errors |
|
|
50
|
+
| `fusion status [path]` | One bucket at a glance |
|
|
51
|
+
| `fusion today` | The composed day, across every bucket in the hub |
|
|
52
|
+
| `fusion agenda` | The wider horizon — dated and active, across the hub |
|
|
53
|
+
| `fusion setup` | Install the skills into every detected agent — the installer's brain. `--remove` undoes it |
|
|
54
|
+
|
|
55
|
+
Every command takes `--json` (agents parse, never scrape). `log`, `new`,
|
|
56
|
+
and `index` take `--as <actor>`; the pen defaults to `FUSION_ACTOR`, then
|
|
57
|
+
the OS username. `status` and `log` take `--since <date|last-reflection>`.
|
|
58
|
+
`log` also takes `--bucket` (resolves the ledger; default: walk up from the current directory).
|
|
59
|
+
The hub lives at `~/.fusion/hub.md` (`FUSION_HUB` overrides).
|
|
60
|
+
|
|
61
|
+
## Development
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
cd cli
|
|
65
|
+
uv run pytest # the suite — golden tests run against ../examples/crazy-ones
|
|
66
|
+
uv run fusion check ../examples/crazy-ones
|
|
67
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
fusion/__init__.py,sha256=llHMk8mEYtxolae7jRHA6InBi4s9_I63LdBprNYR12A,84
|
|
2
|
+
fusion/bucket.py,sha256=EZQH80Uu2VFetkcQPzzNreoCIJsg7rUbwze1FWmRYm4,2124
|
|
3
|
+
fusion/checker.py,sha256=W03XPxWorCqcvxz3oX2dt3Q7GzOHDgi1I0xWEJNUzRI,9462
|
|
4
|
+
fusion/cli.py,sha256=sHAJ4z1yOvdyM1vCqA-cu2nveZWK1xw2D_GvhzqJtq8,17205
|
|
5
|
+
fusion/document.py,sha256=Ajh-faFQLXgwVLibagdxIxwAjMI57CHKQbGsGNwNRNE,4813
|
|
6
|
+
fusion/hub.py,sha256=RgmXtlFqZ36C4rnP4D3syr8O6f3ZrKTIVQGYd_7EeNY,1974
|
|
7
|
+
fusion/indexer.py,sha256=SA9ZBOh4OSZ4lx2x33yUpPte82ZHGPpGtLvFfw6Yhj8,2694
|
|
8
|
+
fusion/ledger.py,sha256=oJNladLLRhA4zhyVTUOgzaaMy3o8nTjDgg3qza0uotw,3280
|
|
9
|
+
fusion/manifest.py,sha256=7UU5HlvTctoSpz9iqLlwJxYQLewXj7GJv3zdhIHoeyI,871
|
|
10
|
+
fusion/scaffold.py,sha256=Dzz5np91MUWCtS38l3dIY60IaXdPFKO2AfjxMsIV5CU,3607
|
|
11
|
+
fusion/setup.py,sha256=j_3nwgvtvxe-ZuIbQXrQWfI8MSoMLRycxV6x6Gp_99E,12771
|
|
12
|
+
fusion/views.py,sha256=hCdq1IjTisd-8drXkuoTmt680NHSBV3dyOaFERj0qes,3796
|
|
13
|
+
fusion/_skills/fusion-analyst/SKILL.md,sha256=T7XnaeylxdyniCcWtXZYEKvgzOZx_I-H2nmHvmX5HKI,2872
|
|
14
|
+
fusion/_skills/fusion-analyst/references/assess.md,sha256=6JKusH38m5uCXp0zRtFsVmiAMdmFL7vwA0jtlqYKGFs,624
|
|
15
|
+
fusion/_skills/fusion-analyst/references/compare.md,sha256=uBEIVC7fa-D6t_SCXNIGGI_dZAYtLIdQ9Ds-ivLizv8,626
|
|
16
|
+
fusion/_skills/fusion-analyst/references/export.md,sha256=CCcirWNSwkZ6GbDeVn1-tmVT7SbTvN9cfIqIQR_Fw6Q,747
|
|
17
|
+
fusion/_skills/fusion-analyst/references/fusion-conventions.md,sha256=dLqp_HFTnhUKl69CyeoEbNXjMy1lCOSfDgbWMVh-tfI,6216
|
|
18
|
+
fusion/_skills/fusion-analyst/references/report.md,sha256=kjsh5G9xaHAuEiotB74pLc_4bs5rYKilSPmJwA2Agbs,751
|
|
19
|
+
fusion/_skills/fusion-analyst/scripts/export.py,sha256=59HhpIfJqPikGUI2GFxrg1JIAQ2JYJnsZvP2sCi67oc,1959
|
|
20
|
+
fusion/_skills/fusion-intake/SKILL.md,sha256=-zhBmLkUgJRnM3DqXfhKc6LQdlvE_8QtWXOcIPhPAGQ,7557
|
|
21
|
+
fusion/_skills/fusion-intake/references/convert.md,sha256=yxEdUnvxVTmSX7wqyYhdRBL49ph3inOEswESVXeO3bY,4392
|
|
22
|
+
fusion/_skills/fusion-intake/references/delivery.md,sha256=r1qmVfq2sUhBqmW35sCEfjyH-C2NTE1RBPEMigXap14,5879
|
|
23
|
+
fusion/_skills/fusion-intake/references/fusion-conventions.md,sha256=dLqp_HFTnhUKl69CyeoEbNXjMy1lCOSfDgbWMVh-tfI,6216
|
|
24
|
+
fusion/_skills/fusion-intake/references/gate.md,sha256=bJ3cEnVXJGqGg8DmkjJakzzzILOlcpr7GZi392YZ-6A,5304
|
|
25
|
+
fusion/_skills/fusion-intake/scripts/convert.py,sha256=FcFQ-ibeWjkyujG-4IZQltUY072RzlFLH1XO7A3v18Q,34829
|
|
26
|
+
fusion/_skills/fusion-intake/scripts/gate.py,sha256=mn2pG2ldAS_h1Y6hrZdB-8QNHo8xYojGPDLsQ5Ja0aY,10002
|
|
27
|
+
fusion/_skills/fusion-librarian/SKILL.md,sha256=EsEaH5TIswQYkeNjO5Xb4Xj704VmcKiig9TGTB6bXuE,3706
|
|
28
|
+
fusion/_skills/fusion-librarian/references/archive.md,sha256=i4xITrqsjjC68aJq1ktsefzZYCChed6uFKuitJxAMy8,1088
|
|
29
|
+
fusion/_skills/fusion-librarian/references/create.md,sha256=cH-NSwPLXDsweQ4MFQLw_YEUwtjksFMa7lU3KqW-x4o,869
|
|
30
|
+
fusion/_skills/fusion-librarian/references/cross-reference.md,sha256=HhEs_j7SqaGgmAE2wJI64x3J8fcmL6uG9H4y8p3DcnI,2481
|
|
31
|
+
fusion/_skills/fusion-librarian/references/fusion-conventions.md,sha256=dLqp_HFTnhUKl69CyeoEbNXjMy1lCOSfDgbWMVh-tfI,6216
|
|
32
|
+
fusion/_skills/fusion-librarian/references/promote.md,sha256=x6qLJWqt6zBN3FgF9r5K65jjwE5h43qvM4e4R9wEuvE,1128
|
|
33
|
+
fusion/_skills/fusion-librarian/references/query.md,sha256=JmQHQfdktK6hFoC7x-ms5Xvj2oGluAiwuO_mpY4MbeQ,831
|
|
34
|
+
fusion/_skills/fusion-librarian/references/reflect.md,sha256=3lkmqhfOhJdZfKw_2vHwEf19Kp4DXZSBI4jyAf1C0WQ,1933
|
|
35
|
+
fusion/_skills/fusion-librarian/references/restructure.md,sha256=U_WtJzmo_uNfIZAN0inga0mtFhqQO1xIvT6VJ2EI1aE,1077
|
|
36
|
+
fusion/_skills/fusion-librarian/references/tag.md,sha256=E9M2Wec5PiGlMpEAF3Q3VbYYDo7O9kMA5ZPv22pbmSs,689
|
|
37
|
+
fusion/_skills/fusion-librarian/scripts/link-repair.py,sha256=q3_dDf-d1kJ852MzzPuxPFAWNlwYJMizbvRlFbG079w,15422
|
|
38
|
+
fusion/_skills/fusion-planner/SKILL.md,sha256=ljMMYpUkykzwpj8Gja-Kfd0QoZ--bSUWc_NRUJvUaro,3018
|
|
39
|
+
fusion/_skills/fusion-planner/references/close.md,sha256=ucKMR93bQazTE532mNqKJLTK0iMji3YzYuIMZfCr51s,709
|
|
40
|
+
fusion/_skills/fusion-planner/references/create-activity.md,sha256=RFIJStk1CCoUYLVBZUxaVz4-SgNRm7YGGesRup4aR-U,994
|
|
41
|
+
fusion/_skills/fusion-planner/references/fusion-conventions.md,sha256=dLqp_HFTnhUKl69CyeoEbNXjMy1lCOSfDgbWMVh-tfI,6216
|
|
42
|
+
fusion/_skills/fusion-planner/references/horizon.md,sha256=E3YchjopfxC-ERTyAxTj5hzmvEnFYd_teY8TScYcg2o,1096
|
|
43
|
+
fusion_cli-1.1.0.dist-info/METADATA,sha256=G1YNkkxeO0gEhxihsLQVwmRAQNfFQi6EUN55RhvHfG8,2289
|
|
44
|
+
fusion_cli-1.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
45
|
+
fusion_cli-1.1.0.dist-info/entry_points.txt,sha256=fVgiRsE5pSqmAqNKk9YQCJnpBW3A780OzNC-A4CjzqM,49
|
|
46
|
+
fusion_cli-1.1.0.dist-info/RECORD,,
|