Lock File Specification
- Version
- 0.1 (Working Draft)
- Date
- 2026-03-09
- Editors
- Daniel Meppiel (Microsoft)
- Repository
- https://github.com/microsoft/apm
- Format
- YAML 1.2
Status of This Document
Section titled “Status of This Document”This is a Working Draft. The lock file format is stable at version "1" and
breaking changes will be gated behind a lockfile_version bump.
Abstract
Section titled “Abstract”apm.lock records the exact resolved state of every dependency in an APM
project. It is the receipt of what was installed — commit SHAs, source URLs,
and every file deployed into the workspace. Its role is analogous to
package-lock.json (npm) or .terraform.lock.hcl (Terraform): given the same
lock file, APM MUST reproduce the same file tree.
1. Conformance
Section titled “1. Conformance”The key words “MUST”, “MUST NOT”, “SHOULD”, “SHOULD NOT”, and “MAY” in this document are to be interpreted as described in RFC 2119.
2. Purpose
Section titled “2. Purpose”The lock file serves four goals:
- Reproducibility — the same lock file yields the same deployed files on every machine, every time.
- Provenance — every dependency is traceable to an exact source commit.
- Completeness —
deployed_fileslists every file APM placed in the project, enabling precise removal. - Auditability —
git log apm.lockprovides a full history of dependency changes across the lifetime of the project.
3. Lifecycle
Section titled “3. Lifecycle”apm.lock is created and updated at well-defined points:
| Event | Effect on apm.lock |
|---|---|
apm install (first run) | Created. All dependencies resolved, commits pinned, files recorded. |
apm install (subsequent) | Read. Locked commits reused. New dependencies appended. |
apm install --update | Re-resolved. All refs re-resolved to latest matching commits. |
apm deps update | Re-resolved. Refreshes versions for specified or all dependencies. |
apm pack | Enriched. A pack: section is prepended to the bundled copy (see section 6). |
apm uninstall | Updated. Removed dependency entries and their deployed_files references. |
The lock file SHOULD be committed to version control. It MUST NOT be manually edited — APM is the sole writer.
4. Document Structure
Section titled “4. Document Structure”A conforming lock file MUST be a YAML 1.2 document with the following top-level structure:
lockfile_version: "1"generated_at: "2026-03-09T14:00:00Z"apm_version: "0.7.7"
dependencies: - repo_url: https://github.com/acme-corp/security-baseline resolved_commit: a1b2c3d4e5f6789012345678901234567890abcd resolved_ref: v2.1.0 version: "2.1.0" depth: 1 package_type: apm_package deployed_files: - .github/instructions/security.instructions.md - .github/agents/security-auditor.agent.md
- repo_url: https://github.com/acme-corp/common-prompts resolved_commit: f6e5d4c3b2a1098765432109876543210fedcba9 resolved_ref: main depth: 2 resolved_by: https://github.com/acme-corp/security-baseline package_type: apm_package deployed_files: - .github/instructions/common-guidelines.instructions.md4.1 Top-Level Fields
Section titled “4.1 Top-Level Fields”| Field | Type | Required | Description |
|---|---|---|---|
lockfile_version | string | MUST | Lock file format version. Currently "1". |
generated_at | string (ISO 8601) | MUST | UTC timestamp of when the lock file was last written. |
apm_version | string | MUST | Version of APM that generated this lock file. |
dependencies | array | MUST | Ordered list of resolved dependencies (see section 4.2). |
mcp_servers | array | MAY | List of MCP server identifiers registered by installed packages. |
4.2 Dependency Entries
Section titled “4.2 Dependency Entries”The dependencies list MUST be sorted by depth (ascending), then by
repo_url (lexicographic). Each entry is a YAML mapping with the following
fields:
| Field | Type | Required | Description |
|---|---|---|---|
repo_url | string | MUST | Source repository URL. |
host | string | MAY | Git host identifier (e.g., github.com). Omitted when inferrable from repo_url. |
resolved_commit | string | MUST | Full 40-character commit SHA that was checked out. |
resolved_ref | string | MUST | Git ref (tag, branch, SHA) that resolved to resolved_commit. |
version | string | MAY | Semantic version of the package, if declared in its manifest. |
virtual_path | string | MAY | Sub-path within the repository for virtual (monorepo) packages. |
is_virtual | boolean | MAY | true if the package is a virtual sub-package. Omitted when false. |
depth | integer | MUST | Dependency depth. 1 = direct dependency, 2+ = transitive. |
resolved_by | string | MAY | repo_url of the parent that introduced this transitive dependency. Present only when depth >= 2. |
package_type | string | MUST | Package type: apm_package, plugin, virtual, or other registered types. |
deployed_files | array of strings | MUST | Every file path APM deployed for this dependency, relative to project root. |
Fields with empty or default values (empty strings, false booleans, empty
lists) SHOULD be omitted from the serialized output to keep the file concise.
4.3 Unique Key
Section titled “4.3 Unique Key”Each dependency is uniquely identified by its repo_url, or by the
combination of repo_url and virtual_path for virtual packages. A
conforming lock file MUST NOT contain duplicate entries for the same key.
5. Path Conventions
Section titled “5. Path Conventions”All paths in deployed_files MUST use forward slashes (POSIX format),
regardless of the host operating system. Paths are relative to the project
root directory.
# Correctdeployed_files: - .github/instructions/security.instructions.md - .github/agents/code-review.agent.md
# Incorrect — backslashes are not permitteddeployed_files: - .github\instructions\security.instructions.mdThis convention ensures lock files are portable across operating systems and produce consistent diffs in version control.
6. Pack Enrichment
Section titled “6. Pack Enrichment”When apm pack creates a bundle, it prepends a pack: section to the lock
file copy included in the bundle. This section is informational and is not
written back to the project’s apm.lock.
pack: format: apm target: vscode packed_at: "2026-03-09T14:30:00Z"
lockfile_version: "1"generated_at: "2026-03-09T14:00:00Z"# ... rest of lock file6.1 Pack Fields
Section titled “6.1 Pack Fields”| Field | Type | Description |
|---|---|---|
pack.format | string | Bundle format: "apm" or "plugin". |
pack.target | string | Target environment: "vscode", "claude", or "all". |
pack.packed_at | string (ISO 8601) | UTC timestamp of when the bundle was created. |
The original lock file is not mutated. The enriched copy exists only inside the packed archive.
7. Resolver Behaviour
Section titled “7. Resolver Behaviour”The dependency resolver interacts with the lock file as follows:
- First install — resolve all refs to commits, write
apm.lock. - Subsequent installs — read
apm.lock, reuse locked commits. Only newly added dependencies trigger resolution. - Update (
--updateflag orapm deps update) — re-resolve all refs, overwrite the lock file with fresh commits.
When a locked commit is no longer reachable (force-pushed branch, deleted tag), APM MUST report an error and refuse to install until the lock file is updated.
8. Migration
Section titled “8. Migration”The lock file reader supports one historical migration:
deployed_skills— renamed todeployed_files. If a lock file contains the legacy key, it is silently migrated on read. New lock files MUST usedeployed_files.
9. Auditing Patterns
Section titled “9. Auditing Patterns”Because apm.lock is committed to version control, standard Git operations
provide a complete audit trail:
# Full history of dependency changesgit log --oneline apm.lock
# What changed in the last commitgit diff HEAD~1 -- apm.lock
# State of dependencies at a specific releasegit show v4.2.1:apm.lock
# Who last modified the lock filegit log -1 --format='%an <%ae> %ai' -- apm.lockIn CI pipelines, apm audit --ci verifies the lock file is in sync with the
manifest and that all deployed files are present.
10. Example: Complete Lock File
Section titled “10. Example: Complete Lock File”lockfile_version: "1"generated_at: "2026-03-09T14:00:00Z"apm_version: "0.7.7"
dependencies: - repo_url: https://github.com/acme-corp/security-baseline resolved_commit: a1b2c3d4e5f6789012345678901234567890abcd resolved_ref: v2.1.0 version: "2.1.0" depth: 1 package_type: apm_package deployed_files: - .github/instructions/security.instructions.md - .github/agents/security-auditor.agent.md - .github/agents/threat-model.agent.md
- repo_url: https://github.com/acme-corp/common-prompts resolved_commit: f6e5d4c3b2a1098765432109876543210fedcba9 resolved_ref: main depth: 2 resolved_by: https://github.com/acme-corp/security-baseline package_type: apm_package deployed_files: - .github/instructions/common-guidelines.instructions.md
- repo_url: https://github.com/example-org/monorepo-tools host: github.com resolved_commit: 0123456789abcdef0123456789abcdef01234567 resolved_ref: v1.0.0 version: "1.0.0" virtual_path: packages/linter-config is_virtual: true depth: 1 package_type: virtual deployed_files: - .github/instructions/linter.instructions.md
mcp_servers: - security-scannerAppendix A: Revision History
Section titled “Appendix A: Revision History”| Version | Date | Changes |
|---|---|---|
| 0.1 | 2026-03-09 | Initial working draft. |