Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: Release

# Simple version tags on main are the release trigger (see
# docs/DESIGN_NOTES.md, release-based distribution). Nothing here treats
# "latest" specially: every release is an explicit, exact tag, and every
# tag that reaches this workflow is validated the same way main is,
# then packaged, then exercised end to end, before anything is published.

on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"

permissions:
contents: write

jobs:
build-and-validate:
name: Build and validate package
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.x"

- name: Install validation dependency
run: python -m pip install --disable-pip-version-check pyyaml

- name: Validate repository structure
run: python scripts/ci-validate.py

- name: Derive version from tag
id: version
run: echo "version=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"

- name: Build release package
run: scripts/build-release.sh "${{ steps.version.outputs.version }}"

- name: Verify the build is reproducible
run: |
set -eu
version="${{ steps.version.outputs.version }}"
mv "dist/codebase-learning-flow-$version.zip" /tmp/first-build.zip
rm -rf dist
scripts/build-release.sh "$version"
cmp /tmp/first-build.zip "dist/codebase-learning-flow-$version.zip"
echo "Two independent builds of $version produced byte-identical packages."

- name: Exercise the packaged installation (install.sh)
run: scripts/ci-release-test.sh "dist/codebase-learning-flow-${{ steps.version.outputs.version }}.zip"

- uses: actions/upload-artifact@v4
with:
name: release-package
path: |
dist/codebase-learning-flow-${{ steps.version.outputs.version }}.zip
dist/checksums.txt
retention-days: 7

powershell-install-check:
name: Exercise the packaged installation (install.ps1)
needs: build-and-validate
runs-on: windows-latest
steps:
- uses: actions/checkout@v4

- uses: actions/download-artifact@v4
with:
name: release-package
path: dist

