Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
499d233
fix(yaml_io): line-1 check for YAML frontmatter to prevent misinterpr…
manideep-malyala Aug 22, 2026
2b9a4e5
fix(yaml_io): address PR review comments (explicit line-1 fence check…
manideep-malyala Aug 22, 2026
2df7154
fix: align frontmatter fence detection
danielmeppiel Aug 23, 2026
778e5ea
test: patch frontmatter at consumer boundaries
danielmeppiel Aug 23, 2026
32046c9
test: guard frontmatter parser authority
danielmeppiel Aug 23, 2026
1f7555c
test: harden frontmatter authority boundary
danielmeppiel Aug 23, 2026
f15b592
chore: refresh architecture instruction hash
danielmeppiel Aug 23, 2026
8d04fe9
fix: centralize instruction frontmatter conversion
danielmeppiel Aug 23, 2026
18cb425
chore: document internal parser consolidation
danielmeppiel Aug 23, 2026
afd4a77
fix: fail closed in instruction conversion
danielmeppiel Aug 23, 2026
7234e26
fix: make instruction rejection atomic
danielmeppiel Aug 23, 2026
e850682
fix: preflight instructions across targets
danielmeppiel Aug 23, 2026
5dbe09f
fix: reject invalid instructions before package writes
danielmeppiel Aug 23, 2026
11d0c93
docs: distinguish invalid fenced frontmatter
danielmeppiel Aug 23, 2026
60a3524
chore: preserve lint after rebase
danielmeppiel Aug 25, 2026
9c57a93
fix: make instruction preflight authoritative
danielmeppiel Sep 2, 2026
235f877
Merge origin/main into fix/frontmatter-horizontal-rule-parsing
danielmeppiel Sep 2, 2026
0ef22f1
test: bind frontmatter owner rule to repository
danielmeppiel Sep 2, 2026
2e14577
fix: preserve BOM detection after convergence
danielmeppiel Sep 2, 2026
e2fcc88
fix: close prepared instruction bypasses
danielmeppiel Sep 2, 2026
33dd3c9
refactor: extract target path summary formatting
danielmeppiel Sep 2, 2026
2ce504c
docs: keep frontmatter release notes current
danielmeppiel Sep 2, 2026
ba16a65
fix: scan decoded surrogate pairs before deployment
danielmeppiel Sep 2, 2026
d44e837
perf: skip surrogate rebuilding on common text
danielmeppiel Sep 2, 2026
801b736
fix: make decoded frontmatter recovery actionable
danielmeppiel Sep 2, 2026
cf0cdf5
fix: surface decoded frontmatter recovery guidance
danielmeppiel Sep 2, 2026
9256b62
fix: preflight before target reconciliation writes
danielmeppiel Sep 2, 2026
ae0359a
test: prove failed updates preserve hook state
danielmeppiel Sep 2, 2026
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
4 changes: 2 additions & 2 deletions .apm/architecture/owners/contracts-tooling.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
},
{
"id": "frontmatter-bom-bounded-yaml",
"decision": "Frontmatter BOM decoding and bounded YAML parsing",
"owner": "utils/yaml_io.py (load_frontmatter, _BoundedYAMLHandler)",
"decision": "Frontmatter delimiter detection, BOM decoding, and bounded YAML parsing",
"owner": "utils/yaml_io.py (load_frontmatter, loads_frontmatter, _BoundedYAMLHandler)",
"selectors": ["src/apm_cli/utils/yaml_io.py"],
"guards": ["contracts-tooling-frontmatter-yaml"]
},
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- `apm install` no longer silently drops instruction Markdown whose
unfenced bodies contain `---` horizontal rules. It now stops the whole package
before deploying any primitive when instruction frontmatter is invalid YAML or
decodes critical hidden characters. `--force` overrides only the critical
character finding, never malformed YAML; warning-level findings do not block.
(by @manideep-malyala, #2666)
- `apm pack` now reports unavailable remote package metadata, exposes
certifiability in JSON, prevents `--check-clean` from certifying degraded
regeneration, and lets `--strict-metadata` fail before writes. (closes #2524)
Expand Down
7 changes: 4 additions & 3 deletions docs/src/content/docs/producer/author-primitives/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ See the [targets matrix](../../reference/targets-matrix/) for the full map.

Commands ship as prompts (`.apm/prompts/*.prompt.md`); there is no separate `.apm/commands/` directory. See [Hooks and commands](./hooks-and-commands/).

Every primitive type follows the same pattern: a markdown file (or directory containing a primary markdown file) with frontmatter declaring its name and its trigger conditions. `apm compile` reads `.apm/`, applies any policy, and writes per-target output to the right directories on the target's filesystem.
Markdown-based primitive types use a markdown file (or directory containing a primary markdown file). Frontmatter requirements vary by primitive type and declare metadata such as the primitive's name and trigger conditions. `apm compile` reads `.apm/`, applies any policy, and writes per-target output to the right directories on the target's filesystem.

Encode primitive Markdown as UTF-8. APM accepts files with or without a
leading UTF-8 BOM and strips the BOM before parsing frontmatter.
:::note[Frontmatter fence]
Encode primitive Markdown as UTF-8. When a Markdown primitive has frontmatter, its opening fence of at least three hyphens (for example, `---`) must be the first content on line 1; an optional UTF-8 BOM may precede it and is stripped before parsing. Without that opening fence, APM treats the document as body content and later `---` lines remain Markdown horizontal rules. Malformed instruction frontmatter stops the package before deployment. Critical hidden characters decoded from metadata also prevent installation by default; `--force` overrides only that critical finding, while warning-level findings do not prevent installation. See [`apm install`](../../reference/cli/install/#behavior).
:::

## Recommended reading order

Expand Down
6 changes: 6 additions & 0 deletions docs/src/content/docs/reference/cli/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ in `apm.yml`, then run `apm install` again.
replacements to isolated staging paths and validate them before publication.
If download, validation, or activation fails, APM keeps the previous package
and lockfile active and exits non-zero with retry guidance.
- **Instruction frontmatter preflight.** Malformed YAML always rejects the
package before any of its primitives are deployed. Critical hidden characters
decoded from metadata also prevent installation by default; `--force`
overrides only that critical finding. Warning-level findings do not prevent
installation. See [Author primitives](../../../producer/author-primitives/)
for fence and UTF-8 BOM syntax.
- **MCP-only lock state.** A normal project install creates or updates `apm.lock.yaml` when `apm.yml` declares only MCP dependencies, records the resolved MCP configs and targets, and migrates a legacy `apm.lock` first. Repeating the same install leaves the lockfile and target configs byte-identical. If initial lock creation fails, install exits nonzero and warns with writable-directory and rerun guidance.
- **Lockfile replay and Git ref freshness.** Plain and `--frozen` installs may trust `apm.lock.yaml` and the local Git cache, reusing the locked commit for unchanged Git dependencies across the full resolved graph. In contrast, `apm install --update`, `apm install --refresh`, [`apm update`](../update/) with or without `--force`, [`apm lock --update`](../lock/), and [`apm outdated`](../outdated/) establish mutable Git refs from upstream instead of accepting stale refs from a local bare Git cache. APM picks up upstream changes to a transitive package's `apm.yml` only when you regenerate the graph -- run `apm update` or `apm lock --update`. See the [lockfile specification](../../lockfile-spec/) for the replay contract.
- **Semver ranges on git deps.** `ref:` accepts semver ranges (`^1.2.0`, `~1.4`, `>=2.0 <3`, `1.5.x`) for git-source deps, including positional virtual-subdirectory references. APM runs `git ls-remote` against the dep, picks the highest tag matching the range, and pins the resolved tag plus commit SHA, version, and original constraint in `apm.lock.yaml`. Subsequent installs replay the lockfile without network; use `--update` (or change the manifest constraint) to re-resolve. See [manage dependencies](../../../consumer/manage-dependencies/#pin-a-semver-range) for the supported syntax.
Expand Down
12 changes: 10 additions & 2 deletions packages/apm-guide/.apm/skills/apm-usage/package-authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,16 @@ correctly -- the component just records NOASSERTION (genuinely unknown).
This warning fires only on the **authoring** path (your own `apm.yml`);
installing or exporting other people's dependencies is silent.

Encode primitive Markdown as UTF-8. APM accepts files with or without a
leading UTF-8 BOM and strips the BOM before parsing frontmatter.
Encode primitive Markdown as UTF-8. Frontmatter requirements vary by Markdown
primitive type. When frontmatter is present, its opening fence of at least
three hyphens (for example, `---`) must be the first content on line 1; an
optional UTF-8 BOM may precede it and is stripped before parsing. Without that
opening fence, APM treats the whole document as body content, and later `---`
lines stay Markdown horizontal rules. Malformed instruction frontmatter stops
the package before any primitive is deployed. Critical hidden characters
decoded from metadata also prevent installation by default; `--force`
overrides only that critical finding, while warning-level findings do not
prevent installation.

## The 7 primitive types

Expand Down
Loading