abstractskill 0.3.2__tar.gz → 0.3.3__tar.gz

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 (94) hide show
  1. {abstractskill-0.3.2/src/abstractskill.egg-info → abstractskill-0.3.3}/PKG-INFO +2 -2
  2. {abstractskill-0.3.2 → abstractskill-0.3.3}/README.md +1 -1
  3. {abstractskill-0.3.2 → abstractskill-0.3.3}/pyproject.toml +1 -1
  4. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/__init__.py +1 -1
  5. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/catalog.yaml +1 -1
  6. abstractskill-0.3.3/src/abstractskill/registry/skills/abstract-release/SKILL.md +209 -0
  7. abstractskill-0.3.3/src/abstractskill/registry/skills/abstract-release/agents/openai.yaml +4 -0
  8. abstractskill-0.3.3/src/abstractskill/registry/skills/abstract-release/references/package-discovery.md +74 -0
  9. abstractskill-0.3.3/src/abstractskill/registry/skills/abstract-release/references/package-inventory.md +131 -0
  10. abstractskill-0.3.3/src/abstractskill/registry/skills/abstract-release/references/release-process.md +227 -0
  11. abstractskill-0.3.3/src/abstractskill/registry/skills/abstract-release/scripts/abstract_release_plan.py +1104 -0
  12. abstractskill-0.3.3/src/abstractskill/registry/skills/abstract-release/scripts/pypi_visibility_gate.py +207 -0
  13. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/coredoc/SKILL.md +68 -1
  14. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/validations.yaml +35 -4
  15. {abstractskill-0.3.2 → abstractskill-0.3.3/src/abstractskill.egg-info}/PKG-INFO +2 -2
  16. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill.egg-info/SOURCES.txt +7 -0
  17. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_bundled.py +4 -4
  18. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_shelf.py +6 -1
  19. {abstractskill-0.3.2 → abstractskill-0.3.3}/LICENSE +0 -0
  20. {abstractskill-0.3.2 → abstractskill-0.3.3}/setup.cfg +0 -0
  21. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/bundled.py +0 -0
  22. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/catalog.py +0 -0
  23. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/demand.py +0 -0
  24. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/errors.py +0 -0
  25. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/hash.py +0 -0
  26. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/loader.py +0 -0
  27. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/models.py +0 -0
  28. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/parser.py +0 -0
  29. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/policy.py +0 -0
  30. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/prompt.py +0 -0
  31. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/advisories.yaml +0 -0
  32. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/guidance.yaml +0 -0
  33. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/licenses/meshvault-live-editing.LICENSE +0 -0
  34. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/licenses/verification-before-completion.LICENSE +0 -0
  35. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/abstractframework-gateway/SKILL.md +0 -0
  36. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/adr/SKILL.md +0 -0
  37. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/adr/agents/openai.yaml +0 -0
  38. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/adr/references/adr-template-and-workflow.md +0 -0
  39. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/adr/references/default-adr-catalog.md +0 -0
  40. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/adr/references/reader-first-adr-style.md +0 -0
  41. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/adversarial-iteration/SKILL.md +0 -0
  42. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/agora-collaboration/SKILL.md +0 -0
  43. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/agora-collaboration/references/failure-ledger.md +0 -0
  44. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/agora-collaboration/references/mechanics.md +0 -0
  45. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/architect/SKILL.md +0 -0
  46. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/architect/agents/openai.yaml +0 -0
  47. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/architect/references/reviewer-memory.md +0 -0
  48. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/backlog/SKILL.md +0 -0
  49. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/backlog/agents/openai.yaml +0 -0
  50. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/backlog/references/abstractframework-board.md +0 -0
  51. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/backlog/references/hub-work-join.md +0 -0
  52. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/backlog/references/layout-and-templates.md +0 -0
  53. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/backlog/references/maintenance-checklists.md +0 -0
  54. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/cicd/SKILL.md +0 -0
  55. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/cicd/agents/openai.yaml +0 -0
  56. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/cicd/references/docs-and-containers.md +0 -0
  57. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/cicd/references/maintenance-playbook.md +0 -0
  58. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/cicd/references/package-publishing.md +0 -0
  59. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/cicd/references/repository-setup.md +0 -0
  60. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/cicd/references/workflow-patterns.md +0 -0
  61. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/coredoc/agents/openai.yaml +0 -0
  62. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/coredoc/references/agent-skill.md +0 -0
  63. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/coredoc/references/core-doc-set.md +0 -0
  64. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/coredoc/references/llms-files.md +0 -0
  65. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/coredoc/references/maintenance-playbook.md +0 -0
  66. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/entity-observation/SKILL.md +0 -0
  67. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/entity-self-knowledge/SKILL.md +0 -0
  68. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/entity-self-knowledge/references/capability_map.md +0 -0
  69. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/meshvault-live-editing/SKILL.md +0 -0
  70. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/review/SKILL.md +0 -0
  71. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/review/agents/openai.yaml +0 -0
  72. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/review/references/reviewer-memory.md +0 -0
  73. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/uxreview/SKILL.md +0 -0
  74. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/uxreview/agents/openai.yaml +0 -0
  75. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/uxreview/references/reviewer-memory.md +0 -0
  76. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/registry/skills/verification-before-completion/SKILL.md +0 -0
  77. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/selection.py +0 -0
  78. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/tree.py +0 -0
  79. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/trust.py +0 -0
  80. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill/validation.py +0 -0
  81. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill.egg-info/dependency_links.txt +0 -0
  82. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill.egg-info/requires.txt +0 -0
  83. {abstractskill-0.3.2 → abstractskill-0.3.3}/src/abstractskill.egg-info/top_level.txt +0 -0
  84. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_audience.py +0 -0
  85. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_catalog.py +0 -0
  86. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_demand.py +0 -0
  87. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_loader.py +0 -0
  88. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_parser.py +0 -0
  89. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_policy.py +0 -0
  90. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_refresh_shelf_pins.py +0 -0
  91. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_selection.py +0 -0
  92. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_tree.py +0 -0
  93. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_trust.py +0 -0
  94. {abstractskill-0.3.2 → abstractskill-0.3.3}/tests/test_vendor_script.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractskill
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: Agent Skills (SKILL.md) parsing, discovery, trust gating, and demand derivation for AbstractFramework
5
5
  Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