- name: Install minimal profile from the local package
shell: pwsh
run: |
$version = "${{ needs.build-and-validate.outputs.version }}"
$package = "dist/codebase-learning-flow-$version.zip"
$root = Join-Path $env:RUNNER_TEMP "learning-flow-release-ci"
New-Item -ItemType Directory -Force -Path $root | Out-Null
& "$PWD/scripts/install.ps1" `
-TargetPath $root `
-PackageFile $package `
-Profile minimal `
-Mode fail `
-SkipRootAgents
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
if (-not (Test-Path "$root/learning-flow")) {
throw "Installer did not create the learning-flow component from the packaged release."
}
if (-not (Test-Path "$root/.agents/skills")) {
throw "Installer did not create .agents/skills from the packaged release."
}

publish:
name: Publish GitHub Release
needs: [build-and-validate, powershell-install-check]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/download-artifact@v4
with:
name: release-package
path: dist

- name: Publish release with validated assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.build-and-validate.outputs.version }}
generate_release_notes: true
files: |
dist/codebase-learning-flow-${{ needs.build-and-validate.outputs.version }}.zip
dist/checksums.txt
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Desktop.ini
# Locally generated distribution archives
/INITIALIZE_LEARNING_FLOW_*.zip
/codebase-learning-flow*.zip
/dist/

# Python script cache
/scripts/__pycache__
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

### Added

- Packaged, checksum-verified release distribution: `--release`/`-Release TAG` in `install.sh`/`install.ps1` downloads the artifact and `checksums.txt` published against an exact tag, verifies the SHA-256 checksum before extracting anything, and cross-checks the package's own `VERSION` file against the requested tag. `--release latest` is rejected; an exact tag is required.
- `scripts/build-release.sh`, which builds the release package directly from `MANIFEST.txt` (the existing package manifest), normalizing file timestamps so two independent builds of the same tree at the same version produce a byte-identical archive.
- `scripts/ci-release-test.sh`, which installs a built package end to end (minimal, full+regulatory, update mode, fail-mode refusal, adoption-resource presence) without touching the network.
- `.github/workflows/release.yml`: on a `v*.*.*` tag push, validates repository structure, builds the release package, verifies build reproducibility, exercises the packaged installation on both `install.sh` and `install.ps1`, and only then publishes the GitHub Release with the package and `checksums.txt` attached.
- A closing `Version:`/`Source:` summary in both installers, distinguishing a packaged release (`packaged release (checksum verified)`) from a development checkout (`development checkout (mutable unless ref is a commit or tag)`).
- A shared `agentic-flow/EDUCATION.md` constitution used by general and repository learning.
- Human-readable Mermaid maps, highlight blocks, and progressive disclosure across core README files.
- Explicit resilience, responsible AI leverage, educational judgment, and domain ownership lenses.
Expand All @@ -16,6 +21,12 @@
- Minimal and full maps and takeaways now retain reusable ownership, resilience, AI fallback, and control knowledge.
- Full-profile skills now validate machine-generated work and surface operational or human control boundaries in proportion to risk.
- Human-facing documentation now explains the framework before agentic implementation detail.
- README and `scripts/README.md` installation guidance now documents packaged-release installation as implemented behavior rather than a planned path.

### Fixed

- `MANIFEST.txt` was missing `docs/ARCHITECTURE.md` and `docs/AGENTIC_WORKFLOW_SANITY.md`, both of which are linked from README and `docs/README.md`; both are now declared with correct sizes.
- `install.ps1` reported a hardcoded, unmaintained `$InstallerVersion` (stuck at `0.8.0`) in a self-refresh log line; removed in favor of the new commit/tag-based version reporting, which cannot go stale.

## 0.8.0

Expand Down
16 changes: 9 additions & 7 deletions MANIFEST.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
.gitattributes 40
.gitignore 317
.gitignore 324
AGENTS.md 3172
CHANGELOG.md 13500
docs/DESIGN_NOTES.md 23730
CHANGELOG.md 15425
docs/AGENTIC_WORKFLOW_SANITY.md 7795
docs/ARCHITECTURE.md 6009
docs/DESIGN_NOTES.md 27644
docs/EDUCATION_MODEL.md 5452
docs/INITIALIZE_LEARNING_FLOW.md 10880
docs/README.md 4185
Expand All @@ -14,7 +16,7 @@ docs/references/REFERENCE_REVIEW_LEARNING_FLOW_ADJUSTMENT.md 9505
docs/references/REFERENCE_REVIEW_LITT.md 2069
docs/references/REFERENCE_REVIEW_POCOK.md 2155
LICENSE 2213
README.md 16282
README.md 17154
sample/common/.agents/skills/agentic-workflow/SKILL.md 4185
sample/common/.agents/skills/learn-anything/agents/openai.yaml 246
sample/common/.agents/skills/learn-anything/SKILL.md 3362
Expand Down Expand Up @@ -95,9 +97,9 @@ sample/README.md 2997
sample/root/AGENTS.md 1339
sample/root/AGENTS.pointer.md 296
scripts/install.bat 1477
scripts/install.ps1 35102
scripts/install.sh 29472
scripts/README.md 4900
scripts/install.ps1 40236
scripts/install.sh 34910
scripts/README.md 6656
skill-evals/agentic-cases.yaml 7109
skill-evals/conversation-cases.yaml 3653
skill-evals/full-cases.yaml 4248
Expand Down
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,24 @@ The framework is intentionally tested against representative low-risk, learning,
### Preferred: packaged release

For team and enterprise use, install a reviewed, versioned release rather than
executing a mutable checkout from `main`. Release installation will be the
preferred distribution path once packaged releases are published.
executing a mutable checkout from `main`. `--release`/`-Release` downloads the
packaged artifact published against an exact tag, verifies its checksum
before extracting anything, and refuses `latest`: pin the version the team
actually reviewed.

Pin the exact release version used by the team and retain the version in the
installation record.
```sh
curl -fsSL https://raw.githubusercontent.com/legrab/codebase-learning-flow/main/scripts/install.sh -o install.sh
sh install.sh --release v0.9.0 --profile minimal
```

```powershell
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/legrab/codebase-learning-flow/main/scripts/install.ps1))) -Release v0.9.0 -Profile Minimal
```

The installer's closing summary states the resolved `Version:` and `Source:`
so the pinned version is easy to record alongside the installation. See
[`scripts/README.md`](scripts/README.md#installing-a-packaged-release) for
the full flag reference and what checksum verification actually checks.

### Development checkout

Expand Down Expand Up @@ -112,7 +125,11 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr https://raw.githubus
./scripts/install.sh --mode update
```

