abstractskill 0.3.3__tar.gz → 0.3.4__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.
- {abstractskill-0.3.3/src/abstractskill.egg-info → abstractskill-0.3.4}/PKG-INFO +6 -2
- {abstractskill-0.3.3 → abstractskill-0.3.4}/README.md +5 -1
- {abstractskill-0.3.3 → abstractskill-0.3.4}/pyproject.toml +1 -1
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/__init__.py +1 -1
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/catalog.yaml +1 -1
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/abstract-release/SKILL.md +143 -6
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/abstract-release/references/package-inventory.md +12 -3
- abstractskill-0.3.4/src/abstractskill/registry/skills/abstract-release/references/readiness-audit.md +54 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/abstract-release/scripts/abstract_release_plan.py +20 -1
- abstractskill-0.3.4/src/abstractskill/registry/skills/abstractframework-website/SKILL.md +110 -0
- abstractskill-0.3.4/src/abstractskill/registry/skills/abstractframework-website/references/check_site.py +83 -0
- abstractskill-0.3.4/src/abstractskill/registry/skills/abstractframework-website/references/preview_server.py +95 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/validations.yaml +39 -5
- {abstractskill-0.3.3 → abstractskill-0.3.4/src/abstractskill.egg-info}/PKG-INFO +6 -2
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill.egg-info/SOURCES.txt +4 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_bundled.py +4 -4
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_shelf.py +6 -1
- {abstractskill-0.3.3 → abstractskill-0.3.4}/LICENSE +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/setup.cfg +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/bundled.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/catalog.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/demand.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/errors.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/hash.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/loader.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/models.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/parser.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/policy.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/prompt.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/advisories.yaml +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/guidance.yaml +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/licenses/meshvault-live-editing.LICENSE +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/licenses/verification-before-completion.LICENSE +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/abstract-release/agents/openai.yaml +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/abstract-release/references/package-discovery.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/abstract-release/references/release-process.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/abstract-release/scripts/pypi_visibility_gate.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/abstractframework-gateway/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/adr/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/adr/agents/openai.yaml +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/adr/references/adr-template-and-workflow.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/adr/references/default-adr-catalog.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/adr/references/reader-first-adr-style.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/adversarial-iteration/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/agora-collaboration/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/agora-collaboration/references/failure-ledger.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/agora-collaboration/references/mechanics.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/architect/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/architect/agents/openai.yaml +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/architect/references/reviewer-memory.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/backlog/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/backlog/agents/openai.yaml +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/backlog/references/abstractframework-board.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/backlog/references/hub-work-join.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/backlog/references/layout-and-templates.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/backlog/references/maintenance-checklists.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/cicd/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/cicd/agents/openai.yaml +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/cicd/references/docs-and-containers.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/cicd/references/maintenance-playbook.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/cicd/references/package-publishing.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/cicd/references/repository-setup.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/cicd/references/workflow-patterns.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/coredoc/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/coredoc/agents/openai.yaml +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/coredoc/references/agent-skill.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/coredoc/references/core-doc-set.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/coredoc/references/llms-files.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/coredoc/references/maintenance-playbook.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/entity-observation/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/entity-self-knowledge/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/entity-self-knowledge/references/capability_map.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/meshvault-live-editing/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/review/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/review/agents/openai.yaml +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/review/references/reviewer-memory.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/uxreview/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/uxreview/agents/openai.yaml +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/uxreview/references/reviewer-memory.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/verification-before-completion/SKILL.md +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/selection.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/tree.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/trust.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/validation.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill.egg-info/dependency_links.txt +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill.egg-info/requires.txt +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill.egg-info/top_level.txt +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_audience.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_catalog.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_demand.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_loader.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_parser.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_policy.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_refresh_shelf_pins.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_selection.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_tree.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/tests/test_trust.py +0 -0
- {abstractskill-0.3.3 → abstractskill-0.3.4}/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.
|
|
3
|
+
Version: 0.3.4
|
|
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
|
|
@@ -61,12 +61,16 @@ pip install abstractskill
|
|
|
61
61
|
|
|
62
62
|
The wheel carries the library and the curated skill registry (the shelf below).
|
|
63
63
|
|
|
64
|
+
What's new in 0.3.4: the `abstractframework-website` skill joins the shelf and
|
|
65
|
+
`abstract-release` covers AbstractAvatar and the AbstractAssistant lanes; see
|
|
66
|
+
the [changelog](CHANGELOG.md#034---2026-11-02).
|
|
67
|
+
|
|
64
68
|
## The bundled skill registry
|
|
65
69
|
|
|
66
70
|
`pip install abstractskill` installs the reviewed shelf as package data:
|
|
67
71
|
|
|
68
72
|
```
|
|
69
|
-
abstractskill/registry/skills/ #
|
|
73
|
+
abstractskill/registry/skills/ # 16 curated skills (one folder per SKILL.md)
|
|
70
74
|
abstractskill/registry/licenses/ # upstream licenses of catalog-vendored skills
|
|
71
75
|
abstractskill/registry/validations.yaml # trust records: byte pins per skill tree
|
|
72
76
|
abstractskill/registry/advisories.yaml # do-not-use advisories (empty at v1, by design)
|
|
@@ -28,12 +28,16 @@ pip install abstractskill
|
|
|
28
28
|
|
|
29
29
|
The wheel carries the library and the curated skill registry (the shelf below).
|
|
30
30
|
|
|
31
|
+
What's new in 0.3.4: the `abstractframework-website` skill joins the shelf and
|
|
32
|
+
`abstract-release` covers AbstractAvatar and the AbstractAssistant lanes; see
|
|
33
|
+
the [changelog](CHANGELOG.md#034---2026-11-02).
|
|
34
|
+
|
|
31
35
|
## The bundled skill registry
|
|
32
36
|
|
|
33
37
|
`pip install abstractskill` installs the reviewed shelf as package data:
|
|
34
38
|
|
|
35
39
|
```
|
|
36
|
-
abstractskill/registry/skills/ #
|
|
40
|
+
abstractskill/registry/skills/ # 16 curated skills (one folder per SKILL.md)
|
|
37
41
|
abstractskill/registry/licenses/ # upstream licenses of catalog-vendored skills
|
|
38
42
|
abstractskill/registry/validations.yaml # trust records: byte pins per skill tree
|
|
39
43
|
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.
|
|
7
|
+
version = "0.3.4"
|
|
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"
|
|
@@ -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.
|
|
19
|
+
version: "2026.11.02"
|
|
20
20
|
|
|
21
21
|
skills:
|
|
22
22
|
|
|
@@ -5,8 +5,8 @@ description: Plan and run an AbstractFramework release wave across its packages
|
|
|
5
5
|
|
|
6
6
|
# Abstract Release
|
|
7
7
|
|
|
8
|
-
AbstractFramework
|
|
9
|
-
|
|
8
|
+
AbstractFramework contains Python packages on PyPI, npm packages and apps, and Rust crates on
|
|
9
|
+
crates.io; `./scripts/deps.sh` lists the current workspace inventory. A release
|
|
10
10
|
wave publishes the changed ones from the bottom of the dependency graph upward, so every package
|
|
11
11
|
a parent depends on is already published, green, and visible on its registry before the parent
|
|
12
12
|
raises its floor and publishes.
|
|
@@ -16,6 +16,38 @@ tag, publish), `coredoc` (README, docs, llms files, version source), `backlog` (
|
|
|
16
16
|
its evidence) and `adr` (durable rules). This skill adds what only shows up across packages: the
|
|
17
17
|
order, the gates between packages, floor propagation, and the root profile.
|
|
18
18
|
|
|
19
|
+
## Read-only readiness audits
|
|
20
|
+
|
|
21
|
+
When asked whether to release, produce evidence and a recommendation without executing a release.
|
|
22
|
+
The checkout synchronization, checkpoint commits, branch integration and final build rules below
|
|
23
|
+
apply when release execution is authorized; an audit does not authorize pulling, merging, staging
|
|
24
|
+
operator edits, dispatching workflows, rerunning CI, or publishing. Read remote refs and CI through
|
|
25
|
+
read-only GitHub APIs when needed and label cached tracking refs explicitly.
|
|
26
|
+
|
|
27
|
+
Read `references/readiness-audit.md` for the audit evidence contract, registry-only build checks,
|
|
28
|
+
missing-package discovery and the distinction between a release blocker and later roadmap work.
|
|
29
|
+
|
|
30
|
+
## Non-negotiable rules (operator, 2026-10-28; release execution)
|
|
31
|
+
|
|
32
|
+
1. **A release ships EVERY pending change of the work in scope.** Before cutting any package: every
|
|
33
|
+
pending change ON `main` (local unpushed commits, uncommitted edits: an operator's edit is committed
|
|
34
|
+
as `checkpoint` after a secret scan, never left aside) and every branch THE AGENTS CREATED to complete
|
|
35
|
+
a task is merged into an up-to-date `main`, tested and released. NOT every branch: the operator's own
|
|
36
|
+
branches (e.g. a private memory-block branch in AbstractCore) are theirs, are never merged, pushed or
|
|
37
|
+
touched unless the operator says so; when in doubt about a branch's owner, ask. "Held because the operator has edits" or "held because local main has
|
|
38
|
+
unpushed commits" is forbidden: fix the build, merge with origin, release. The only reasons to stop
|
|
39
|
+
are secrets in the tree or a failing test that cannot be fixed without a decision: then ask, with
|
|
40
|
+
the exact file and failure, and keep every other package moving.
|
|
41
|
+
2. **Always pull before starting any work**, in every repository, every time: `git -C <repo> fetch
|
|
42
|
+
origin && git -C <repo> pull --ff-only origin main` before cutting a branch or a worktree; cut
|
|
43
|
+
worktrees from `origin/main`. Pull the local `main` again right after every merge on GitHub.
|
|
44
|
+
3. **A release means every pending change has been merged into an up-to-date `main`.** The wave ends
|
|
45
|
+
only when `./scripts/status.sh` shows every repository on `main`, clean, 0 ahead, 0 behind, and
|
|
46
|
+
`./scripts/build.sh` passes from those checkouts. A checkout left on a feature branch, a merged PR
|
|
47
|
+
not pulled, or a repo "N ahead" is a release defect, reported as such, not as a note.
|
|
48
|
+
4. A worker that cannot run `git merge` or `git rebase` or `git switch` asks the coordinator to do it
|
|
49
|
+
immediately; it never leaves the branch unmerged and moves on.
|
|
50
|
+
|
|
19
51
|
## Before you start
|
|
20
52
|
|
|
21
53
|
- Default to a read-only plan. Commits, pushes, tags, workflow dispatches, publishes, CI reruns and
|
|
@@ -31,6 +63,8 @@ python3 "$SKILL_DIR/scripts/abstract_release_plan.py" "$AF_ROOT" --registry
|
|
|
31
63
|
python3 "$SKILL_DIR/scripts/abstract_release_plan.py" "$AF_ROOT" --registry --json -o "$AF_ROOT/untracked/release-plan.json"
|
|
32
64
|
```
|
|
33
65
|
|
|
66
|
+
Two packages may share a registry name across registries (AbstractAvatar's crate and Python
|
|
67
|
+
package): the planner keys the crate as `<name>-crate`; a crate dependent's edge resolves to it.
|
|
34
68
|
Without a path, the planner finds the workspace by walking up from the current directory
|
|
35
69
|
(or reads `ABSTRACTFRAMEWORK_ROOT`). A package is in the wave when it has uncommitted changes,
|
|
36
70
|
commits since its last release tag, a version with no tag, or (with `--registry`) a version not
|
|
@@ -47,8 +81,11 @@ python3 "$SKILL_DIR/scripts/abstract_release_plan.py" "$AF_ROOT" --registry --js
|
|
|
47
81
|
Release by published dependency floors, not by what happens to pass locally:
|
|
48
82
|
|
|
49
83
|
1. Independent lower packages: `abstractvoice`, `abstractvision`, `abstractmusic` (and the other
|
|
50
|
-
tier-0 media plugins), `abstractskill`,
|
|
51
|
-
|
|
84
|
+
tier-0 media plugins), `abstractskill`, `abstractavatar` (one repository, TWO packages: the
|
|
85
|
+
crate `abstractavatar` on crates.io and the Python package `abstractavatar` on PyPI; the crate
|
|
86
|
+
first: `abstracttui`'s `avatar` feature depends on it, and `abstractcore-console`,
|
|
87
|
+
`abstractgateway-console` and `abstractcode` depend on `abstracttui` with that feature), and
|
|
88
|
+
the AbstractUIC npm packages (`ui-kit`, `app-server`, `monitor-*`, `panel-chat`).
|
|
52
89
|
2. `abstractsemantics` and `abstractmemory` (AbstractMemory owns the memory graph).
|
|
53
90
|
3. `abstractcore`.
|
|
54
91
|
4. `abstractruntime`.
|
|
@@ -56,8 +93,20 @@ Release by published dependency floors, not by what happens to pass locally:
|
|
|
56
93
|
6. `abstractgateway`.
|
|
57
94
|
7. Apps on the gateway: `abstractassistant`, `abstractcode`, `abstractobserver`, `abstractentity`,
|
|
58
95
|
`abstractflow`, `abstractcontinuum`, `abstractnote` (Python on the gateway and AbstractMemory,
|
|
59
|
-
plus its web app).
|
|
60
|
-
|
|
96
|
+
plus its web app). AbstractAssistant is one repository with FOUR lanes: the Python package
|
|
97
|
+
(PyPI, the desktop palette and the gateway seam), the web app (`web/`, `@abstractframework/assistant`,
|
|
98
|
+
served by the gateway; not on npm yet), the iPhone app (`phone/iphone`, App Store / TestFlight
|
|
99
|
+
through `scripts/release.py` and `scripts/upload-candidate.sh`, `iphone.yml`) and the watch app
|
|
100
|
+
(`watch/apple`, `watch.yml`, `scripts/testflight.sh`). The registry wave releases the Python
|
|
101
|
+
package; the Apple lanes release through App Store Connect with the operator's approval
|
|
102
|
+
(`app-store` environment) and are reported as their own rows, never folded into the PyPI row.
|
|
103
|
+
8. Root `abstractframework`: pins, `RELEASE_VERSIONS`, `NPM_RELEASE_VERSIONS`,
|
|
104
|
+
`CRATE_RELEASE_VERSIONS` (includes `abstractavatar` and `abstracttui`), install manifest,
|
|
105
|
+
installers, install docs.
|
|
106
|
+
9. The website, last and gated: once the root profile is on PyPI, run the `abstractframework-website`
|
|
107
|
+
skill — it updates the site branch locally (versions, install commands, new apps and
|
|
108
|
+
capabilities, refreshed screenshots and llms mirrors), serves it locally and hands the operator
|
|
109
|
+
the preview URL. The operator validates and pushes `gh-pages`; a wave never pushes the site.
|
|
61
110
|
|
|
62
111
|
The planner refines this from the real manifests: it skips packages with nothing to release and
|
|
63
112
|
adds every package downstream of a changed package for a floor review. `scripts/lib/packages.txt`
|
|
@@ -207,3 +256,91 @@ to release):
|
|
|
207
256
|
- `references/package-inventory.md`: the tiers, and per package its version source, release
|
|
208
257
|
trigger, registry environment, llms generator, and package-specific rules.
|
|
209
258
|
- `references/package-discovery.md`: how the planner discovers packages and reads its output.
|
|
259
|
+
|
|
260
|
+
## Keep every checkout in step with GitHub (repo sync rule)
|
|
261
|
+
|
|
262
|
+
Observed 2026-10-27: several local `main` checkouts were dozens of commits behind their remotes
|
|
263
|
+
(abstractuic 86, the root 10) because PRs were merged on GitHub while nobody pulled the local
|
|
264
|
+
checkout, and new branches were then cut from the stale main. Rules, every time:
|
|
265
|
+
|
|
266
|
+
1. Before cutting a branch or a worktree: `git -C <repo> fetch origin && git -C <repo> pull --ff-only origin main`
|
|
267
|
+
on the main checkout (a dirty checkout is left alone and reported; never stash someone else's work).
|
|
268
|
+
2. After merging a PR on GitHub: pull the local main checkout immediately (the merge watcher does it).
|
|
269
|
+
3. Worktrees are cut from `origin/main`, never from the local `main` ref.
|
|
270
|
+
4. A sweep before any release wave: for each repo, `rev-list --count main..origin/main` must be 0;
|
|
271
|
+
`scripts/status.sh` at the root prints ahead/behind per repo.
|
|
272
|
+
5. A root `main` that diverged (local release commits made elsewhere) is merged, never rebased: the
|
|
273
|
+
operator's commits keep their hashes; origin's pins and version win in conflicts, local docs and backlog
|
|
274
|
+
additions are kept, duplicated release sections are dropped.
|
|
275
|
+
|
|
276
|
+
## Final gate: the local source build of the whole stack
|
|
277
|
+
|
|
278
|
+
After the root pins are released, run the operator's own developer path before the final report:
|
|
279
|
+
`./scripts/status.sh` (every repo on `main`, 0 behind, no checkout left on a feature branch by a worker)
|
|
280
|
+
and `./scripts/build.sh` (editable Python installs, every npm package built from local packs, every Rust
|
|
281
|
+
crate compiled tier by tier). A failure there is a release defect even when every registry install passes:
|
|
282
|
+
a crate that does not compile from a clean checkout, a pin that does not resolve locally, a checkout left
|
|
283
|
+
behind. Operator-modified files are reported, never built around: say which file fails and whose edit it is.
|
|
284
|
+
|
|
285
|
+
## Final report: the summary table, then "show me your work"
|
|
286
|
+
|
|
287
|
+
The per-package summary table (package | released | new capabilities | remaining work) is the right
|
|
288
|
+
visibility level and stays. It is NOT the report. For every track of the wave add a "show me your work"
|
|
289
|
+
section with exactly three parts, written for the operator who was not watching:
|
|
290
|
+
|
|
291
|
+
- **(a) What was tested:** the suites and counts per package, the end-to-end runs on real weights or a
|
|
292
|
+
real gateway (what scenario, which model, which data), the mutation checks (which rule was removed and
|
|
293
|
+
which test went red), the adversarial review rounds and verdicts, the conformance fixtures (how many,
|
|
294
|
+
real vs synthetic).
|
|
295
|
+
- **(b) What it enables or fixes:** in the operator's words: the user-visible behaviour before and after,
|
|
296
|
+
and which apps/clients actually consume it today versus which still have to migrate (name each client
|
|
297
|
+
and its state: migrated / designed-for / untouched). Never present a served capability as integrated
|
|
298
|
+
when no client reads it.
|
|
299
|
+
- **(c) Proofs:** numbers a human can read: latency and memory before/after, sizes, counts, run ids,
|
|
300
|
+
PR links, registry versions, and one concrete example (a ledger, a run, a voice) walked end to end.
|
|
301
|
+
|
|
302
|
+
A track whose clients are not migrated is reported as "foundation released, integration pending" with the
|
|
303
|
+
migration list and an ETA, never folded into "done".
|
|
304
|
+
|
|
305
|
+
## Think like an architect before closing anything (operator, 2026-10-28)
|
|
306
|
+
|
|
307
|
+
Before a package is held, a track is called done, or a wave is closed, the coordinator (or its adversarial
|
|
308
|
+
reviewer) answers these questions in writing:
|
|
309
|
+
|
|
310
|
+
- What happens if I do not release all the pending changes I have been working on? What breaks for the
|
|
311
|
+
person who installs or builds from source tomorrow?
|
|
312
|
+
- What happens if I do not release this package just yet? Which consumer is left on a stale floor?
|
|
313
|
+
- Did I fully implement AND reuse the functionality I just created in the consumers of that code?
|
|
314
|
+
(A shared component in abstractuic or a gateway contract exists only when the apps consume it:
|
|
315
|
+
AbstractCode, AbstractAssistant, AbstractObserver, AbstractContinuum, AbstractFlow, AbstractNote,
|
|
316
|
+
the consoles.) List each consumer with migrated / pending.
|
|
317
|
+
- Is the result production-grade for a person, not only green for CI?
|
|
318
|
+
|
|
319
|
+
The goal is always a finished, production-grade solution that benefits from the change; the secondary goal
|
|
320
|
+
is the supervisor's visibility: a roadmap while work is ongoing, and at the end a report that shows the
|
|
321
|
+
work (what is new or fixed, what it enables now or later, why it is good). Keep it a dialogue: ask early
|
|
322
|
+
when a decision is genuinely the operator's, decide and say so when it is not.
|
|
323
|
+
|
|
324
|
+
## Backlog discipline for work left pending
|
|
325
|
+
|
|
326
|
+
When a task cannot be carried on now (time, credits, a blocker, a decision), write the backlog item
|
|
327
|
+
immediately, while the understanding is fresh: `proposed` when the need is likely, `planned` when it is
|
|
328
|
+
certain; it carries the analysis, the chosen route, the evidence so far and the open decision.
|
|
329
|
+
When an item is picked up later, start with an adversarial review of the item itself: is its knowledge
|
|
330
|
+
still current, is it still the best route (new research, superseded component, changed contract)?
|
|
331
|
+
|
|
332
|
+
## Changelog fragments (gateway, core, runtime; since 2026-10-29)
|
|
333
|
+
|
|
334
|
+
These repos no longer edit `CHANGELOG.md [Unreleased]` per PR. Each PR adds `changelog.d/<pr-or-slug>.md`; CI fails a PR that touches source without a fragment. At release time, before the version bump commit:
|
|
335
|
+
|
|
336
|
+
```
|
|
337
|
+
python scripts/changelog.py check # every fragment well-formed
|
|
338
|
+
python scripts/changelog.py preview # what the section will say
|
|
339
|
+
python scripts/changelog.py assemble X.Y.Z # writes the [X.Y.Z] section, deletes the fragments
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Commit the assembled section with the version bump. Never hand-edit `[Unreleased]` in these repos.
|
|
343
|
+
|
|
344
|
+
## A conflicting PR gets no CI run
|
|
345
|
+
|
|
346
|
+
GitHub creates `pull_request` runs from the merge ref; a PR whose `mergeStateStatus` is DIRTY has none, so pushes to it create no run and no error. Before pushing a fix: merge `origin/main` into the branch, then `gh pr view N --json mergeStateStatus` must say CLEAN/BLOCKED, never DIRTY.
|
|
@@ -4,7 +4,7 @@ What exists, in which order it releases, and how each package releases. The work
|
|
|
4
4
|
`scripts/lib/packages.txt` is the machine-readable inventory (`./scripts/deps.sh` prints the tiers,
|
|
5
5
|
`./scripts/deps.sh check` verifies them against the real manifests, `./scripts/deps.sh rdeps <id>`
|
|
6
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
|
|
7
|
+
repositories and their GitHub settings on 2026-10-27 (AbstractAvatar and AbstractAssistant lanes: 2026-11-02); re-check a row before relying on it for an
|
|
8
8
|
irreversible step.
|
|
9
9
|
|
|
10
10
|
## Tiers
|
|
@@ -14,8 +14,8 @@ depends on is published and visible.
|
|
|
14
14
|
|
|
15
15
|
| Tier | Python (PyPI) | npm | Rust (crates.io) |
|
|
16
16
|
|---|---|---|---|
|
|
17
|
-
| 0 | abstractskill, abstractsemantics, AbstractMemory, abstractvision, abstractvoice, abstractmusic, abstractcamera | ui-kit, app-server, monitor-flow, monitor-gpu, monitor-memory, monitor-active-memory |
|
|
18
|
-
| 1 | abstract3d (needs abstractvision) | panel-chat (peer of ui-kit) | abstracttui-graph, abstractcore-console, abstractcode (CLI) |
|
|
17
|
+
| 0 | abstractskill, abstractsemantics, AbstractMemory, abstractvision, abstractvoice, abstractmusic, abstractcamera, abstractavatar (Python) | ui-kit, app-server, monitor-flow, monitor-gpu, monitor-memory, monitor-active-memory | abstractavatar (crate) |
|
|
18
|
+
| 1 | abstract3d (needs abstractvision) | panel-chat (peer of ui-kit) | abstracttui (its `avatar` feature needs the abstractavatar crate), abstracttui-graph, abstractcore-console, abstractcode (CLI) |
|
|
19
19
|
| 2 | abstractcore (needs voice, vision, music, 3d) | flow, observer, continuum, entity, code (web), note (web) | abstracttui-mermaid, abstractgateway-console |
|
|
20
20
|
| 3 | AbstractRuntime (needs core, memory, semantics) | | |
|
|
21
21
|
| 4 | abstractagent, abstractassistant | | |
|
|
@@ -35,6 +35,13 @@ Roles worth knowing when you order a wave:
|
|
|
35
35
|
its `gateway` extra) plus a web app (`@abstractframework/note`). The gateway imports
|
|
36
36
|
`abstractnote` lazily as an optional seam, so it is not a gateway dependency; AbstractNote
|
|
37
37
|
releases after the gateway it needs.
|
|
38
|
+
- **AbstractAvatar** is one repository with two packages that must stay at one version: the
|
|
39
|
+
crate (procedural avatars, the Wasm artifact) and the Python package over it. The crate releases
|
|
40
|
+
first (AbstractTUI's `avatar` feature, hence every console crate, resolves it from crates.io);
|
|
41
|
+
the Python package follows through its `release.yml`.
|
|
42
|
+
- **AbstractAssistant** is one repository with four lanes: the Python package (PyPI), the web app
|
|
43
|
+
(`web/`, served by the gateway), the iPhone app and the watch app (App Store Connect through the
|
|
44
|
+
`app-store` environment, operator approval). Only the Python package is a registry release.
|
|
38
45
|
- **abstractframework** (root) pins exact versions of the released matrix and releases last.
|
|
39
46
|
|
|
40
47
|
Not released with the framework: the local test projects `abstractaudio`, `abstractsound`,
|
|
@@ -67,6 +74,7 @@ release needs a tag rule there.
|
|
|
67
74
|
| Package | Repo | Version source | Trigger | `pypi` env policy | llms generator | Notes |
|
|
68
75
|
|---|---|---|---|---|---|---|
|
|
69
76
|
| 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. |
|
|
77
|
+
| abstractavatar (Python) | lpalbou/AbstractAvatar | `pyproject.toml` (= `Cargo.toml` version) | tag `v*` or dispatch `-f version=X.Y.Z -f publish_confirmation=…` (read `release.yml`: created 2026-11-02) | `pypi` env, trusted publisher registered by the operator 2026-11-02 (project `abstractavatar`, workflow `release.yml`, environment `pypi`) | `scripts/docs.py` | Builds the native wheel matrix + sdist; the crate is NOT published by this workflow. |
|
|
70
78
|
| abstractvision | lpalbou/AbstractVision | `src/abstractvision/__init__.py` | tag | no restriction | `scripts/generate_llms_full.py` | |
|
|
71
79
|
| 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
80
|
| abstractcamera | lpalbou/AbstractCamera | `src/abstractcamera/__init__.py` | tag | main, tag `v*` | `scripts/generate_llms_full.py` | Ships a package agent skill (`skills/camera-piloting/`). |
|
|
@@ -98,6 +106,7 @@ release needs a tag rule there.
|
|
|
98
106
|
|
|
99
107
|
| Crate | Repo / path | Trigger | `crates-io` env policy |
|
|
100
108
|
|---|---|---|---|
|
|
109
|
+
| abstractavatar | lpalbou/AbstractAvatar, `.` | local `cargo publish` from the tagged commit (no crates.io workflow; `~/.cargo/credentials.toml` on the operator's machine); tag `v*` | none | First published 0.1.0 on 2026-11-02; the `avatar` feature of abstracttui resolves it from crates.io, never from a path. |
|
|
101
110
|
| abstracttui | lpalbou/AbstractTUI | tag `v*`, or dispatch `-f publish=true` (without it the run only verifies) | no restriction |
|
|
102
111
|
| 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
112
|
| abstractcore-console | lpalbou/AbstractCore, `console-tui/` | with AbstractCore | no restriction |
|
abstractskill-0.3.4/src/abstractskill/registry/skills/abstract-release/references/readiness-audit.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Release readiness audit
|
|
2
|
+
|
|
3
|
+
An audit answers what is published, what changed, what must ship together, and what evidence is
|
|
4
|
+
still missing. It does not execute the wave. Preserve existing operator rules when refreshing
|
|
5
|
+
this skill from AbstractSkill: compare all files first, because the registry copy may be older
|
|
6
|
+
than the installed skill.
|
|
7
|
+
|
|
8
|
+
## Evidence to collect
|
|
9
|
+
|
|
10
|
+
- Record the observation time, local HEAD, branch and dirty state for every inventoried repo.
|
|
11
|
+
Query live remote-main SHAs when available; cached `origin/main` alone cannot prove current
|
|
12
|
+
ahead/behind. Do not pull or merge during the audit.
|
|
13
|
+
- Run the planner with registry checks. Compare published versions, matching release tags and
|
|
14
|
+
the source changes beyond those tags. A published local version with newer source requires a
|
|
15
|
+
fresh version; publication of the old version is not proof that HEAD shipped.
|
|
16
|
+
- Review open release-scope agent PRs as well as main. A clean checkout can still omit delivered
|
|
17
|
+
work on a branch. Protect operator branches and do not infer ownership from branch names alone.
|
|
18
|
+
- Check CI for the proposed commit, not merely the latest successful run. Keep failed jobs,
|
|
19
|
+
pending checks, environment failures and missing checks distinct. Inspect failed-job evidence
|
|
20
|
+
before classifying a failure or recommending a rerun.
|
|
21
|
+
- Check root pins, installer matrix and per-package dependency floors. Internal consistency of
|
|
22
|
+
the old root matrix does not show that it delivers the new capabilities.
|
|
23
|
+
- Reconcile backlog claims against code, completed records, registry data and CI. Count lifecycle
|
|
24
|
+
files separately from unique tickets; planned/completed duplicates and old overview text are
|
|
25
|
+
not reliable estimates of remaining work.
|
|
26
|
+
|
|
27
|
+
## Check the artifacts users install
|
|
28
|
+
|
|
29
|
+
Local packs, editable siblings and path dependencies can hide missing published APIs. For a
|
|
30
|
+
consumer using new shared UI exports, perform a clean source build in a temporary directory with
|
|
31
|
+
dependencies resolved from the registry. A version-only lockfile check can pass while the build
|
|
32
|
+
fails because a locally packed dependency reused an already-published version number.
|
|
33
|
+
|
|
34
|
+
Inspect planner `inventory_gaps` even when `deps.sh check` succeeds. A newly added public crate
|
|
35
|
+
can be absent from the inventory and release workflow. Cargo `path` plus `version` dependencies
|
|
36
|
+
must resolve from crates.io when packaged: release and verify the new lower crate before the
|
|
37
|
+
dependent package's `cargo publish --dry-run` verification job. Check its trusted publisher and
|
|
38
|
+
the workflow graph; adding a late publish job after verification does not solve this dependency.
|
|
39
|
+
|
|
40
|
+
Run applicable changelog fragment validation as a read-only check. Do not assemble fragments or
|
|
41
|
+
bump versions during an audit. A malformed fragment can block release preparation even when a
|
|
42
|
+
previous remote commit passed CI.
|
|
43
|
+
|
|
44
|
+
## Verdict and sequencing
|
|
45
|
+
|
|
46
|
+
Separate observed defects, missing required proof and later product work. A partial consumer
|
|
47
|
+
migration is a foundation delivered with integration pending, not a complete feature. Security
|
|
48
|
+
guards, registry-resolvable dependencies, required concurrency/isolation evidence and exact-commit
|
|
49
|
+
CI are release gates when applicable; unrelated proposals do not all become blockers.
|
|
50
|
+
|
|
51
|
+
Return a per-package release/skip/floor-review decision, proposed fresh versions (subject to a
|
|
52
|
+
new registry check), dependency order, and exit criteria. Give effort ranges as estimates with
|
|
53
|
+
assumptions, never promise a date without evidence. Preserve recorded release-scope obligations;
|
|
54
|
+
do not silently defer already-delivered main changes to manufacture a smaller green wave.
|
|
@@ -608,7 +608,12 @@ def collect_requirements(
|
|
|
608
608
|
for group, raw in raw_groups:
|
|
609
609
|
req = parse_requirement(raw, group, known)
|
|
610
610
|
# A crate only depends on crates; a Python/npm name that compacts to a
|
|
611
|
-
# crate name (or the reverse) is a different package.
|
|
611
|
+
# crate name (or the reverse) is a different package. A name shared by a
|
|
612
|
+
# crate and a Python package resolves to the crate for a crate dependent.
|
|
613
|
+
if req and pkg.ecosystem == "crates" and by_key_ecosystem(packages, req.target) != "crates":
|
|
614
|
+
alt = known.get(req.target + "-crate")
|
|
615
|
+
if alt is not None:
|
|
616
|
+
req.target = alt
|
|
612
617
|
if req and (pkg.ecosystem == "crates") != (by_key_ecosystem(packages, req.target) == "crates"):
|
|
613
618
|
continue
|
|
614
619
|
add_internal_requirement(pkg, req)
|
|
@@ -623,6 +628,8 @@ def collect_requirements(
|
|
|
623
628
|
by_key = {p.key: p for p in packages}
|
|
624
629
|
for var in ("NPM_RELEASE_VERSIONS", "CRATE_RELEASE_VERSIONS"):
|
|
625
630
|
for key, version in parse_version_dict(init_path, var).items():
|
|
631
|
+
if var == "CRATE_RELEASE_VERSIONS" and key + "-crate" in by_key:
|
|
632
|
+
key = key + "-crate"
|
|
626
633
|
if key in by_key:
|
|
627
634
|
add_internal_requirement(
|
|
628
635
|
framework, InternalRequirement(key, f"{by_key[key].name}=={version}", var, "==", version)
|
|
@@ -778,6 +785,18 @@ def discover(root: Path) -> Tuple[List[Package], List[Dict[str, Any]], str]:
|
|
|
778
785
|
keys: Dict[str, Package] = {}
|
|
779
786
|
for pkg in packages:
|
|
780
787
|
if pkg.key in keys:
|
|
788
|
+
# One repository can publish a crate AND a Python package under the same
|
|
789
|
+
# name (AbstractAvatar: crates.io `abstractavatar` + PyPI `abstractavatar`).
|
|
790
|
+
# They are different packages on different registries: the crate keys as
|
|
791
|
+
# `<name>-crate` so requirements and pins can tell them apart.
|
|
792
|
+
other = keys[pkg.key]
|
|
793
|
+
crate = pkg if pkg.ecosystem == "crates" else other if other.ecosystem == "crates" else None
|
|
794
|
+
if crate is not None and {pkg.ecosystem, other.ecosystem} != {"crates"}:
|
|
795
|
+
keys.pop(crate.key, None)
|
|
796
|
+
crate.key = crate.key + "-crate"
|
|
797
|
+
for remaining in (pkg, other):
|
|
798
|
+
keys.setdefault(remaining.key, remaining)
|
|
799
|
+
continue
|
|
781
800
|
raise PlanError(f"duplicate package {pkg.name}: {keys[pkg.key].path} and {pkg.path}")
|
|
782
801
|
keys[pkg.key] = pkg
|
|
783
802
|
collect_git_status(packages)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: abstractframework-website
|
|
3
|
+
description: Update the abstractframework.ai website after a release wave so it describes the framework that is actually published (versions, install commands, every app and capability, refreshed screenshots and llms mirrors), verify every claim against code and registries, serve the result locally and hand the operator a preview URL. The site is GATED - this skill never pushes gh-pages; the operator validates the preview and publishes. Use at the end of every abstract-release wave, when the operator asks whether the site is current, or when a page describes a package that moved.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AbstractFramework website update (gated)
|
|
7
|
+
|
|
8
|
+
The site at https://abstractframework.ai is the `gh-pages` branch of lpalbou/AbstractFramework:
|
|
9
|
+
static HTML (`index.html`, one page per package and per persona, `llms*.txt` mirrors, screenshots
|
|
10
|
+
under `assets/`). Its job is to describe the framework a person can install TODAY. After every
|
|
11
|
+
release wave it must say the released versions, the install commands that resolve, every app that
|
|
12
|
+
exists (desktop, web, iPhone, watch, consoles), every capability (text, voice, vision, music, 3D,
|
|
13
|
+
camera, memory, decisions, entities, automations) and what changed, in the operator's voice.
|
|
14
|
+
|
|
15
|
+
**The gate.** This skill ends with a local preview URL and a branch, never with a push. The
|
|
16
|
+
operator reads the preview, asks for changes, and pushes `gh-pages` personally. A worker that
|
|
17
|
+
pushes, force-pushes, or rebases `gh-pages` has broken the operator's one rule for this surface.
|
|
18
|
+
|
|
19
|
+
## Paths
|
|
20
|
+
|
|
21
|
+
- Site worktree: `/Users/albou/tmp/abstractframework-ghpages` (a git worktree of the root repo on
|
|
22
|
+
a site branch). Published ref: `origin/gh-pages`. Start every update from it:
|
|
23
|
+
`git -C <worktree> fetch origin && git -C <worktree> switch -c site-<root version> origin/gh-pages`
|
|
24
|
+
(one branch per root version; an existing branch for the same version is resumed, never recreated).
|
|
25
|
+
- Method and history: `/Users/albou/tmp/abstractframework/untracked/site-rethink/` (PLAN.md,
|
|
26
|
+
REPORT.md with the operator's rounds, CLAIMS.md, examples/, deliver/, shots/). Read REPORT.md's
|
|
27
|
+
operator rounds before changing copy: they are the record of what was accepted and refused.
|
|
28
|
+
- Preview server: `python3 references/preview_server.py <worktree> --port 56265` (Range-capable,
|
|
29
|
+
needed for the videos). The URL to hand over is `http://127.0.0.1:56265/`.
|
|
30
|
+
- Workspace: `/Users/albou/tmp/abstractframework/<repo>` (each its own git repo; `git -C`).
|
|
31
|
+
|
|
32
|
+
## Invariants (operator decisions; keep them unless the operator changes them on the record)
|
|
33
|
+
|
|
34
|
+
- Identity: the original dark site; content changes, identity does not. Tagline
|
|
35
|
+
"Write once. Generate everything. Run anywhere." Modality order voice, music, vision, 3D, camera.
|
|
36
|
+
- Install: exactly three profiles, `abstractframework`, `abstractframework[apple]`,
|
|
37
|
+
`abstractframework[gpu]`, plus the short installer addresses (`abstractframework.ai/install.sh`,
|
|
38
|
+
`/install.ps1`, `/uninstall.sh`). Never `[remote]`, `[mlx]` or a per-package pip line as the
|
|
39
|
+
primary path. Provider badges list every provider the text names, never trimmed.
|
|
40
|
+
- Names: PascalCase package names in prose (AbstractCore, AbstractAssistant); "Consoles" is not
|
|
41
|
+
a package; the Assistant is "One Click Away", never "Built for macOS" (OS-agnostic, tested most on
|
|
42
|
+
Apple). Entities are "persistent, self-evolving agents ... we are defining the field here", the
|
|
43
|
+
identity planted once; memory is reconstruction (passive / active / durable).
|
|
44
|
+
- The "Ledger Is the Record of the Run" animation stays as it is.
|
|
45
|
+
- Every code block is either RUN (a hermetic example under `untracked/site-rethink/examples/`,
|
|
46
|
+
its `run.log` next to it, the HTML comment `E<n> PASS`) or carries a visible "not executed" note.
|
|
47
|
+
No worker runs model generation for the site beyond what an example needs; one model process at
|
|
48
|
+
a time on the machine (the live gateway owns the GPU).
|
|
49
|
+
- Screenshots come from a fresh scratch install of the RELEASED matrix (never from a dev tree),
|
|
50
|
+
captured at the sizes the page uses, including a 400 px phone capture for every new page or
|
|
51
|
+
redesigned interface. A pre-release capture is captioned as such.
|
|
52
|
+
- Claims are text-only when the code says so: the adversary of 2026-09-29 found the operator's own
|
|
53
|
+
framings false in code (no hash-chained gateway ledgers, no re-execution on replay, `create_llm`
|
|
54
|
+
needs a provider). Verify before writing, write what the code does.
|
|
55
|
+
|
|
56
|
+
## Procedure
|
|
57
|
+
|
|
58
|
+
1. **Inventory what is published.** `python3 ~/.codex/skills/abstract-release/scripts/abstract_release_plan.py <workspace> --registry`
|
|
59
|
+
plus the root's `abstractframework/__init__.py` (`RELEASE_VERSIONS`, `NPM_RELEASE_VERSIONS`,
|
|
60
|
+
`CRATE_RELEASE_VERSIONS`) and `pip download abstractframework==<v> --no-deps` for the pins.
|
|
61
|
+
The site states the ROOT version and the versions the root pins; nothing "coming".
|
|
62
|
+
2. **Diff the site against reality.** For every page: the versions it names, the install lines,
|
|
63
|
+
the package list, the apps and capabilities it describes, the screenshots' provenance, the
|
|
64
|
+
llms mirrors' headers. `grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+" *.html | sort | uniq -c` finds stale
|
|
65
|
+
numbers fast. Read each released package's CHANGELOG from the version the site names to the
|
|
66
|
+
released one: that is the list of new features and fixes to tell.
|
|
67
|
+
3. **Write the update ledger first** (`untracked/site-<root version>/CLAIMS.md`, same shape as the
|
|
68
|
+
2026-09-29 ledger): every factual claim to add or change, with the repository line, registry
|
|
69
|
+
JSON, or example run that supports it; every page to touch; every screenshot to refresh and
|
|
70
|
+
from which scratch install. New apps get their own section or page (the Assistant's web, iPhone
|
|
71
|
+
and watch apps; a new console); a new capability gets its place in the home grid and on the
|
|
72
|
+
package page that provides it (decision models on core.html, with the model family named as the
|
|
73
|
+
package docs name it).
|
|
74
|
+
4. **Apply the changes** on the site branch, in commits named `site <root version>: <what>`.
|
|
75
|
+
Refresh `llms.txt` / `llms-full.txt` mirrors from each released repository's main at the tag
|
|
76
|
+
(headers kept). Regenerate `sitemap.xml` when pages are added.
|
|
77
|
+
5. **Check.** `python3 references/check_site.py <worktree>`: every local link and asset resolves,
|
|
78
|
+
every page has one `<title>`, no leftover `TODO`/`PENDING` markers, every `<img>` exists and has
|
|
79
|
+
`width`/`height`, no version string older than the root's pins unless the ledger explains it, no
|
|
80
|
+
"coming soon". Open every changed page in the preview at desktop width and 400 px and look at it;
|
|
81
|
+
record a screenshot of each under `untracked/site-<root version>/shots/`.
|
|
82
|
+
6. **Adversarial pass.** A reader that did not write the pages checks the ledger line by line
|
|
83
|
+
against the code and the registries, and the copy against the invariants above; fix or
|
|
84
|
+
withdraw every finding on the record (`REVIEW-<n>.md`).
|
|
85
|
+
7. **Serve and hand over.** Start the preview server on the worktree, confirm it answers, and
|
|
86
|
+
end with the handover block below. Do not push. Do not merge into `gh-pages`. Leave the
|
|
87
|
+
worktree on the site branch so the operator's rounds continue there.
|
|
88
|
+
|
|
89
|
+
## Handover block (the last thing a run prints)
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
Site branch: site-<root version> @ <sha> (worktree /Users/albou/tmp/abstractframework-ghpages)
|
|
93
|
+
Preview: http://127.0.0.1:56265/ (server pid <pid>; restart: python3 ~/.codex/skills/abstractframework-website/references/preview_server.py <worktree> --port 56265)
|
|
94
|
+
Changed pages: <list> New pages: <list> Screenshots refreshed: <n> (from abstractframework==<v> scratch install)
|
|
95
|
+
Ledger: untracked/site-<root version>/CLAIMS.md Review: REVIEW-1.md (<n> findings, <m> fixed)
|
|
96
|
+
Not done / needs you: <anything the operator must decide or capture>
|
|
97
|
+
To publish (operator only): git -C <worktree> push origin site-<root version>:gh-pages
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Pitfalls
|
|
101
|
+
|
|
102
|
+
- A site built from the dev checkouts drifts from what `pip install` gives: scratch-install the
|
|
103
|
+
released root profile for screenshots and example runs (`uv venv` + `uv pip install
|
|
104
|
+
abstractframework[apple]==<v>` with `UV_CACHE_DIR=/Users/albou/.cache/uv`; delete the venv after).
|
|
105
|
+
- The home page is one 180 KB file with inline sections per package: edit the section, not the
|
|
106
|
+
whole file; keep `assets/` names stable so the operator's cached screenshots stay valid.
|
|
107
|
+
- `llms-full.txt` mirrors are large; refresh them from the released tag, not from a working tree
|
|
108
|
+
that carries unreleased docs.
|
|
109
|
+
- A page for an app that exists on one platform only says so plainly (the watch app is watchOS,
|
|
110
|
+
the iPhone app iOS, the web app runs where the gateway runs).
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Static checks for the abstractframework.ai site worktree. Read-only.
|
|
3
|
+
|
|
4
|
+
Usage: check_site.py <site dir> [--min-version-for <package>=<x.y.z> ...]
|
|
5
|
+
Fails (exit 1) on: a local link or asset that does not resolve, a page without exactly one
|
|
6
|
+
<title>, an <img> without width/height or whose file is missing, leftover TODO/PENDING/COMING SOON
|
|
7
|
+
markers, and version strings below the given floors next to a package name.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
import sys
|
|
15
|
+
from html.parser import HTMLParser
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Collector(HTMLParser):
|
|
19
|
+
def __init__(self) -> None:
|
|
20
|
+
super().__init__()
|
|
21
|
+
self.titles = 0
|
|
22
|
+
self.links: list[str] = []
|
|
23
|
+
self.imgs: list[tuple[str, bool]] = []
|
|
24
|
+
|
|
25
|
+
def handle_starttag(self, tag, attrs): # noqa: ANN001
|
|
26
|
+
d = dict(attrs)
|
|
27
|
+
if tag == "title":
|
|
28
|
+
self.titles += 1
|
|
29
|
+
if tag in ("a", "link") and d.get("href"):
|
|
30
|
+
self.links.append(d["href"])
|
|
31
|
+
if tag in ("script", "source", "video", "audio") and d.get("src"):
|
|
32
|
+
self.links.append(d["src"])
|
|
33
|
+
if tag == "img" and d.get("src"):
|
|
34
|
+
self.imgs.append((d["src"], bool(d.get("width") and d.get("height"))))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def local(ref: str) -> str | None:
|
|
38
|
+
if re.match(r"^(https?:|mailto:|tel:|data:|javascript:|#)", ref):
|
|
39
|
+
return None
|
|
40
|
+
return ref.split("#", 1)[0].split("?", 1)[0] or None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def main() -> int:
|
|
44
|
+
ap = argparse.ArgumentParser()
|
|
45
|
+
ap.add_argument("site")
|
|
46
|
+
ap.add_argument("--min-version-for", action="append", default=[], metavar="PKG=X.Y.Z")
|
|
47
|
+
a = ap.parse_args()
|
|
48
|
+
root = os.path.abspath(a.site)
|
|
49
|
+
floors = dict(x.split("=", 1) for x in a.min_version_for)
|
|
50
|
+
problems: list[str] = []
|
|
51
|
+
pages = [f for f in os.listdir(root) if f.endswith(".html")]
|
|
52
|
+
for page in sorted(pages):
|
|
53
|
+
text = open(os.path.join(root, page), encoding="utf-8", errors="replace").read()
|
|
54
|
+
c = Collector()
|
|
55
|
+
c.feed(text)
|
|
56
|
+
if c.titles != 1:
|
|
57
|
+
problems.append(f"{page}: {c.titles} <title> tags")
|
|
58
|
+
for marker in ("TODO", "PENDING-W", "COMING SOON", "coming soon", "FIXME"):
|
|
59
|
+
if marker in text:
|
|
60
|
+
problems.append(f"{page}: leftover marker {marker!r}")
|
|
61
|
+
for ref in c.links:
|
|
62
|
+
rel = local(ref)
|
|
63
|
+
if rel and not os.path.exists(os.path.join(root, rel.lstrip("/"))):
|
|
64
|
+
problems.append(f"{page}: broken local link {ref}")
|
|
65
|
+
for src, sized in c.imgs:
|
|
66
|
+
rel = local(src)
|
|
67
|
+
if rel and not os.path.exists(os.path.join(root, rel.lstrip("/"))):
|
|
68
|
+
problems.append(f"{page}: missing image {src}")
|
|
69
|
+
if not sized:
|
|
70
|
+
problems.append(f"{page}: <img {src}> without width/height")
|
|
71
|
+
for pkg, floor in floors.items():
|
|
72
|
+
for m in re.finditer(re.escape(pkg) + r"[^0-9\n]{0,40}?(\d+\.\d+\.\d+)", text):
|
|
73
|
+
found = tuple(int(x) for x in m.group(1).split("."))
|
|
74
|
+
if found < tuple(int(x) for x in floor.split(".")):
|
|
75
|
+
problems.append(f"{page}: {pkg} {m.group(1)} is below the released {floor}")
|
|
76
|
+
for p in problems:
|
|
77
|
+
print(p)
|
|
78
|
+
print(f"{len(pages)} pages, {len(problems)} problems")
|
|
79
|
+
return 1 if problems else 0
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if __name__ == "__main__":
|
|
83
|
+
sys.exit(main())
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Serve a static site directory locally with HTTP Range support (videos seek), no caching.
|
|
3
|
+
|
|
4
|
+
Usage: preview_server.py <directory> [--port 56265] [--bind 127.0.0.1]
|
|
5
|
+
Read-only: it never writes into the directory. Stop it with Ctrl-C or kill <pid>.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
12
|
+
import sys
|
|
13
|
+
from functools import partial
|
|
14
|
+
from http import HTTPStatus
|
|
15
|
+
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class RangeHandler(SimpleHTTPRequestHandler):
|
|
19
|
+
def end_headers(self) -> None:
|
|
20
|
+
self.send_header("Cache-Control", "no-store")
|
|
21
|
+
self.send_header("Accept-Ranges", "bytes")
|
|
22
|
+
super().end_headers()
|
|
23
|
+
|
|
24
|
+
def send_head(self): # noqa: ANN201 - stdlib signature
|
|
25
|
+
rng = self.headers.get("Range")
|
|
26
|
+
if not rng:
|
|
27
|
+
return super().send_head()
|
|
28
|
+
path = self.translate_path(self.path)
|
|
29
|
+
if os.path.isdir(path):
|
|
30
|
+
return super().send_head()
|
|
31
|
+
try:
|
|
32
|
+
size = os.path.getsize(path)
|
|
33
|
+
except OSError:
|
|
34
|
+
self.send_error(HTTPStatus.NOT_FOUND, "File not found")
|
|
35
|
+
return None
|
|
36
|
+
m = re.match(r"bytes=(\d*)-(\d*)$", rng.strip())
|
|
37
|
+
if not m:
|
|
38
|
+
return super().send_head()
|
|
39
|
+
start = int(m.group(1)) if m.group(1) else max(0, size - int(m.group(2) or 0))
|
|
40
|
+
end = int(m.group(2)) if m.group(1) and m.group(2) else size - 1
|
|
41
|
+
end = min(end, size - 1)
|
|
42
|
+
if start > end or start >= size:
|
|
43
|
+
self.send_response(HTTPStatus.REQUESTED_RANGE_NOT_SATISFIABLE)
|
|
44
|
+
self.send_header("Content-Range", f"bytes */{size}")
|
|
45
|
+
self.end_headers()
|
|
46
|
+
return None
|
|
47
|
+
fh = open(path, "rb")
|
|
48
|
+
fh.seek(start)
|
|
49
|
+
self.send_response(HTTPStatus.PARTIAL_CONTENT)
|
|
50
|
+
self.send_header("Content-Type", self.guess_type(path))
|
|
51
|
+
self.send_header("Content-Range", f"bytes {start}-{end}/{size}")
|
|
52
|
+
self.send_header("Content-Length", str(end - start + 1))
|
|
53
|
+
self.end_headers()
|
|
54
|
+
self._range_left = end - start + 1
|
|
55
|
+
return fh
|
|
56
|
+
|
|
57
|
+
def copyfile(self, source, outputfile) -> None: # noqa: ANN001 - stdlib signature
|
|
58
|
+
left = getattr(self, "_range_left", None)
|
|
59
|
+
if left is None:
|
|
60
|
+
return super().copyfile(source, outputfile)
|
|
61
|
+
while left > 0:
|
|
62
|
+
chunk = source.read(min(65536, left))
|
|
63
|
+
if not chunk:
|
|
64
|
+
break
|
|
65
|
+
outputfile.write(chunk)
|
|
66
|
+
left -= len(chunk)
|
|
67
|
+
self._range_left = None
|
|
68
|
+
|
|
69
|
+
def log_message(self, fmt, *args) -> None: # noqa: ANN001 - quiet by default
|
|
70
|
+
if os.environ.get("PREVIEW_VERBOSE"):
|
|
71
|
+
super().log_message(fmt, *args)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def main() -> int:
|
|
75
|
+
ap = argparse.ArgumentParser()
|
|
76
|
+
ap.add_argument("directory")
|
|
77
|
+
ap.add_argument("--port", type=int, default=56265)
|
|
78
|
+
ap.add_argument("--bind", default="127.0.0.1")
|
|
79
|
+
a = ap.parse_args()
|
|
80
|
+
directory = os.path.abspath(a.directory)
|
|
81
|
+
if not os.path.isdir(directory):
|
|
82
|
+
print(f"not a directory: {directory}", file=sys.stderr)
|
|
83
|
+
return 2
|
|
84
|
+
handler = partial(RangeHandler, directory=directory)
|
|
85
|
+
httpd = ThreadingHTTPServer((a.bind, a.port), handler)
|
|
86
|
+
print(f"serving {directory} at http://{a.bind}:{a.port}/ (pid {os.getpid()})", flush=True)
|
|
87
|
+
try:
|
|
88
|
+
httpd.serve_forever()
|
|
89
|
+
except KeyboardInterrupt:
|
|
90
|
+
pass
|
|
91
|
+
return 0
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if __name__ == "__main__":
|
|
95
|
+
sys.exit(main())
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
validations:
|
|
9
9
|
- name: abstract-release
|
|
10
10
|
source: codex-skills (maintainer)
|
|
11
|
-
tree_hash:
|
|
11
|
+
tree_hash: e8c297c3c8a73d54a68fd754f789a54095ee701a8e36049de433342425e741a5
|
|
12
12
|
level: adopted
|
|
13
13
|
method: first-party-adoption
|
|
14
14
|
audience: host
|
|
15
15
|
validated_by: skill
|
|
16
|
-
validated_at: '2026-
|
|
16
|
+
validated_at: '2026-11-02'
|
|
17
17
|
evidence:
|
|
18
18
|
parser_roundtrip: true
|
|
19
19
|
has_scripts: true
|
|
20
|
-
files:
|
|
20
|
+
files: 8
|
|
21
21
|
notes: "Maintainer-authored skill (AbstractFramework release waves), rewritten 2026-10-27\
|
|
22
22
|
\ from the release wave of that day: dependency order with AbstractNote after\
|
|
23
23
|
\ the gateway, per-package mechanics (tag push vs workflow_dispatch, GitHub publishing-environment\
|
|
@@ -31,8 +31,19 @@ validations:
|
|
|
31
31
|
\ requires_review at the gate until the operator enables them. Adversarially reviewed\
|
|
32
32
|
\ before pinning (3 P0 / 6 P1 / 5 P2 folded: committed-but-unpublished detection,\
|
|
33
33
|
\ per-workflow dispatch inputs, AbstractCode/Abstract3D triggers, scratch-gateway\
|
|
34
|
-
\ recipe verified live).
|
|
35
|
-
\
|
|
34
|
+
\ recipe verified live). Re-reviewed and re-pinned 2026-11-02 from the maintainer\
|
|
35
|
+
\ copy: abstractavatar (crate first, then the Python package) in the order, AbstractAssistant's\
|
|
36
|
+
\ four lanes (PyPI, web, iPhone, watch; Apple lanes through the app-store environment),\
|
|
37
|
+
\ a gated step 9 handing the website to abstractframework-website (never pushes\
|
|
38
|
+
\ gh-pages), the operator's release-execution and repo-sync rules, the final local-build\
|
|
39
|
+
\ gate and 'show me your work' report, changelog fragments; NEW references/readiness-audit.md\
|
|
40
|
+
\ (read-only audit evidence contract); package-inventory rows for AbstractAvatar\
|
|
41
|
+
\ and the Assistant lanes. PLANNER PATCHED: a crate and a Python package sharing\
|
|
42
|
+
\ a name (abstractavatar) no longer abort with 'duplicate package' \u2014 the\
|
|
43
|
+
\ crate keys as <name>-crate, a crate dependent's edge resolves to it, CRATE_RELEASE_VERSIONS\
|
|
44
|
+
\ pins map to it (verified on the live workspace: 36 packages, abstractavatar-crate\
|
|
45
|
+
\ ordered before abstracttui; the previous planner aborts). Still read-only, stdlib\
|
|
46
|
+
\ only. Behavioral audit (backlog 0003) pending \u2014 upgrades to audited then."
|
|
36
47
|
- name: abstractframework-gateway
|
|
37
48
|
source: first-party
|
|
38
49
|
tree_hash: bf438ba23526abf39e591865358c55ae8efa4da61437c4fc5527bafc68c6882d
|
|
@@ -58,6 +69,29 @@ validations:
|
|
|
58
69
|
\ text) and close was taught as loop-release \u2014 re-taught to auto-wake-on-open\
|
|
59
70
|
\ + restore-previous-on-close, refusal reasons verified against entity_visits.py\
|
|
60
71
|
\ (paused/one-visit/consent-rite; sleep wakes)."
|
|
72
|
+
- name: abstractframework-website
|
|
73
|
+
source: first-party
|
|
74
|
+
tree_hash: b91fe3fb6d167fee6f535c5d9004669233b978c822b6ccd8054b2382eae5d0d5
|
|
75
|
+
level: first_party
|
|
76
|
+
method: first-party
|
|
77
|
+
audience: host
|
|
78
|
+
validated_by: skill
|
|
79
|
+
validated_at: '2026-11-02'
|
|
80
|
+
evidence:
|
|
81
|
+
parser_roundtrip: true
|
|
82
|
+
has_scripts: true
|
|
83
|
+
files: 3
|
|
84
|
+
notes: "First-party skill (2026-11-02): update the abstractframework.ai site (the\
|
|
85
|
+
\ gh-pages branch of lpalbou/AbstractFramework) after a release wave \u2014 inventory\
|
|
86
|
+
\ what is published, diff the site against reality, a claims ledger before any\
|
|
87
|
+
\ copy change, apply on a site-<root version> branch, check, adversarial pass,\
|
|
88
|
+
\ serve locally and hand the operator a preview URL. GATED: the skill never pushes,\
|
|
89
|
+
\ force-pushes, rebases or merges gh-pages; the operator validates the preview\
|
|
90
|
+
\ and publishes. SCRIPTS-BEARING (two read-only stdlib helpers under references/):\
|
|
91
|
+
\ preview_server.py (static server with HTTP Range support, binds 127.0.0.1 by\
|
|
92
|
+
\ default, no writes) and check_site.py (static link/asset/title/marker/version-floor\
|
|
93
|
+
\ checker, no writes, no network), so requires_review at the gate until the operator\
|
|
94
|
+
\ enables them. Paths name the maintainer's workspace."
|
|
61
95
|
- name: adr
|
|
62
96
|
source: codex-skills (maintainer)
|
|
63
97
|
tree_hash: a4cb55fcea54e969a9c342e314b4dda3556ce5e6fb0e210821350688c62c934b
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractskill
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
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
|
|
@@ -61,12 +61,16 @@ pip install abstractskill
|
|
|
61
61
|
|
|
62
62
|
The wheel carries the library and the curated skill registry (the shelf below).
|
|
63
63
|
|
|
64
|
+
What's new in 0.3.4: the `abstractframework-website` skill joins the shelf and
|
|
65
|
+
`abstract-release` covers AbstractAvatar and the AbstractAssistant lanes; see
|
|
66
|
+
the [changelog](CHANGELOG.md#034---2026-11-02).
|
|
67
|
+
|
|
64
68
|
## The bundled skill registry
|
|
65
69
|
|
|
66
70
|
`pip install abstractskill` installs the reviewed shelf as package data:
|
|
67
71
|
|
|
68
72
|
```
|
|
69
|
-
abstractskill/registry/skills/ #
|
|
73
|
+
abstractskill/registry/skills/ # 16 curated skills (one folder per SKILL.md)
|
|
70
74
|
abstractskill/registry/licenses/ # upstream licenses of catalog-vendored skills
|
|
71
75
|
abstractskill/registry/validations.yaml # trust records: byte pins per skill tree
|
|
72
76
|
abstractskill/registry/advisories.yaml # do-not-use advisories (empty at v1, by design)
|
|
@@ -31,10 +31,14 @@ src/abstractskill/registry/skills/abstract-release/SKILL.md
|
|
|
31
31
|
src/abstractskill/registry/skills/abstract-release/agents/openai.yaml
|
|
32
32
|
src/abstractskill/registry/skills/abstract-release/references/package-discovery.md
|
|
33
33
|
src/abstractskill/registry/skills/abstract-release/references/package-inventory.md
|
|
34
|
+
src/abstractskill/registry/skills/abstract-release/references/readiness-audit.md
|
|
34
35
|
src/abstractskill/registry/skills/abstract-release/references/release-process.md
|
|
35
36
|
src/abstractskill/registry/skills/abstract-release/scripts/abstract_release_plan.py
|
|
36
37
|
src/abstractskill/registry/skills/abstract-release/scripts/pypi_visibility_gate.py
|
|
37
38
|
src/abstractskill/registry/skills/abstractframework-gateway/SKILL.md
|
|
39
|
+
src/abstractskill/registry/skills/abstractframework-website/SKILL.md
|
|
40
|
+
src/abstractskill/registry/skills/abstractframework-website/references/check_site.py
|
|
41
|
+
src/abstractskill/registry/skills/abstractframework-website/references/preview_server.py
|
|
38
42
|
src/abstractskill/registry/skills/adr/SKILL.md
|
|
39
43
|
src/abstractskill/registry/skills/adr/agents/openai.yaml
|
|
40
44
|
src/abstractskill/registry/skills/adr/references/adr-template-and-workflow.md
|
|
@@ -38,8 +38,8 @@ LICENSES = (
|
|
|
38
38
|
# The bundle version must move whenever the bundled content moves. When this
|
|
39
39
|
# test fails: bump `version:` in src/abstractskill/registry/catalog.yaml, then
|
|
40
40
|
# update BOTH values below (the digest printed in the failure message).
|
|
41
|
-
PINNED_VERSION = "2026.
|
|
42
|
-
PINNED_DIGEST = "
|
|
41
|
+
PINNED_VERSION = "2026.11.02"
|
|
42
|
+
PINNED_DIGEST = "1486aef6fd33341f74a7d2310a45a3c4c930b40de740fa203b1fcd83935fd687"
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
def _bundle_digest(root: Path) -> str:
|
|
@@ -70,11 +70,11 @@ def _all_items() -> set[str]:
|
|
|
70
70
|
return skills | set(TRUST_FILES) | set(LICENSES)
|
|
71
71
|
|
|
72
72
|
|
|
73
|
-
def
|
|
73
|
+
def test_bundled_dir_is_the_package_registry_with_16_skills() -> None:
|
|
74
74
|
root = bundled_registry_dir()
|
|
75
75
|
assert root == REPO / "src" / "abstractskill" / "registry"
|
|
76
76
|
skills = sorted(p.name for p in (root / "skills").iterdir() if p.is_dir())
|
|
77
|
-
assert len(skills) ==
|
|
77
|
+
assert len(skills) == 16
|
|
78
78
|
assert all((root / "skills" / name / "SKILL.md").is_file() for name in skills)
|
|
79
79
|
for name in TRUST_FILES:
|
|
80
80
|
assert (root / name).is_file()
|
|
@@ -26,6 +26,7 @@ GUIDANCE = REPO / "src" / "abstractskill" / "registry" / "guidance.yaml"
|
|
|
26
26
|
EXPECTED_SHELF = {
|
|
27
27
|
"abstract-release",
|
|
28
28
|
"abstractframework-gateway",
|
|
29
|
+
"abstractframework-website",
|
|
29
30
|
"adversarial-iteration",
|
|
30
31
|
"adr",
|
|
31
32
|
"agora-collaboration",
|
|
@@ -49,6 +50,7 @@ EXPECTED_SHELF = {
|
|
|
49
50
|
EXPECTED_LEVELS = {
|
|
50
51
|
"abstract-release": TrustLevel.ADOPTED,
|
|
51
52
|
"abstractframework-gateway": TrustLevel.FIRST_PARTY,
|
|
53
|
+
"abstractframework-website": TrustLevel.FIRST_PARTY,
|
|
52
54
|
"adversarial-iteration": TrustLevel.FIRST_PARTY,
|
|
53
55
|
"agora-collaboration": TrustLevel.FIRST_PARTY,
|
|
54
56
|
"adr": TrustLevel.ADOPTED,
|
|
@@ -66,6 +68,7 @@ EXPECTED_LEVELS = {
|
|
|
66
68
|
EXPECTED_SOURCES = {
|
|
67
69
|
"abstract-release": "codex-skills (maintainer)",
|
|
68
70
|
"abstractframework-gateway": "first-party",
|
|
71
|
+
"abstractframework-website": "first-party",
|
|
69
72
|
"adversarial-iteration": "first-party",
|
|
70
73
|
"agora-collaboration": "first-party",
|
|
71
74
|
"adr": "codex-skills (maintainer)",
|
|
@@ -85,7 +88,9 @@ EXPECTED_SOURCES = {
|
|
|
85
88
|
# name HERE — the admission review's explicit signature, never a silent pass.
|
|
86
89
|
# abstract-release (2026-10-27): a read-only release planner and a registry
|
|
87
90
|
# visibility gate (stdlib, HTTPS GETs to pypi.org / registry.npmjs.org only).
|
|
88
|
-
|
|
91
|
+
# abstractframework-website (2026-11-02): two read-only helpers under
|
|
92
|
+
# references/ (a local Range-capable preview server, a static site checker).
|
|
93
|
+
EXPECTED_SCRIPTS_BEARING: set[str] = {"abstract-release", "abstractframework-website"}
|
|
89
94
|
|
|
90
95
|
|
|
91
96
|
def test_shelf_discovers_exactly_the_expected_skills() -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/adr/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/architect/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/backlog/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/coredoc/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/review/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractskill-0.3.3 → abstractskill-0.3.4}/src/abstractskill/registry/skills/uxreview/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|