6
6
  License-Expression: MIT
@@ -66,7 +66,7 @@ The wheel carries the library and the curated skill registry (the shelf below).
66
66
  `pip install abstractskill` installs the reviewed shelf as package data:
67
67
 
68
68
  ```
69
- abstractskill/registry/skills/ # 14 curated skills (one folder per SKILL.md)
69
+ abstractskill/registry/skills/ # 15 curated skills (one folder per SKILL.md)
70
70
  abstractskill/registry/licenses/ # upstream licenses of catalog-vendored skills
71
71
  abstractskill/registry/validations.yaml # trust records: byte pins per skill tree
72
72
  abstractskill/registry/advisories.yaml # do-not-use advisories (empty at v1, by design)
@@ -33,7 +33,7 @@ The wheel carries the library and the curated skill registry (the shelf below).
33
33
  `pip install abstractskill` installs the reviewed shelf as package data:
34
34
 
35
35
  ```
36
- abstractskill/registry/skills/ # 14 curated skills (one folder per SKILL.md)
36
+ abstractskill/registry/skills/ # 15 curated skills (one folder per SKILL.md)
37
37
  abstractskill/registry/licenses/ # upstream licenses of catalog-vendored skills
38
38
  abstractskill/registry/validations.yaml # trust records: byte pins per skill tree
39
39
  abstractskill/registry/advisories.yaml # do-not-use advisories (empty at v1, by design)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "abstractskill"
7
- version = "0.3.2"
7
+ version = "0.3.3"
8
8
  description = "Agent Skills (SKILL.md) parsing, discovery, trust gating, and demand derivation for AbstractFramework"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -140,4 +140,4 @@ __all__ = [
140
140
  "validate_skill_name",
141
141
  ]
142
142
 
143
- __version__ = "0.3.2"
143
+ __version__ = "0.3.3"
@@ -16,7 +16,7 @@
16
16
  # four yaml files shipped in the abstractskill wheel). Bump it whenever any
17
17
  # of that content changes; seed_registry() records it in <dest>/.seeded.json
18
18
  # and tests/test_bundled.py pins it to a content digest.
19
- version: "2026.10.21"
19
+ version: "2026.10.27"
20
20
 
21
21
  skills:
22
22
 