Remote piping executes the referenced revision. Pin a release tag or commit for a team installation.
Remote piping executes whatever `main` currently resolves to. For a team or
enterprise installation, use `--release`/`-Release` with an exact tag (see
"Preferred: packaged release" above) rather than pinning a checkout commit:
the release path adds checksum verification and is what CI actually
validates before publishing.

</details>

Expand Down
18 changes: 18 additions & 0 deletions docs/DESIGN_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,23 @@ Minimal-to-full update is supported. Full-to-minimal update is rejected because

Extensions (currently only `regulatory`) use the same three modes along a dimension orthogonal to profile: they track their own managed-file and managed-skill manifests under distinct marker names so they never collide with the profile's own markers, and adding or removing one never touches the other's files.

## Release-based distribution

A checkout install (`--ref`/`-Ref`, default `main`) and a packaged-release install (`--release`/`-Release`) are two distinct trust boundaries, not two code paths for the same thing:

- **Checkout** downloads GitHub's own source-archive snapshot of an arbitrary ref. It is the mutable, development-oriented path: convenient for trying the framework or tracking `main`, but nothing about it asserts that the content was reviewed as a unit.
- **Packaged release** downloads a purpose-built artifact published against an exact, immutable tag, with a checksum the installer verifies before extracting anything. `scripts/build-release.sh` builds this artifact directly from `MANIFEST.txt`, so the package's contents and the package's own manifest never drift apart: `MANIFEST.txt` is the single declared list of "what ships," used both for CI's size/drift check and for the release build.

Design decisions specific to this boundary:

- **No `latest` shortcut.** Both installers reject `--release latest` outright rather than resolving and warning. An enterprise install that claims to be version-pinned should not have a silent path to "whatever the newest tag happens to be today." Pinning is enforced by the absence of the feature, not by a warning someone can miss.
- **The installer reports its trust boundary, not just its ref.** The closing summary always states `Version:` and `Source:` distinctly for a checkout (`development checkout`) versus a packaged release (`packaged release (checksum verified)`), so a person looking at installer output (or CI logs) can tell which boundary they got without reading the flags that produced it.
- **The release path does not require `git`.** Only the self-refresh stage (pinning the installer script itself to the release commit) touches `resolve_remote_commit`; the payload step downloads the release asset and its checksum over HTTP(S) directly, so a minimal environment with just `curl`/`wget`, `unzip`, and a SHA-256 tool can install a pinned release.
- **The package is a curated subset, not the whole repository.** `MANIFEST.txt` already excludes CI/workflow files and maintainer-only scripts (`ci-validate.py`, `check_manifest.py`, `manifest-update.py`, `ci-install-test.sh`, and now `build-release.sh`/`ci-release-test.sh`) from "the package" -- consistent with the pre-existing convention that repository infrastructure lives outside the package manifest. The release artifact ships exactly what an installing repository needs plus the documentation required to understand and adopt it.
- **Reproducibility is enforced, not assumed.** `scripts/build-release.sh` normalizes staged file mtimes before zipping specifically so that two independent builds of the same tree at the same version produce a byte-identical archive; CI builds twice and diffs them before anything is exercised or published.
- **CI validates the artifact it is about to publish, not just the source tree.** The release workflow builds the package, confirms reproducibility, then runs the installer against the built package itself (minimal, full+regulatory, update-mode, and fail-mode-refusal, on both the POSIX and PowerShell installers) before a GitHub Release is created. A release that fails any of these checks is never published.
- **A hidden `--package-file`/`-PackageFile` flag exists solely for this CI loop.** It installs directly from a local archive, bypassing both the network and self-refresh, which is what lets CI exercise a release package before that package has actually been published anywhere. It is intentionally undocumented in `--help`/user-facing docs: it is a testing seam, not a supported installation method.

