executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
) so only the project's own version matches. Use `sed -i.bak` plus backup cleanup for portable in-place edits across macOS/BSD sed and GNU sed.\n\n**Released tier (per-package semver):**\n\n```bash\n# Example: openai goes 1.6.0 -> 1.6.1 (PATCH); core stays\nsed -i.bak 's/^version = \"1.6.0\"$/version = \"1.6.1\"/' python/packages/openai/pyproject.toml\nrm python/packages/openai/pyproject.toml.bak\n```\n\n**Root `agent-framework` (only when `core` bumps, OR for its own changes):**\n\n```bash\nsed -i.bak \"s/^version = \\\"${OLD_ROOT}\\\"$/version = \\\"${NEW_ROOT}\\\"/\" python/pyproject.toml\n# AND keep the exact pin in sync with core\nsed -i.bak \"s/agent-framework-core\\\\[all\\\\]==${OLD_CORE}/agent-framework-core[all]==${NEW_CORE}/\" python/pyproject.toml\nrm python/pyproject.toml.bak\n```\n\n**RC tier (counter increment):**\n\n```bash\n# ag-ui goes 1.0.0rc3 -> 1.0.0rc4 only because it has a CHANGELOG entry\nsed -i.bak 's/^version = \"1.0.0rc3\"$/version = \"1.0.0rc4\"/' python/packages/ag-ui/pyproject.toml\nrm python/packages/ag-ui/pyproject.toml.bak\n```\n\n**Alpha/Beta tier (new date stamp):**\n\n```bash\nOLD_DATE=260521\nNEW_DATE=260528\n\n# Only the packages with CHANGELOG entries get the new stamp.\n# Example: anthropic and bedrock had entries, others did not.\nfor pkg in anthropic bedrock; do\n file=\"python/packages/$pkg/pyproject.toml\"\n sed -i.bak \"s/1\\\\.0\\\\.0b${OLD_DATE}/1.0.0b${NEW_DATE}/g\" \"$file\"\n rm \"${file}.bak\"\ndone\n```\n\nIf the user opts into a cohort-wide beta bump regardless of per-package changes, enumerate every beta package from `PACKAGE_STATUS.md` and stamp all of them. State that this is a cohort bump in the commit message.\n\nSpot-check with `grep '^version' python/pyproject.toml python/packages/*/pyproject.toml | sort` before moving on.\n\n### 5a. Refresh the `core[all]` release cohort\n\nWhen Core bumps, update every Agent Framework dependency in\n`python/packages/core/pyproject.toml` `[project.optional-dependencies].all`:\n\n- Workspace packages use their post-bump version as the lower bound, or their unchanged current version when they\n are not otherwise releasing this cycle.\n- External Agent Framework packages such as Azure Functions and Durable Task retain a bounded known-good floor.\n- Every entry keeps an upper bound for its supported major version.\n- Preserve environment markers for packages that do not support every Python/platform combination.\n\nThese bounds prevent pip from backtracking across old cyclic `core[all] -> integration -> core` combinations. The\nrelease validator rejects missing, stale, or unbounded cohort entries.\n\n### 6. Floor bound updates on `agent-framework-core`\n\nOnly relevant when `core` itself bumped this cycle. Two policies, pick one explicitly with the user:\n\n- **Conservative (default)**: raise `agent-framework-core>=X.Y.Z` to the new core version on every non-core package that is ALSO bumping this cycle. Leaves packages-not-bumped at their existing floor.\n- **Strict per-upstream-doc**: only raise the floor on packages that actually consume a new core API introduced in the bump. This requires per-package code inspection because release probes use the co-released local core and cannot prove compatibility with an older published core floor.\n\nWhen raising a core floor, replace only the `>=OLD` half of the bound you intend to change:\n\n```bash\nfile=\"python/packages/\u003cpkg>/pyproject.toml\"\nsed -i.bak \"s/agent-framework-core>=${OLD_CORE}/agent-framework-core>=${NEW_CORE}/\" \"$file\"\nrm \"${file}.bak\"\n```\n\nIf `core` did not bump this cycle, do not touch floors.\n\n### 7. Validate\n\n```bash\ncd python && uv run poe validate-python-release --base-ref \"$RELEASE_BASE\"\n```\n\nUse the same freshly fetched main ref that the release branch was based on (`upstream/main` above; use `origin/main`\nwhen that is the authoritative release base). Must exit 0. This task first regenerates `uv.lock`, then discovers the\npackage `pyproject.toml` files changed from that base and runs their published runtime dependencies and\nnon-development extras through lock-independent `lowest-direct` and `highest` import probes. The probes run in\nparallel, derive the minimum supported Python minor from each package's internal editable closure, and share a hard\n300-second deadline. Use `--python` only when the release requires an explicit interpreter override.\n\nThis is the release safety net for selective bumping: the lower probe catches unresolvable or unimportable external\nfloors, internal constraints that reject co-released package versions, and the upper probe catches caps that exclude\nan installable package set. The JSON report records the concrete versions resolved in both scenarios. It does not\nreplace the package-by-package code inspection required by the strict core-floor policy. If it fails, fix the named\npackage/bound and re-run before committing.\n\nDo not substitute the workspace-wide `validate-dependency-bounds-test` command here. That command runs every\npackage's full tests and Pyright in separate isolated environments and is intentionally reserved for CI or an\nexplicit dependency-range audit. If the release itself changes an external dependency range, also run\n`validate-dependency-bounds-project --mode both --package \u003cpkg> --dependency \u003cname>` for that dependency.\n\nIf only prereleases changed (no `core` bump, no floor changes), release validation is still required because the\nlockfile and both ends of each changed package's published dependency metadata must remain installable.\n\n### 8. Commit (expect hook retry)\n\nThe project's pre-commit hook runs `poe check` / `poe typing` / `uv lock` and may re-modify `uv.lock` on first commit attempt. Expected pattern — run twice:\n\n```bash\ngit add -u\ngit commit -m \"\u003cmessage>\" # may fail with \"files were modified by this hook\"\ngit add -u # re-stage hook-generated changes\ngit commit -m \"\u003cmessage>\" # succeeds\n```\n\n**Commit message format** — HEREDOC, no `Co-Authored-By`:\n\n```bash\ngit commit -m \"$(cat \u003c\u003c'EOF'\nBump Python package versions for \u003crelease-label> release\n\n\u003cOne paragraph explaining:\n - which packages bumped and why (CHANGELOG-driven)\n - semver rationale for any released-tier bumps\n - whether a beta cohort bump was applied\n - whether core floors were raised, and under which policy>\nEOF\n)\"\n```\n\n### 9. Push and report\n\n```bash\ngit push origin bump-py-ver-release-YYMMDD\n```\n\nThe push output includes a `Create a pull request for '\u003cbranch>' on GitHub by visiting: \u003cURL>` line — surface that to the user.\n\n## Pitfalls from past cycles — avoid repeating\n\n- **Scoping from the wrong tag.** A release may have been tagged between bump cycles. Always compute `LAST_RELEASED_TAG` fresh — do NOT reuse the previous compare base. Symptom: dragging already-shipped PRs into the new CHANGELOG section.\n- **Bumping packages that had no changes.** This was the old lockstep default. Now: a package without a CHANGELOG entry does not bump. The two exceptions (root follows core, optional beta cohort bump) are explicit choices, not defaults.\n- **Touched package missing from CHANGELOG.** The inverse failure mode of the previous pitfall, and the dangerous one. If a PR landed code into `python/packages/foo/` but the new CHANGELOG section has no `**agent-framework-foo**:` line, then `foo` will NOT bump, and the fix sits in `main` but never reaches PyPI. Always run the touched-vs-mentioned reconciliation in step 4a before applying bumps.\n- **Directory name vs PyPI name confusion.** Some package dirs use underscores or split names that differ from the published PyPI name (e.g. `foundry_local` → `agent-framework-foundry-local`). When reconciling touched dirs against CHANGELOG mentions, normalize on the PyPI form.\n- **Forgetting root when core bumps.** Root `agent-framework` has `agent-framework-core[all]==EXACT_VERSION`. If `core` bumps and root does not, the pin is broken. Always bump them together and update the pin string.\n- **Renaming an existing section header.** When drafting a new release, do NOT rewrite an existing `## [X.Y.Z]` header to a new label — that wipes the historical section. Always INSERT a new section above.\n- **Forgetting footer reference links.** When a released-tier bump is in play, the `[Unreleased]` line and the new `[X.Y.Z]` link at the bottom MUST be updated. Heading links don't resolve without them.\n- **Wrong footer compare base.** The new `[X.Y.Z]` line compares from the PREVIOUS released tag, not from two releases ago.\n- **Timezone drift.** For alpha/beta date stamps, follow the `python-package-management` date-stamp rule;\n do not infer a local timezone from the user's current shell.\n- **`Co-Authored-By` trailer.** Never add it. Rewrite/amend if it slipped in.\n- **Stale inventory in this skill.** Always read `python/PACKAGE_STATUS.md` for the live tier map. Do not trust a hardcoded list.\n- **Divergent origin vs upstream.** In fork clones, use freshly fetched `upstream/main` consistently for branch creation, changeset discovery, and release validation. A stale `origin/main` must never become the implicit compare base.\n- **`--pre` README cleanup on promotion.** When a package is promoted to `released` in this cycle, grep for `pip install agent-framework-\u003cpkg> --pre` in READMEs and drop the `--pre` flag.\n- **RC counter inflation.** Do not increment `1.0.0rcN` without a CHANGELOG entry for that package. The counter tracks iterations, not calendar.\n\n## References\n\n- Package lifecycle and versioning source of truth: `python/.github/skills/python-package-management/SKILL.md`\n- Lifecycle source of truth: `python/PACKAGE_STATUS.md`\n- Release validator: `python/scripts/dependencies/validate_dependency_bounds.py --mode release` (changed-package,\n lock-independent `lowest-direct` and `highest` import probes under a five-minute deadline)\n- Poe task definitions: `python/pyproject.toml` `[tool.poe.tasks]`\n","licenseDocuments":[]}}
agent-framework-py-releaseUse when cutting a Python release for the microsoft/agent-framework monorepo. Triggers on "bump py versions", "cut a python release", "prepare release PR for python", "release py packages", "bump python to X.Y.Z", or similar requests to bump Python package versions and prepare a release PR. Handles all four lifecycle tiers (alpha, beta, rc, released) with C…
Independent GitHub snapshot · Automated classification · Original documentation governs
Cuts a Python release PR for the microsoft/agent-framework monorepo.
No more universal lockstep. A package only bumps if it has a CHANGELOG entry this cycle. Draft the CHANGELOG first, then derive the bump list from it.
Exceptions to selective bumping (these stay coupled regardless of per-package changes):
agent-framework is coupled to agent-framework-core via agent-framework-core[all]==X.Y.Z (exact pin in python/pyproject.toml). If core bumps, root bumps. Root may also bump independently for its own changes (docs/metadata/extras).If the user explicitly states which packages to bump (or hands over a PR list per package), treat that as authoritative.
Use python/.github/skills/python-package-management/SKILL.md as the source of truth for lifecycle
version patterns, date-stamp cutoffs, classifier alignment, and internal dependency updates.
For release work, derive the live tier map at release time from python/PACKAGE_STATUS.md and the actual
version = lines in each pyproject.toml. Do not hardcode counts — packages move between tiers.
git log ${LAST_RELEASED_TAG}..${RELEASE_BASE} -- python/.python-package-management
date-stamp rule.If the user states target versions or a date explicitly, use exactly what they said — do not "correct" based on historical timezones.
python/CHANGELOG.md; this workflow creates the entries centrally from merged changes.python-package-management for package lifecycle and versioning rules — do not duplicate those
rules in this release workflow.Co-Authored-By trailer on any commit.uv run for cross-version Python/Poe commands and add the relevant
tooling/requirements-*.txt bundle only for single-version tools.git fetch origin main --tags --quiet
git fetch upstream main --tags --quiet 2>/dev/null || true
git status
# Fork clones use upstream/main as the authoritative release base; direct clones use origin/main.
if git show-ref --verify --quiet refs/remotes/upstream/main; then
RELEASE_BASE=upstream/main
else
RELEASE_BASE=origin/main
fi
git log -1 --oneline "$RELEASE_BASE"
If the user already has a bump-py-ver-release-* branch checked out, use it. Otherwise:
git checkout -b bump-py-ver-release-YYMMDD "$RELEASE_BASE"
Read python/PACKAGE_STATUS.md to enumerate current packages and lifecycle stages, and grep '^version' python/pyproject.toml python/packages/*/pyproject.toml to confirm actual versions. Cross-reference — if PACKAGE_STATUS.md shows a package as beta but its version looks like 1.0.0aYYMMDD, surface the inconsistency before proceeding.
Watch for: new packages added since the last release, lifecycle transitions (alpha→beta, beta→rc, rc→released), and stale packages that haven't been touched in many cycles.
Use the LATEST released tag as the compare base:
LAST_RELEASED_TAG=$(
git tag -l 'python-[0-9]*.[0-9]*.[0-9]*' \
| uv run --directory python python -c 'import sys; tags=[t.strip() for t in sys.stdin if t.strip()]; print(max(tags, key=lambda t: tuple(map(int, t[7:].split(".")))))'
)
echo "Compare base: $LAST_RELEASED_TAG"
List commits and packages touched:
git log --oneline ${LAST_RELEASED_TAG}..${RELEASE_BASE} -- python/ ':!python/CHANGELOG.md'
# Per-commit package footprint
for sha in $(git log --format='%H' ${LAST_RELEASED_TAG}..${RELEASE_BASE} -- python/); do
echo "--- $(git show -s --format='%h %s' $sha) ---"
git show --name-only --format='' $sha | grep '^python/packages/' | \
sed 's|^python/packages/||' | awk -F/ '{print $1}' | sort -u
done
When both remotes exist, record whether the fork is behind the authoritative base:
git rev-list --left-right --count origin/main...upstream/main
If user provides an explicit commit/PR list, treat THAT as authoritative.
Aggregate the per-commit footprint into a single union across the whole range. This is the source of truth for what must appear in the CHANGELOG. Save it before drafting entries.
# Union of all touched package directories across the range
git log --name-only --format='' ${LAST_RELEASED_TAG}..${RELEASE_BASE} -- python/packages/ \
| grep '^python/packages/' \
| sed 's|^python/packages/||' \
| awk -F/ '{print $1}' \
| sort -u
# Root-level files (drive a root agent-framework entry if substantive)
git log --name-only --format='' ${LAST_RELEASED_TAG}..${RELEASE_BASE} \
-- python/pyproject.toml python/agent_framework_meta/ python/README.md \
2>/dev/null | grep -v '^#x27; | sort -u
What "touched" means for bump purposes (apply judgment, document in commit message):
Change scope under python/packages/<pkg>/ | Drives a bump? |
|---|---|
Source code under <pkg>/agent_framework_* or the package's library tree | Yes — ship-affecting |
pyproject.toml (deps, classifiers, extras, version metadata) | Yes — publishes new metadata |
README.md substantive changes (env vars, install instructions, usage) | Yes — user-facing |
README.md typo/wording-only | Judgment — usually no, but record under ### Changed if you do bump |
Tests only (tests/) | Usually no — test changes don't ship to PyPI consumers. Bump only if the test change reflects a real behavior change in the package |
| Package-local samples (alpha packages only, before promotion) | Yes for alpha; samples ship with the alpha package |
| Repo infra touching the package dir (CI config, lint config) | No — record under - **tests**:, - **samples**:, or - **docs**: instead |
Root agent-framework is touched when python/pyproject.toml, python/agent_framework_meta/, or root README.md substantive content changed.
Individual feature/fix PRs intentionally do not add CHANGELOG entries. During release preparation, derive this section centrally from the merged PRs since the last released tag.
Locate ## [Unreleased] and the top existing release header. INSERT a new section between them.
New section structure:
## [<release-label>] - YYYY-MM-DD
### Added
- **agent-framework-<pkg>**: <subject> ([#NNNN](https://github.com/microsoft/agent-framework/pull/NNNN))
### Changed
- **agent-framework-<pkg>**: ...
### Fixed
- **agent-framework-<pkg>**: ...
<release-label> is the released-tier target if any released package is bumping (e.g. 1.7.0), or the date stamp (e.g. 1.0.0b260528) if the release is prerelease-only. Reflect the user's framing.
Categorization heuristics (read commit subject + PR title/body):
feat(...), new re-exports from agent_framework, new capabilities surfaced from underlying SDKsfix(...), bug/crash/regression repairs, noise reduction (e.g. stop emitting spurious warnings), protocol-compliance fixes[BREAKING] prefix if breaking)Entry format:
- **agent-framework-<pkg>**: <subject, grammar-normalized> ([#NNNN](https://github.com/microsoft/agent-framework/pull/NNNN))- **agent-framework-core**, **agent-framework-foundry**: ...- **agent-framework**: ...- **tests**: ..., - **samples**: ..., - **docs**: ... (these do not drive package bumps)Once entries are drafted, the set of **agent-framework-<pkg>** and root **agent-framework** mentions IS the bump list. Anything not mentioned does not bump.
Before moving on, prove that every ship-affecting touched package has at least one CHANGELOG entry. A package whose code changed but is missing from CHANGELOG will NOT bump — and the fix will not ship to PyPI consumers.
# 1. Touched ship-affecting packages and root package files (from step 3a)
TOUCHED_PACKAGES=$(git log --name-only --format='' ${LAST_RELEASED_TAG}..${RELEASE_BASE} -- python/packages/ \
| grep '^python/packages/' \
| sed 's|^python/packages/||' \
| awk -F/ '{print $1}' \
| sort -u)
ROOT_TOUCHED=$(git log --name-only --format='' ${LAST_RELEASED_TAG}..${RELEASE_BASE} \
-- python/pyproject.toml python/agent_framework_meta/ python/README.md \
2>/dev/null | grep -v '^#x27; | sort -u)
TOUCHED=$(
{
if [ -n "$TOUCHED_PACKAGES" ]; then echo "$TOUCHED_PACKAGES"; fi
if [ -n "$ROOT_TOUCHED" ]; then echo "agent-framework"; fi
} | sort -u
)
# 2. Packages mentioned in the new CHANGELOG section
# (Extract from the section you just drafted — adjust the awk range to the new section's bounds)
MENTIONED=$(awk '
/^## \[<release-label>\]/ { in_section=1; next }
in_section && /^## \[/ { exit }
in_section { print }
' python/CHANGELOG.md \
| grep -oE '\*\*agent-framework(-[a-z0-9_-]+)?\*\*' \
| sed 's/\*\*//g;s/^agent-framework-//' \
| sort -u)
# 3. Diff — anything in TOUCHED but missing from MENTIONED is a gap
comm -23 <(echo "$TOUCHED") <(echo "$MENTIONED")
For every gap, decide explicitly with the user:
### Changed.Package-name aliasing to watch for: directory foundry_local → package agent-framework-foundry-local; github_copilot → agent-framework-github-copilot; azure-ai-search → agent-framework-azure-ai-search. The directory name and the published PyPI name are not always identical — confirm both when reconciling.
Footer reference links (REQUIRED every release):
grep -n "^\[.*\]:" python/CHANGELOG.md | head -5
Two edits when a released-tier bump is in play:
[Unreleased] compare base from python-${OLD_RELEASED}...HEAD to python-${NEW_RELEASED}...HEAD.[${NEW_RELEASED}] line ABOVE the previous version's link: [${NEW_RELEASED}]: https://github.com/microsoft/agent-framework/compare/python-${OLD_RELEASED}...python-${NEW_RELEASED}For prerelease-only releases (no released-tier bump this cycle), footer links don't change.
For each package in the bump list, choose the rule for its current tier. Use anchored sed (^version = "..."$) so only the project's own version matches. Use sed -i.bak plus backup cleanup for portable in-place edits across macOS/BSD sed and GNU sed.
Released tier (per-package semver):
# Example: openai goes 1.6.0 -> 1.6.1 (PATCH); core stays
sed -i.bak 's/^version = "1.6.0"$/version = "1.6.1"/' python/packages/openai/pyproject.toml
rm python/packages/openai/pyproject.toml.bak
Root agent-framework (only when core bumps, OR for its own changes):
sed -i.bak "s/^version = \"${OLD_ROOT}\"$/version = \"${NEW_ROOT}\"/" python/pyproject.toml
# AND keep the exact pin in sync with core
sed -i.bak "s/agent-framework-core\\[all\\]==${OLD_CORE}/agent-framework-core[all]==${NEW_CORE}/" python/pyproject.toml
rm python/pyproject.toml.bak
RC tier (counter increment):
# ag-ui goes 1.0.0rc3 -> 1.0.0rc4 only because it has a CHANGELOG entry
sed -i.bak 's/^version = "1.0.0rc3"$/version = "1.0.0rc4"/' python/packages/ag-ui/pyproject.toml
rm python/packages/ag-ui/pyproject.toml.bak
Alpha/Beta tier (new date stamp):
OLD_DATE=260521
NEW_DATE=260528
# Only the packages with CHANGELOG entries get the new stamp.
# Example: anthropic and bedrock had entries, others did not.
for pkg in anthropic bedrock; do
file="python/packages/$pkg/pyproject.toml"
sed -i.bak "s/1\\.0\\.0b${OLD_DATE}/1.0.0b${NEW_DATE}/g" "$file"
rm "${file}.bak"
done
If the user opts into a cohort-wide beta bump regardless of per-package changes, enumerate every beta package from PACKAGE_STATUS.md and stamp all of them. State that this is a cohort bump in the commit message.
Spot-check with grep '^version' python/pyproject.toml python/packages/*/pyproject.toml | sort before moving on.
core[all] release cohortWhen Core bumps, update every Agent Framework dependency in
python/packages/core/pyproject.toml [project.optional-dependencies].all:
These bounds prevent pip from backtracking across old cyclic core[all] -> integration -> core combinations. The
release validator rejects missing, stale, or unbounded cohort entries.
agent-framework-coreOnly relevant when core itself bumped this cycle. Two policies, pick one explicitly with the user:
agent-framework-core>=X.Y.Z to the new core version on every non-core package that is ALSO bumping this cycle. Leaves packages-not-bumped at their existing floor.When raising a core floor, replace only the >=OLD half of the bound you intend to change:
file="python/packages/<pkg>/pyproject.toml"
sed -i.bak "s/agent-framework-core>=${OLD_CORE}/agent-framework-core>=${NEW_CORE}/" "$file"
rm "${file}.bak"
If core did not bump this cycle, do not touch floors.
cd python && uv run poe validate-python-release --base-ref "$RELEASE_BASE"
Use the same freshly fetched main ref that the release branch was based on (upstream/main above; use origin/main
when that is the authoritative release base). Must exit 0. This task first regenerates uv.lock, then discovers the
package pyproject.toml files changed from that base and runs their published runtime dependencies and
non-development extras through lock-independent lowest-direct and highest import probes. The probes run in
parallel, derive the minimum supported Python minor from each package's internal editable closure, and share a hard
300-second deadline. Use --python only when the release requires an explicit interpreter override.
This is the release safety net for selective bumping: the lower probe catches unresolvable or unimportable external floors, internal constraints that reject co-released package versions, and the upper probe catches caps that exclude an installable package set. The JSON report records the concrete versions resolved in both scenarios. It does not replace the package-by-package code inspection required by the strict core-floor policy. If it fails, fix the named package/bound and re-run before committing.
Do not substitute the workspace-wide validate-dependency-bounds-test command here. That command runs every
package's full tests and Pyright in separate isolated environments and is intentionally reserved for CI or an
explicit dependency-range audit. If the release itself changes an external dependency range, also run
validate-dependency-bounds-project --mode both --package <pkg> --dependency <name> for that dependency.
If only prereleases changed (no core bump, no floor changes), release validation is still required because the
lockfile and both ends of each changed package's published dependency metadata must remain installable.
The project's pre-commit hook runs poe check / poe typing / uv lock and may re-modify uv.lock on first commit attempt. Expected pattern — run twice:
git add -u
git commit -m "<message>" # may fail with "files were modified by this hook"
git add -u # re-stage hook-generated changes
git commit -m "<message>" # succeeds
Commit message format — HEREDOC, no Co-Authored-By:
git commit -m "$(cat <<'EOF'
Bump Python package versions for <release-label> release
<One paragraph explaining:
- which packages bumped and why (CHANGELOG-driven)
- semver rationale for any released-tier bumps
- whether a beta cohort bump was applied
- whether core floors were raised, and under which policy>
EOF
)"
git push origin bump-py-ver-release-YYMMDD
The push output includes a Create a pull request for '<branch>' on GitHub by visiting: <URL> line — surface that to the user.
LAST_RELEASED_TAG fresh — do NOT reuse the previous compare base. Symptom: dragging already-shipped PRs into the new CHANGELOG section.python/packages/foo/ but the new CHANGELOG section has no **agent-framework-foo**: line, then foo will NOT bump, and the fix sits in main but never reaches PyPI. Always run the touched-vs-mentioned reconciliation in step 4a before applying bumps.foundry_local → agent-framework-foundry-local). When reconciling touched dirs against CHANGELOG mentions, normalize on the PyPI form.agent-framework has agent-framework-core[all]==EXACT_VERSION. If core bumps and root does not, the pin is broken. Always bump them together and update the pin string.## [X.Y.Z] header to a new label — that wipes the historical section. Always INSERT a new section above.[Unreleased] line and the new [X.Y.Z] link at the bottom MUST be updated. Heading links don't resolve without them.[X.Y.Z] line compares from the PREVIOUS released tag, not from two releases ago.python-package-management date-stamp rule;
do not infer a local timezone from the user's current shell.Co-Authored-By trailer. Never add it. Rewrite/amend if it slipped in.python/PACKAGE_STATUS.md for the live tier map. Do not trust a hardcoded list.upstream/main consistently for branch creation, changeset discovery, and release validation. A stale origin/main must never become the implicit compare base.--pre README cleanup on promotion. When a package is promoted to released in this cycle, grep for pip install agent-framework-<pkg> --pre in READMEs and drop the --pre flag.1.0.0rcN without a CHANGELOG entry for that package. The counter tracks iterations, not calendar.python/.github/skills/python-package-management/SKILL.mdpython/PACKAGE_STATUS.mdpython/scripts/dependencies/validate_dependency_bounds.py --mode release (changed-package,
lock-independent lowest-direct and highest import probes under a five-minute deadline)python/pyproject.toml [tool.poe.tasks]