@@ -0,0 +1,209 @@
1
+ ---
2
+ name: abstract-release
3
+ description: Plan and run an AbstractFramework release wave across its packages in dependency order. Covers which packages changed, the release order, the per-package mechanics (tag push or workflow_dispatch, the PyPI/npm/crates.io GitHub environments), the gates (adversarial review before merge, real-weights or real-gateway end-to-end checks, merge only on all-green, registry visibility, dependency-floor propagation with the install-profile pin tests), and the final report. Use when releasing one or more AbstractFramework packages, raising inter-package floors, publishing the root `abstractframework` profile, or auditing whether a release wave is complete. For a single package with no dependents, the package-level `release` skill is enough.
4
+ ---
5
+
6
+ # Abstract Release
7
+
8
+ AbstractFramework is 34 packages in 22 repositories on 2026-10-27 (Python on PyPI, npm packages
9
+ and apps, Rust crates on crates.io; `./scripts/deps.sh` in the workspace lists them). A release
10
+ wave publishes the changed ones from the bottom of the dependency graph upward, so every package
11
+ a parent depends on is already published, green, and visible on its registry before the parent
12
+ raises its floor and publishes.
13
+
14
+ This skill orchestrates the wave. Inside each package, use the `release` skill (version, changelog,
15
+ tag, publish), `coredoc` (README, docs, llms files, version source), `backlog` (the work item and
16
+ its evidence) and `adr` (durable rules). This skill adds what only shows up across packages: the
17
+ order, the gates between packages, floor propagation, and the root profile.
18
+
19
+ ## Before you start
20
+
21
+ - Default to a read-only plan. Commits, pushes, tags, workflow dispatches, publishes, CI reruns and
22
+ skipped gates need the operator's explicit approval (see the approval packet in
23
+ `references/release-process.md`).
24
+ - Set the skill directory once; the scripts run from any working directory:
25
+
26
+ ```bash
27
+ SKILL_DIR=~/.claude/skills/abstract-release # or wherever this skill is installed
28
+ AF_ROOT=/path/to/abstractframework # the workspace root (holds scripts/lib/packages.txt)
29
+ git -C "$AF_ROOT/<repo>" fetch --tags # per repository: the planner reads local release tags
30
+ python3 "$SKILL_DIR/scripts/abstract_release_plan.py" "$AF_ROOT" --registry
31
+ python3 "$SKILL_DIR/scripts/abstract_release_plan.py" "$AF_ROOT" --registry --json -o "$AF_ROOT/untracked/release-plan.json"
32
+ ```
33
+
34
+ Without a path, the planner finds the workspace by walking up from the current directory
35
+ (or reads `ABSTRACTFRAMEWORK_ROOT`). A package is in the wave when it has uncommitted changes,
36
+ commits since its last release tag, a version with no tag, or (with `--registry`) a version not
37
+ on its registry; packages downstream of one are added for a floor review only.
38
+ - Read `references/package-inventory.md` for the tiers and each package's version source,
39
+ release trigger and registry environment. Read `references/release-process.md` before the first
40
+ irreversible step.
41
+ - Operator checkouts can hold uncommitted work that is not yours. Never stage it, never rebase a
42
+ diverged branch for the operator. When you need a clean tree, use a worktree in a scratch
43
+ directory.
44
+
45
+ ## The order
46
+
47
+ Release by published dependency floors, not by what happens to pass locally:
48
+
49
+ 1. Independent lower packages: `abstractvoice`, `abstractvision`, `abstractmusic` (and the other
50
+ tier-0 media plugins), `abstractskill`, and the AbstractUIC npm packages (`ui-kit`,
51
+ `app-server`, `monitor-*`, `panel-chat`).
52
+ 2. `abstractsemantics` and `abstractmemory` (AbstractMemory owns the memory graph).
53
+ 3. `abstractcore`.
54
+ 4. `abstractruntime`.
55
+ 5. `abstractagent`.
56
+ 6. `abstractgateway`.
57
+ 7. Apps on the gateway: `abstractassistant`, `abstractcode`, `abstractobserver`, `abstractentity`,
58
+ `abstractflow`, `abstractcontinuum`, `abstractnote` (Python on the gateway and AbstractMemory,
59
+ plus its web app).
60
+ 8. Root `abstractframework`: pins, `RELEASE_VERSIONS`, install manifest, installers, install docs.
61
+
62
+ The planner refines this from the real manifests: it skips packages with nothing to release and
63
+ adds every package downstream of a changed package for a floor review. `scripts/lib/packages.txt`
64
+ in the workspace is the inventory the workspace scripts use; the planner reports any package it
65
+ finds on disk that the inventory is missing.
66
+
67
+ ## The per-package loop
68
+
69
+ Repeat for each package in the plan's `release_wave`, lowest order first.
70
+
71
+ 1. **Work item.** Every change has a `backlog` item in its own package; close it with evidence.
72
+ A rule that should outlive the task (for example "no direct lower-level imports; a missing
73
+ capability is surfaced by the runtime") becomes an ADR.
74
+ 2. **Version and docs.** Bump the package's version source (named per package in
75
+ `references/package-inventory.md`; some packages keep it in two places that must agree). Fold
76
+ `Unreleased` into one dated `CHANGELOG.md` section for the version. Run `coredoc`'s release
77
+ checklist: version source, README badges and install snippets, package metadata, llms files
78
+ regenerated with the package's generator and committed, backlog/ADR trace.
79
+ 3. **Local proof.** Run the package tests. For anything that touches an engine, run a real-weights
80
+ end-to-end check on the machine, not a mock. For gateway routes, go through a scratch gateway
81
+ over HTTP (recipe in `references/release-process.md`). A local failure can be the stale venv,
82
+ not the code: CI installs from the published pins, so decide per failure whether it is a code
83
+ bug or the environment (keys in the shell, CLIs on PATH, missing extras, older siblings).
84
+ 4. **Adversarial review before merge.** A read-only reviewer that did not write the diff reviews
85
+ it. Fix the confirmed findings, re-verify, and record what was found.
86
+ 5. **Pull request, merge only on all-green.**
87
+
88
+ ```bash
89
+ gh pr create --base main --head <branch> --title "<package> X.Y.Z: <summary>" --body-file <notes.md>
90
+ gh pr checks <N> --watch
91
+ gh pr checks <N> | awk -F'\t' '{print $2}' | sort -u # must print exactly: pass
92
+ gh pr merge <N> --merge # alone, never chained after other commands
93
+ gh pr view <N> --json state,mergeCommit # confirm MERGED before tagging
94
+ ```
95
+
96
+ 6. **Publish.** Read the package's row in `references/package-inventory.md` (trigger, dispatch
97
+ inputs, environment policy) first. Then:
98
+ - Confirm the publishing environment admits the ref you will publish from, or the publish job
99
+ is refused after the build passed (a 404 means no policy: any ref may deploy):
100
+
101
+ ```bash
102
+ gh api repos/lpalbou/<Repo>/environments/<pypi|npm|crates-io>/deployment-branch-policies \
103
+ --jq '.branch_policies[]|"\(.type):\(.name)"'
104
+ ```
105
+
106
+ - Confirm you publish the merged commit:
107
+ `git switch main && git pull --ff-only`, then `git rev-parse HEAD` must equal the PR's
108
+ `mergeCommit.oid`.
109
+ - Tag push (most packages; AbstractUIC tags its root `package.json` version, AbstractCode's
110
+ web app tags `web-vX.Y.Z`):
111
+
112
+ ```bash
113
+ git tag -a vX.Y.Z -m "<package> X.Y.Z" && git push origin vX.Y.Z
114
+ ```
115
+
116
+ - Or `workflow_dispatch` from main, with the inputs that workflow declares (the run builds,
117
+ publishes and creates the tag; required where the environment admits only `main`, as for
118
+ AbstractAssistant):
119
+
120
+ ```bash
121
+ gh workflow run release.yml --ref main -f version=X.Y.Z # most Python packages
122
+ gh workflow run release.yml --ref main -f version=X.Y.Z -f publish=true \
123
+ -f publish_confirmation=publish-<package>-X.Y.Z # AbstractRuntime, AbstractMusic
124
+ ```
125
+
126
+ - Follow the run: `gh run list --workflow release.yml --branch vX.Y.Z -L 1` for a tag push
127
+ (`--event workflow_dispatch` for a dispatch), then `gh run watch <run-id> --exit-status`.
128
+ 7. **Visibility gate.** The registry index lags the upload. Do not raise a floor upstream until
129
+ the version resolves:
130
+
131
+ ```bash
132
+ python3 "$SKILL_DIR/scripts/pypi_visibility_gate.py" --wait 900 abstractvoice==X.Y.Z
133
+ python3 "$SKILL_DIR/scripts/pypi_visibility_gate.py" --wait 900 npm:@abstractframework/ui-kit==X.Y.Z
134
+ python3 "$SKILL_DIR/scripts/pypi_visibility_gate.py" --wait 900 crates:abstractgateway-console==X.Y.Z
135
+ ```
136
+
137
+ 8. **Floor propagation.** Raise the floor in each direct dependent the plan lists under
138
+ `dependency_floor_reviews`. Update the tests that pin floors literally in the same change
139
+ (for example AbstractGateway's `tests/test_gateway_install_profiles.py` and
140
+ `live_deltas.ABSTRACTRUNTIME_FLOOR`), respect the cross-package floor rules in
141
+ `references/package-inventory.md`, and refresh npm lockfiles after an AbstractUIC publish.
142
+ Rerun the planner and continue with the updated wave.
143
+
144
+ ## Gates (never skipped without the operator's approval)
145
+
146
+ 1. Adversarial review of every diff before merge.
147
+ 2. Real-weights (engines) or real-gateway (routes) end-to-end proof on the machine.
148
+ 3. Merge only when every check is `pass`; check the PR state after merging.
149
+ 4. A parent is released only after each lower version is visible on its registry and the lower
150
+ package's release run is green.
151
+ 5. Every dependent's floor or exact pin is raised or explicitly confirmed, with its pin tests.
152
+ 6. One dated changelog section per released version; llms files regenerated; backlog item closed
153
+ with evidence; durable rules recorded as ADRs.
154
+ 7. No publish from a checkout with uncommitted release-scope changes.
155
+ 8. Root `abstractframework` last, and only when its pins, `RELEASE_VERSIONS`, install manifest,
156
+ installers and install docs match the released matrix. If the wave stops earlier, either
157
+ release the root profile in the same approved wave or file a backlog item and say plainly that
158
+ `pip install abstractframework[...]` still resolves the older matrix.
159
+
160
+ Stop and report on: an ambiguous version source, a duplicate target version, an unclear publish
161
+ destination, a red or unknown check, a version not visible on its registry, or a floor that still
162
+ points below a just-released version.
163
+
164
+ ## Final report
165
+
166
+ End the wave with this report (one row per package touched, including the ones you decided not
167
+ to release):
168
+
169
+ ```markdown
170
+ # AbstractFramework release wave <date>
171
+
172
+ | Package | Released | Registry | Release run | Floors raised in dependents |
173
+ |---|---|---|---|---|
174
+ | abstractvoice | 0.19.1 (from 0.18.2) | PyPI, visible | <run URL>, green | abstractcore >=0.19.1 |
175
+ | ... | not released: <reason> | | | |
176
+
177
+ ## New capabilities (per package, user-facing)
178
+ - abstractvoice 0.19.1: ...
179
+
180
+ ## Gates
181
+ - Adversarial reviews: <package: findings fixed / none>
182
+ - End-to-end proofs: <package: what ran, on which weights or gateway>
183
+ - Root profile: released X.Y.Z | not released, backlog <id>, users of `abstractframework[...]` still get <old matrix>
184
+
185
+ ## Remaining work and improvements
186
+ - <package>: <follow-up>, backlog <id>
187
+ - Process: <what slowed the wave, the fix proposed>
188
+ ```
189
+
190
+ ## Scripts
191
+
192
+ - `scripts/abstract_release_plan.py [ROOT] [--registry] [--json] [-o FILE]`: read-only
193
+ inventory, dependency order, release signals per package, release wave, floor reviews, root pin
194
+ drift (pyproject pins and `RELEASE_VERSIONS` / `NPM_RELEASE_VERSIONS` / `CRATE_RELEASE_VERSIONS`),
195
+ changes outside any package, and packages missing from `scripts/lib/packages.txt`. Needs
196
+ Python 3.11+ (or `tomli` installed).
197
+ - `scripts/pypi_visibility_gate.py SPEC... [--from-plan FILE] [--wait SECONDS]`: checks that each
198
+ `name==version` (PyPI), `npm:@scope/name==version` or `crates:name==version` is installable from
199
+ its registry; `--from-plan` checks the plan's changed packages; with `--wait` it polls until
200
+ visible or the deadline passes. Exit code 0 only when all are visible. Python 3.9+.
201
+
202
+ ## References
203
+
204
+ - `references/release-process.md`: the full process: order, per-package loop, gates in detail,
205
+ the scratch-gateway recipe, changelog/llms/backlog/ADR duties, approval packet, stop conditions,
206
+ partial releases, and the pitfalls seen in practice.
207
+ - `references/package-inventory.md`: the tiers, and per package its version source, release
208
+ trigger, registry environment, llms generator, and package-specific rules.
209
+ - `references/package-discovery.md`: how the planner discovers packages and reads its output.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Abstract Release"
3
+ short_description: "Release AbstractFramework packages in dependency order, with gates."
4
+ default_prompt: "Use $abstract-release to plan an AbstractFramework release wave from the changed packages upward, run each package through review, end-to-end proof, all-green merge, publish and registry visibility, propagate dependency floors, and end with the wave report."
@@ -0,0 +1,74 @@
1
+ # Package Discovery
2
+
3
+ `scripts/abstract_release_plan.py` builds a deterministic, read-only picture of the workspace. Run
4
+ it before the wave, after every release, and after every floor bump.
5
+
6
+ ```bash
7
+ python3 "$SKILL_DIR/scripts/abstract_release_plan.py" "$AF_ROOT" --registry
8
+ python3 "$SKILL_DIR/scripts/abstract_release_plan.py" "$AF_ROOT" --registry --json -o "$AF_ROOT/untracked/release-plan.json"
9
+ ```
10
+
11
+ Without a path it uses `ABSTRACTFRAMEWORK_ROOT`, else the nearest ancestor of the current directory
12
+ that holds `scripts/lib/packages.txt`, and stops with an error when there is none (it never walks
13
+ an arbitrary directory unless you pass it explicitly). It needs Python 3.11+ (tomllib) or the
14
+ `tomli` backport.
15
+
16
+ ## Release signals
17
+
18
+ A package is **changed** (a release candidate) when any of these holds:
19
+
20
+ - uncommitted changes in its directory (`git status`);
21
+ - commits touching its directory since its last release tag (`git describe --match 'v*'`; a
22
+ package in a sub-directory with its own tag family, such as AbstractCode's `web-v*`, uses it).
23
+ Tags are read locally: run `git fetch --tags` in each repository first, or a release a workflow
24
+ tagged remotely shows as untagged;
25
+ - for a package at its repository root, no local tag `v<version>`;
26
+ - with `--registry`, its local version is missing from PyPI, npm or crates.io (a 404; a network
27
+ error leaves it unknown, never "unpublished").
28
+
29
+ Every package downstream of a changed package joins the wave as "floor review only".
30
+
31
+ ## How it finds packages
32
+
33
+ - **With the inventory** (`scripts/lib/packages.txt`, the list the workspace scripts read): one
34
+ package per row, read from `<repo>/<path>` (`pyproject.toml`, `package.json` or `Cargo.toml`).
35
+ Scratch copies elsewhere in the workspace (worktrees and audits under `untracked/`, release
36
+ checkouts) are never mistaken for the real package.
37
+ - **Without the inventory**: a filesystem walk that skips `untracked/`, virtualenvs,
38
+ `node_modules`, `site-packages`, build output and `*-backup` / `*-gh-pages` folders, plus the
39
+ local experiment projects (`abstractaudio`, `abstractsound`, `abstractvideo`,
40
+ `abstractcognition`, `abstractgeometry`, `abstractspatial`). Two packages with the same name stop
41
+ the run with both paths listed.
42
+
43
+ The root meta-package's `NPM_RELEASE_VERSIONS` and `CRATE_RELEASE_VERSIONS` pins count as
44
+ dependency edges, so an app or crate release reaches the root's floor review.
45
+
46
+ For each package it reads the version (static, or the setuptools `attr` the pyproject points to),
47
+ the internal dependencies (Python `dependencies` and extras, npm dependency groups, Cargo
48
+ `[dependencies]`), and `git status` for the package directory. Changes inside a nested package's
49
+ directory belong to that package (AbstractUIC's packages, the gateway's `console-tui` crate,
50
+ AbstractNote's `web` app, the sibling repositories under the root).
51
+
52
+ Vite source aliases into the AbstractUIC checkout are not in any manifest. With the inventory they
53
+ come from its `alias` edges (verified by `./scripts/deps.sh check`); without it, from a text scan
54
+ of the package sources for sibling npm package names, which can over-report.
55
+
56
+ ## Output
57
+
58
+ The Markdown is for reading; the JSON is for follow-up checks and release logs.
59
+
60
+ - `ordered_packages`: every package in dependency order (ties broken by the ADR-0034 tier rank).
61
+ - `release_wave`: changed packages (`changed: true`, with the reasons) plus every package
62
+ downstream of one (`floor review only`).
63
+ - `dependency_floor_reviews`: each internal requirement inside the wave, with the declared range
64
+ and the lower package's local version: raise or confirm it after the lower publish is visible.
65
+ - `profile_pin_reviews`: the root pins (`pyproject.toml` exact pins, `RELEASE_VERSIONS`,
66
+ `NPM_RELEASE_VERSIONS`, `CRATE_RELEASE_VERSIONS`) against local versions; `drift` means the root
67
+ profile would not deliver the local version.
68
+ - `changes_outside_packages`: uncommitted changes in a package repository that no package
69
+ directory owns (for example AbstractUIC's root `package.json`, which names its release tag, and
70
+ its lockfile). Assign them to a release by hand.
71
+ - `inventory_gaps`: packages the workspace scripts would miss: `repo_not_in_inventory` (a sibling
72
+ AbstractFramework repository with no row), `package_not_in_inventory` (a public manifest tracked
73
+ in a listed repository, outside tests, fixtures, examples and docs), `not_cloned`,
74
+ `name_mismatch`.
@@ -0,0 +1,131 @@
1
+ # Package Inventory
2
+
3
+ What exists, in which order it releases, and how each package releases. The workspace's
4
+ `scripts/lib/packages.txt` is the machine-readable inventory (`./scripts/deps.sh` prints the tiers,
5
+ `./scripts/deps.sh check` verifies them against the real manifests, `./scripts/deps.sh rdeps <id>`
6
+ lists what must follow a bump). This page adds the release mechanics. Facts were read from the
7
+ repositories and their GitHub settings on 2026-10-27; re-check a row before relying on it for an
8
+ irreversible step.
9
+
10
+ ## Tiers
11
+
12
+ Tier = dependency depth from `packages.txt`. A package releases only after every package it
13
+ depends on is published and visible.
14
+
15
+ | Tier | Python (PyPI) | npm | Rust (crates.io) |
16
+ |---|---|---|---|
17
+ | 0 | abstractskill, abstractsemantics, AbstractMemory, abstractvision, abstractvoice, abstractmusic, abstractcamera | ui-kit, app-server, monitor-flow, monitor-gpu, monitor-memory, monitor-active-memory | abstracttui |
18
+ | 1 | abstract3d (needs abstractvision) | panel-chat (peer of ui-kit) | abstracttui-graph, abstractcore-console, abstractcode (CLI) |
19
+ | 2 | abstractcore (needs voice, vision, music, 3d) | flow, observer, continuum, entity, code (web), note (web) | abstracttui-mermaid, abstractgateway-console |
20
+ | 3 | AbstractRuntime (needs core, memory, semantics) | | |
21
+ | 4 | abstractagent, abstractassistant | | |
22
+ | 5 | abstractgateway | | |
23
+ | 6 | abstractnote, abstractframework (root meta-package) | | |
24
+
25
+ Roles worth knowing when you order a wave:
26
+
27
+ - **AbstractMemory** owns the memory graph (temporal assertions, the graph store and its
28
+ operations). AbstractRuntime, AbstractGateway and AbstractNote build on it, so a memory change
29
+ can ripple to all three.
30
+ - **AbstractCore** depends on the media plugins (voice, vision, music, 3d). Avoid a Core release in
31
+ the middle of a wave unless the change needs it; its floor propagation is the slow path.
32
+ - **AbstractGateway** is the one HTTP door; the apps are thin clients of it.
33
+ - **AbstractNote** is a notes app on the gateway: a Python package (`abstractnote`, depends on
34
+ AbstractMemory, AbstractSemantics, AbstractRuntime and AbstractCore; reaches the gateway through
35
+ its `gateway` extra) plus a web app (`@abstractframework/note`). The gateway imports
36
+ `abstractnote` lazily as an optional seam, so it is not a gateway dependency; AbstractNote
37
+ releases after the gateway it needs.
38
+ - **abstractframework** (root) pins exact versions of the released matrix and releases last.
39
+
40
+ Not released with the framework: the local test projects `abstractaudio`, `abstractsound`,
41
+ `abstractvideo`, `abstractcognition`, `abstractgeometry`, `abstractspatial` (the planner skips
42
+ them).
43
+
44
+ ## Release mechanics per package
45
+
46
+ Trigger: **tag** = push `vX.Y.Z` (`release.yml` on tag push); **dispatch** = `gh workflow run
47
+ release.yml --ref main ...` with the inputs named in the row. Most Python workflows accept both:
48
+ dispatched with `-f version=X.Y.Z`, they build, publish and create the tag themselves (an
49
+ `ensure-tag` job), which also satisfies an environment that admits only `main`. Dispatch inputs
50
+ differ per workflow and gh refuses unknown inputs ("Unexpected inputs"), so read the row, and read
51
+ the publish jobs' `if:` conditions before dispatching a workflow the table does not cover.
52
+ Environment policy = the deployment branch/tag policy of the publishing environment: a tag-push
53
+ release needs a tag rule there.
54
+
55
+ | Dispatch inputs | Packages |
56
+ |---|---|
57
+ | `-f version=X.Y.Z` | abstractvoice, abstractvision, abstractcamera, abstractskill, abstractsemantics, AbstractMemory, abstractcore, abstractagent, abstractassistant, abstractgateway, abstractflow |
58
+ | `-f version=X.Y.Z -f publish=true -f publish_confirmation=publish-<package>-X.Y.Z` | AbstractRuntime, abstractmusic |
59
+ | `-f version=X.Y.Z` (`-f dry_run=true` rehearses) | abstractnote |
60
+ | `-f target=web` or `-f target=cli` (default `all`) | AbstractCode |
61
+ | `-f publish=true` | abstracttui (and its extension crates) |
62
+ | none | abstractuic, abstractobserver, abstractentity, abstractcontinuum, root abstractframework (check the workflow's publish conditions first) |
63
+ | none, and dispatch publishes nothing | abstract3d: publishes only from a `v*` tag |
64
+
65
+ ### Python
66
+
67
+ | Package | Repo | Version source | Trigger | `pypi` env policy | llms generator | Notes |
68
+ |---|---|---|---|---|---|---|
69
+ | abstractvoice | lpalbou/AbstractVoice | `abstractvoice/_version.py` (single source; pyproject reads it) | tag | main, tag `v*.*.*` | none (edit by hand) | PR CI: tests 3.9-3.12, Qwen3-TTS/ASR transformers floor and latest, build, docs (10 checks). release.yml publishes to PyPI with trusted publishing, creates the GitHub release, deploys docs. |
70
+ | abstractvision | lpalbou/AbstractVision | `src/abstractvision/__init__.py` | tag | no restriction | `scripts/generate_llms_full.py` | |
71
+ | abstractmusic | lpalbou/AbstractMusic | `src/abstractmusic/_version.py` | tag or dispatch (`-f publish=true -f publish_confirmation=publish-abstractmusic-X.Y.Z`) | main, tag `v*.*.*` | none | |
72
+ | abstractcamera | lpalbou/AbstractCamera | `src/abstractcamera/__init__.py` | tag | main, tag `v*` | `scripts/generate_llms_full.py` | Ships a package agent skill (`skills/camera-piloting/`). |
73
+ | abstract3d | lpalbou/Abstract3D | `pyproject.toml` and `src/abstract3d/__init__.py` | tag `v*` only (the publish jobs run only on `refs/tags/v*`; a dispatch publishes nothing) | main, tag `v*` | none | AbstractCore depends on it: release before Core. |
74
+ | abstractskill | lpalbou/AbstractSkill | `pyproject.toml` and `src/abstractskill/__init__.py` | tag | main, tag `v*` | `scripts/generate_llms_full.py` | Shelf changes: `scripts/refresh_shelf.py`, bump `catalog.yaml` `version`, update the pins in `tests/test_bundled.py` and `tests/test_shelf.py`. |
75
+ | abstractsemantics | lpalbou/AbstractSemantics | `pyproject.toml` | tag | main, tag `v*.*.*` | `scripts/generate_llms_full.py` | |
76
+ | AbstractMemory | lpalbou/AbstractMemory | `pyproject.toml` | tag | main, tag `v*.*.*` | none | Memory graph owner. |
77
+ | abstractcore | lpalbou/AbstractCore | `abstractcore/utils/version.py` | tag | main, tag `v*.*.*` | `scripts/update_llms.py` | Also publishes the `abstractcore-console` crate and GHCR images. Ships `skills/abstractcore/`. |
78
+ | AbstractRuntime | lpalbou/AbstractRuntime | `pyproject.toml` | dispatch: `gh workflow run release.yml --ref main -f version=X.Y.Z -f publish=true -f publish_confirmation=publish-abstractruntime-X.Y.Z` (the run creates the tag); a tag push also works | main, tag `v*.*.*` (tag rule added 2026-10-27) | `scripts/generate_llms_full.py` (commit the output) | PR CI: 7 checks. |
79
+ | abstractagent | lpalbou/AbstractAgent | `pyproject.toml` | tag | main, tag `v*.*.*` | none | |
80
+ | abstractassistant | lpalbou/AbstractAssistant | `pyproject.toml` and `abstractassistant/_version.py` (a test keeps them equal) | dispatch: `gh workflow run release.yml --ref main -f version=X.Y.Z` (creates the tag) | **main only**: a tag-push run is refused at the publish job; dispatch from main, or ask the operator to add a tag rule | `scripts/update_llms_full.py` | Desktop app plus iPhone (`phone/iphone`, xcodegen, `iphone.yml`) and watch (`watch.yml`) workflows. |
81
+ | abstractgateway | lpalbou/AbstractGateway | `pyproject.toml` and `src/abstractgateway/__init__.py` | tag | main, tag `v*` | `scripts/generate-llms-full.py` | release.yml: tests 3.10-3.13, build, docs, the `abstractgateway-console` crate to crates.io when `console-tui/Cargo.toml` has a new version, GHCR images. See the floor rules below. |
82
+ | abstractnote | lpalbou/AbstractNote | `pyproject.toml`, `src/abstractnote/__init__.py` and `web/package.json` (the release validates the tag against pyproject and web) | tag, or dispatch with `-f version=X.Y.Z` (`-f dry_run=true` rehearses) | no restriction (`npm` env: main, tag `v*`) | `scripts/build_llms_full.py` | One release publishes the Python package and the web app. Needs the gateway release that carries the AbstractNote seam (`abstractgateway>=0.15.11`). |
83
+ | abstractframework | lpalbou/AbstractFramework | `pyproject.toml` and `abstractframework/__init__.py` (`__version__`, `RELEASE_VERSIONS`, `NPM_RELEASE_VERSIONS`, `CRATE_RELEASE_VERSIONS`) | tag | main, tag `v*` | `scripts/gen_llms_full.py` (`--check`) | Last. Also `docs/installers/install-manifest.json`, `scripts/install.sh`, `scripts/install.ps1`, install docs; `scripts/tests/test_inventory.sh` checks they agree. |
84
+
85
+ ### npm
86
+
87
+ | Package | Repo / path | Version source | Trigger | `npm` env policy | Notes |
88
+ |---|---|---|---|---|---|
89
+ | ui-kit, app-server, monitor-flow, monitor-gpu, monitor-memory, monitor-active-memory, panel-chat | lpalbou/AbstractUIC, `<pkg>/package.json` | each package's `package.json`; the root `package.json` version names the release tag; root `package-lock.json` entries must match (`npm install --package-lock-only`) | PR, merge on green (one job "Test, build, and pack"), then tag `vX.Y.Z` = root version | main, tag `v*` | release.yml publishes each changed package with `npm publish --provenance`. Verify with `npm view @abstractframework/ui-kit version`. llms: `scripts/generate-llms-full.py`. |
90
+ | @abstractframework/flow | lpalbou/AbstractFlow | `package.json` | tag | main, tag `v*` | `npm run check:lock` fails until the pinned ui-kit is on npm; after it is, `npm install` and commit the lockfile. |
91
+ | @abstractframework/observer | lpalbou/AbstractObserver | `package.json` | tag | main, tag `v*` | same lockfile rule |
92
+ | @abstractframework/entity | lpalbou/AbstractEntity | `package.json` | tag | no restriction | same lockfile rule |
93
+ | @abstractframework/continuum | lpalbou/AbstractContinuum | `package.json` | tag | no restriction | same lockfile rule |
94
+ | @abstractframework/code | lpalbou/AbstractCode, `web/` (`npm --prefix web`) | `web/package.json` (versioned independently of the crate) | tag `web-vX.Y.Z` (a `vX.Y.Z` tag publishes only the crate), or dispatch `-f target=web` | main, tag `v*`, tag `web-v*` | same lockfile rule; the repository also holds the `abstractcode` crate |
95
+ | @abstractframework/note | lpalbou/AbstractNote, `web/` | `web/package.json` (equal to the Python version) | with abstractnote | main, tag `v*` | |
96
+
97
+ ### Rust
98
+
99
+ | Crate | Repo / path | Trigger | `crates-io` env policy |
100
+ |---|---|---|---|
101
+ | abstracttui | lpalbou/AbstractTUI | tag `v*`, or dispatch `-f publish=true` (without it the run only verifies) | no restriction |
102
+ | abstracttui-graph, abstracttui-mermaid | lpalbou/AbstractTUI, `extensions/graph`, `extensions/mermaid` | with abstracttui: the `publish-family` job publishes graph, then mermaid (mermaid depends on graph) | no restriction |
103
+ | abstractcore-console | lpalbou/AbstractCore, `console-tui/` | with AbstractCore | no restriction |
104
+ | abstractgateway-console | lpalbou/AbstractGateway, `console-tui/` | with AbstractGateway, when `console-tui/Cargo.toml` has a new version | no restriction |
105
+ | abstractcode | lpalbou/AbstractCode, `tui/` (versioned independently of the web app) | tag `vX.Y.Z` only: its `crates-io` environment admits only `v*` tags, so a dispatch with `target=cli` or `all` is refused at `publish-crate` | tag `v*` |
106
+
107
+ Check a policy before a tag push:
108
+
109
+ ```bash
110
+ gh api repos/lpalbou/<Repo>/environments/<pypi|npm|crates-io>/deployment-branch-policies \
111
+ --jq '.branch_policies[]|"\(.type):\(.name)"'
112
+ ```
113
+
114
+ A 404 means the environment has no custom policy (any ref may deploy).
115
+
116
+ ## Cross-package floor rules
117
+
118
+ - **Gateway install profiles.** `abstractgateway/tests/test_gateway_install_profiles.py` pins the
119
+ gateway's dependency floors literally. Update it in the same change as any floor.
120
+ - **Gateway AbstractVoice floor ≤ Core's.** The same test requires the gateway's `abstractvoice`
121
+ floor to be at most AbstractCore's own `abstractvoice` floor, so the gateway never pins a newer
122
+ AbstractVoice than Core declares. Release Core with the new floor first, or document "install
123
+ the latest AbstractVoice" instead of pinning it.
124
+ - **Runtime floor constant.** `abstractgateway.live_deltas.ABSTRACTRUNTIME_FLOOR` must equal the
125
+ gateway's pyproject `abstractruntime` floor (the startup "runtime too old" check reads it).
126
+ - **AbstractNote gateway extra.** `abstractnote[gateway]` requires the first gateway release with
127
+ the AbstractNote seam; raise it when the seam changes.
128
+ - **Root pins.** The root pins exact versions (`==`); every release that should reach
129
+ `pip install abstractframework[...]` needs a root release.
130
+ - **npm apps and AbstractUIC.** Apps pin AbstractUIC packages with a caret range; raise the range
131
+ and refresh the lockfile after the AbstractUIC publish is visible.