## Deliberately rejected

- mandatory configuration before routine work;
Expand Down Expand Up @@ -254,3 +271,4 @@ Extensions (currently only `regulatory`) use the same three modes along a dimens
11. The Markdown fallback works without skill support.
12. No workflow requires contributor identity unless the user explicitly wants personal tracking.
13. An installed extension never changes what a profile means, and adding or removing one never touches unrelated framework or repository content.
14. A checkout install and a packaged-release install are never ambiguous about which one ran: the installer states its version and trust boundary, and there is no path that silently resolves an unpinned "latest" release.
56 changes: 51 additions & 5 deletions scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ These scripts perform **complete installation**. They are intentionally separate
from the guided adoption process under `adoption/`, which is for repositories
that already have their own agentic delivery layer.

For team and enterprise use, the preferred future distribution path is a pinned
packaged release. Checkout-based installers remain useful for framework
development and experimentation.
For team and enterprise use, the preferred distribution path is a pinned,
checksum-verified packaged release (`--release`/`-Release`). Checkout-based
installers (`--ref`/`-Ref`, defaulting to `main`) remain available and are the
right choice for framework development and experimentation, but they resolve
a mutable source snapshot with no checksum, so treat them as a development
path rather than a production one.

```mermaid
flowchart LR
D[Download pinned source] --> P[Select profile]
D[Resolve source: checkout ref or pinned release] --> P[Select profile]
P --> C[Install common agentic flow]
C --> L[Install learning profile]
L --> Ext[Install or remove regulatory extension]
Expand All @@ -21,6 +24,49 @@ flowchart LR
X --> R[Integrate or preserve root AGENTS]
```

## Installing a packaged release

```text
--release TAG
-Release TAG
```

```text
sh install.sh --release v0.9.0 --profile minimal
```

```powershell
.\install.ps1 -Release v0.9.0 -Profile Minimal
```

`--release`/`-Release` downloads the packaged artifact and `checksums.txt`
published against that exact tag on the repository's Releases page, verifies
the SHA-256 checksum before extracting anything, and cross-checks the
package's own `VERSION` file against the requested tag. `--ref`/`-Ref` and
`--release`/`-Release` are mutually exclusive. `latest` is not accepted as a
release value: look up the tag you want on the Releases page and pass it
explicitly. This is deliberate, not an oversight -- see "Release-based
distribution" in `docs/DESIGN_NOTES.md`.

Every install prints which trust boundary it used:

```text
Codebase Learning Flow
Version: v0.9.0
Source: packaged release (checksum verified)
```

```text
Codebase Learning Flow
Version: 4f2ab61 (ref: main)
Source: development checkout (mutable unless ref is a commit or tag)
```

Release packages are built by `scripts/build-release.sh` from `MANIFEST.txt`
and validated end to end (`scripts/ci-release-test.sh`, on both installers)
by `.github/workflows/release.yml` before anything is published. A release
never ships something CI has not already installed and exercised.

## Installed components

1. common `agentic-flow/`;
Expand Down Expand Up @@ -102,6 +148,6 @@ The installer never replaces an existing root file wholesale.
- Old contributor placeholders retired by a managed manifest can be removed during update.
- Contributor-authored legacy learning state is never deleted automatically. Copy it into `.local/`, verify it, then remove the tracked source explicitly.
- Repeated local workspace initialization is idempotent.
- Team installations should pin a tag or commit rather than relying on a moving branch.
- Team installations should use `--release`/`-Release` with an exact tag rather than relying on a moving branch. A `--ref`/`-Ref` commit SHA is pinned too, but skips checksum verification and the packaged-release documentation-inclusion guarantees.

</details>
Loading
Loading