feat(kiro): deploy agents primitive to .kiro/agents/ (#2089) - #2440
Conversation
Add Kiro IDE/CLI v3 agent compilation support. APM now deploys agent files from .apm/agents/ to .kiro/agents/<relative-stem>.md when a .kiro/ project directory is present. Key design decisions: - Identity derives from relative path (name field stripped from output) - Only description, model, and tools frontmatter are emitted - Unknown frontmatter fields are silently omitted - tools is permission-bearing: fail closed (no write) if any value is outside the approved Kiro capability set (read, write, shell, web, subagent, knowledge, context, todo_list, @mcp, @Builtin, *) - Nested .apm/agents/subdir/agent.agent.md deploys to .kiro/agents/subdir/agent.md preserving path-based identity - model is passed through opaquely without validation (Kiro may warn if the model is unavailable but APM does not gate on it) Implementation: - Add KIRO_AGENT_ALLOWED_TOOLS constant to agent_integrator.py - Add _kiro_agent_relpath() static method for nested path handling - Add _write_kiro_agent() static method (frontmatter filter + tools gate) - Update integrate_agents_for_target() dispatch for kiro_agent format_id - Add agents PrimitiveMapping to KNOWN_TARGETS["kiro"] in targets.py - Update test_partition_parity_with_old_buckets to include agents_kiro - Add 13 new acceptance tests to test_kiro_target.py covering all required lifecycle scenarios (deploy, nested identity, frontmatter preservation, fail-closed tools, idempotency, update, cleanup, coexistence, skip-when-no-kiro-dir) - Add kiro-agent-project row to primitive_target_covering_array Docs updated: - instructions-and-agents.md: Kiro row in What-compiles-where table - ide-tool-integration.md: Kiro section updated with agents - targets-matrix.md: kiro agents column and section updated - package-authoring.md: Kiro tools constraint documented Official sources (accessed 2026-08-03): - https://kiro.dev/docs/custom-agents/ - https://kiro.dev/docs/cli/v3/ - https://kiro.dev/docs/cli/v3/agent-config/ Closes #2089 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9c7e3f39-dd3e-4fc6-bc4e-c64ffeaf1685
There was a problem hiding this comment.
Pull request overview
Adds first-class Kiro support for the agents primitive by deploying .apm/agents/**/*.agent.md to .kiro/agents/<relative-stem>.md, applying a Kiro-specific frontmatter transform and enforcing a fail-closed tools allowlist to avoid deploying agents with unsupported (permission-bearing) capability tags.
Changes:
- Extend the Kiro target profile to include
agentsand route agent integration through a newkiro_agentformat transformer. - Implement Kiro agent path derivation (preserve nested identity) + frontmatter filtering + allowed-tools gate in
AgentIntegrator. - Add unit/integration coverage and update docs + changelog to reflect Kiro agents support.
Show a summary per file
| File | Description |
|---|---|
src/apm_cli/integration/targets.py |
Adds agents primitive mapping for the kiro target profile. |
src/apm_cli/integration/agent_integrator.py |
Implements Kiro agent relpath derivation + filtered frontmatter output + tools allowlist gate; wires kiro_agent into agent integration dispatch. |
tests/unit/integration/test_kiro_target.py |
Adds Kiro agents acceptance tests (deploy, nested paths, tools gate, idempotency, cleanup). |
tests/unit/integration/test_data_driven_dispatch.py |
Extends dispatch exhaustiveness expectations for agents_kiro. |
tests/integration/test_primitive_target_covering_array.py |
Adds covering-array row for kiro + agents. |
packages/apm-guide/.apm/skills/apm-usage/package-authoring.md |
Documents Kiro agents frontmatter forwarding and the tools allowlist/fail-closed behavior. |
docs/src/content/docs/reference/targets-matrix.md |
Updates Kiro capabilities matrix and adds Kiro agents behavior details. |
docs/src/content/docs/producer/author-primitives/instructions-and-agents.md |
Updates primitive behavior descriptions/table to include Kiro agent deployment + constraints. |
docs/src/content/docs/integrations/ide-tool-integration.md |
Updates Kiro integration summary to include Agents + constraints. |
CHANGELOG.md |
Adds Unreleased entry for Kiro agents support. |
Review details
Suppressed comments (1)
tests/unit/integration/test_kiro_target.py:576
- These tests reach into
DiagnosticCollector._diagnostics(a private attribute). Prefer the publicby_category()helper.
errors = [d for d in diagnostics._diagnostics if d.category == "error"]
assert not errors
- Files reviewed: 10/10 changed files
- Comments generated: 4
- Review effort level: Lite
| elif mapping.format_id == "kiro_agent": | ||
| ok = self._write_kiro_agent( | ||
| source_file, | ||
| target_path, | ||
| diagnostics=diagnostics, | ||
| package_name=package_info.package.name, | ||
| ) | ||
| if not ok: | ||
| files_skipped += 1 | ||
| continue | ||
| links_resolved = 0 |
| elif isinstance(tools_raw, list): | ||
| tools_strs = [str(t).strip() for t in tools_raw] | ||
| incompatible = set(tools_strs) - KIRO_AGENT_ALLOWED_TOOLS | ||
| if incompatible: | ||
| if diagnostics is not None: | ||
| names = ", ".join(sorted(incompatible)) | ||
| diagnostics.error( | ||
| message=( | ||
| f"Kiro agent {printable_ascii_text(source.name)}: " | ||
| f"unsupported tool(s) {names!a} -- " | ||
| "agent will not be deployed. " | ||
| "Remove or replace with Kiro-approved capability " | ||
| "tags (read, write, shell, web, subagent, knowledge, " | ||
| "context, todo_list, @mcp, @builtin, *). " | ||
| "Ref: https://kiro.dev/docs/custom-agents/" | ||
| ), | ||
| package=printable_ascii_text(package_name), | ||
| ) | ||
| return False | ||
| tools_out = tools_raw |
| - Kiro IDE/CLI v3 now receives agents from `.apm/agents/` as Markdown files | ||
| under `.kiro/agents/<relative-stem>.md`. Agent identity derives from the | ||
| deployed path. Only `description`, `model`, and `tools` frontmatter fields | ||
| are emitted; `name` and unknown fields are stripped. Tools are | ||
| permission-bearing: APM fails closed (no partial write) if any tool value is | ||
| outside the approved Kiro capability set (`read`, `write`, `shell`, `web`, | ||
| `subagent`, `knowledge`, `context`, `todo_list`, `@mcp`, `@builtin`, `*`). | ||
| Nested source paths under `.apm/agents/` are preserved, and the targets | ||
| matrix is updated to reflect the new `agents` primitive for `kiro`. | ||
| (ref: [kiro.dev/docs/custom-agents/](https://kiro.dev/docs/custom-agents/), | ||
| [kiro.dev/docs/cli/v3/](https://kiro.dev/docs/cli/v3/), accessed 2026-08-03. | ||
| #2089) |
…2089) Corrective wave for issue #2089 acceptance blockers: 1. Permission gate hardening (req-tg-009): - Extract _preflight_render_kiro_agent() as the single owner of kiro render+validate. This runs BEFORE any adopt/collision check or filesystem mutation, closing the adopt-bypass flaw where a byte-identical source with invalid tools could be silently adopted. - Lazy agents_dir.mkdir(): directory is created only when a write actually proceeds, so an all-invalid-tools package does not leave an empty .kiro/agents/ tree. - _write_kiro_agent() now delegates to _preflight_render_kiro_agent (single owner; belt-and-suspenders call site). - Adopt comparison for kiro_agent uses rendered content (not source bytes) so pre-placed invalid-tools targets cannot be laundered. 2. Spec conformance (Mode B, req-tg-009): - Add req-tg-009 to spec Section 8.5.1 (after req-tg-006): fail-closed evaluation must precede content-identity adoption. - Add manifest row (keyword: MUST, section: 8.5.1, consumer). - Add Appendix C traceability row. - Add @pytest.mark.req('req-tg-009') conformance test asserting the adopt-bypass regression case. - Regenerate CONFORMANCE.{md,json}. 3. Integration lifecycle tests: - Add tests/integration/test_kiro_agent_lifecycle.py (markers: integration, e2e, requires_e2e_mode, requires_apm_binary). - Covers via ApmLifecycleRunner + real CLI binary: compatible deploy, nested path identity, idempotency, stale removal, coexistence with steering/hooks, incompatible-tools fail-closed (no partial write, diagnostic names unsupported tool). 4. Unit regression tests (adopt-bypass): - test_kiro_agents_preflight_before_adopt_bypass: pre-seeds a byte-identical target with invalid tools; verifies adopt is skipped and error diagnostic fires. - test_kiro_agents_no_agents_dir_created_for_all_invalid: proves .kiro/agents/ is NOT created when every agent is invalid. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9c7e3f39-dd3e-4fc6-bc4e-c64ffeaf1685
…ios (#2089) Wave 3 additions: - test_kiro_agent_update_replacement: commits v1 agent, installs, commits v2 to same repo, updates consumer apm.yml ref, reinstalls -- verifies deployed bytes change from v1-marker to v2-marker (real binary + real git operations). - test_kiro_target_autodetection: consumer apm.yml declares no targets; .kiro/ presence drives autodetection via detect_signals() -> KNOWN_TARGETS['kiro']. detect_by_dir=True; agent deploys without --target flag. Also fixes module docstring to accurately list 7 scenarios. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9c7e3f39-dd3e-4fc6-bc4e-c64ffeaf1685
Docs sync advisoryVerdict: in_place * Pages affected: 1 * LLM calls: 7/15 * Took: ~510s SummaryPR #2440 adds Kiro IDE/CLI v3 agents support and pre-patched three doc pages Proposed patches
|
APM Spec Guardian:
|
| Panel | Verdict | Shocked | New B | New R | New N |
|---|---|---|---|---|---|
| Spec Swagger Editor | ship_with_followups | 3/10 | 0 | 4 | 2 |
| Spec Oci Editor | ship_with_followups | 3/10 | 0 | 3 | 2 |
| Spec Pkgmgr Editor | ship_with_followups | 4/10 | 1 | 4 | 2 |
| Spec Tag Architect | ship_with_followups | 4/10 | 0 | 3 | 2 |
B = new blocking findings, R = new recommended, N = new nits.
Counts are signal strength, not gates. The maintainer ships.
Convergent themes (flagged by 2+ panels)
- T1 -- Count-consistency drift: Section 1.3, Appendix C trailer, and Appendix D revision row all stale at 107 while CONFORMANCE.json reports 108 post-PR (supporting: sw-rec-r1-1, oci-rec-r1-3, pm-rec-r1-2, tag-rec-r1-2)
- T2 -- Missing normative anchor or registry cross-reference for the "approved capability set" / "capability vocabulary" concepts load-bearing in req-tg-009 (supporting: sw-rec-r1-4, oci-rec-r1-1, pm-rec-r1-4, tag-rec-r1-1)
- T3 -- Section-placement mismatch: req-tg-009 (fail-closed vocabulary gate) placed under heading "8.5.1 Lossy agent conversion" which describes a distinct concern (supporting: sw-rec-r1-3, pm-nit-r1-1, pm-nit-r1-2, tag-nit-r1-2, oci-nit-r1-2)
- T4 -- Content-identity adoption fast-path underspecification: "bytes match the source" and symlink/hardlink edge cases not pinned to a resolution context (supporting: pm-rec-r1-3, oci-nit-r1-1)
Fold now (5 item(s))
- [F1 / Blast-radius ambiguity closure (blocker pm-blk-r1-1)] 8.5.1 (req-tg-009) -- Append after "(zero bytes, no partial file)": "This gate is evaluated per agent primitive independently; failure for one agent MUST NOT prevent deployment of other, vocabulary-conformant agent primitives from the same dependency or install operation."
Success criterion:grep confirms the phrase "per agent primitive independently" is present within the req-tg-009 anchor block and a MUST NOT clause explicitly scopes failure to a single agent. - [F2 / Count-consistency reconciliation (T1)] 1.3, Appendix C trailer, Appendix D -- Update Section 1.3 from "107 normative statements" to "108 normative statements". Update the Appendix C trailer from "Total normative statements: 107 (102 MUST, 5 SHOULD)" to "Total normative statements: 108 (103 MUST, 5 SHOULD)". Add an Appendix D row: "0.1.24 | 2026-08-03 | Added [req-tg-009] (Section 8.5.1, consumer MUST): fail-closed agent deployment when source tools fall outside target vocabulary. Statement count: 107 -> 108 (103 MUST, 5 SHOULD)."
Success criterion:All three prose count sites read 108 with breakdown (103 MUST, 5 SHOULD); Appendix D contains a row with revision 0.1.24 referencing req-tg-009 and the 107->108 delta; CONFORMANCE.json total matches. - [F3 / Conformance-class enumeration gap (sw-rec-r1-2)] 8.7, 11.3.2 -- In Section 8.7 Consumer bullet, append ", req-tg-009" after "req-tg-008". In Section 11.3.2 Consumer enumeration list, append the same reference after req-tg-008.
Success criterion:Both Section 8.7 Consumer bullet and Section 11.3.2 Consumer enumeration list include req-tg-009 as the final target-class entry immediately following req-tg-008. - [F4 / Capability-vocabulary registry cross-reference (T2, synthesized from sw-rec-r1-4 + oci-rec-r1-1 + pm-rec-r1-4 + tag-rec-r1-1)] 8.5.1 (editorial note after req-tg-009) -- Append an editorial note after req-tg-009: "Editorial note. The approved capability set for each target is the vocabulary enumerated in the OpenAPM Target Registry companion entry for that target at the spec version the consumer declares conformance to. A conformance test suite MUST pin the exact companion version it validates against. A future revision may promote this pinning to a standalone normative requirement and define a machine-readable vocabulary schema; until then, conformance testing is scoped to the sets published in the companion."
Success criterion:An editorial note following req-tg-009 (a) names the Target Registry companion as the vocabulary authority, (b) mandates version-pinning for conformance testing, and (c) introduces no undefined terms or forward references without explicit deferral language. - [F5 / Composition-order with req-tg-008 (pm-rec-r1-1)] 8.5.1 (req-tg-009) -- Add a sentence to req-tg-009 (before the editorial note): "This evaluation applies only to agents whose target is included in the effective intersection computed under req-tg-008; agents whose target is already excluded by that intersection are not subject to this gate."
Success criterion:req-tg-009 text contains an explicit cross-reference to req-tg-008 establishing it as a precondition; no circular dependency is introduced between the two requirements.
Defer to v0.1.1 (4 items)
- [F6 / Atomicity SHOULD clause for zero-bytes guarantee (oci-rec-r1-2)] 8.5.1 (after req-tg-009 editorial note) -- Add a SHOULD-level clause: "Implementations SHOULD use write-to-temporary-then-atomic-rename to satisfy the zero-bytes guarantee across process interruptions. An implementation that streams directly to the target path MUST remove any partial artifact before returning from the failed operation; this cleanup requirement does not extend to unrecoverable process termination (e.g. SIGKILL)."
- [F7 / Section-heading taxonomy fix (T3)] 8.5.1 -- Introduce a new subsection "8.5.1.1 Fail-closed vocabulary enforcement" to host req-tg-009, its editorial note, and its SHOULD clause separately from req-tg-006. Keep the parent "8.5.1 Lossy agent conversion" heading for req-tg-006.
- [F8 / Terminology table reconciliation (tag-rec-r1-3)] Section 3 (Terminology) -- Add a row to the Section 3 Terminology table: "Target capability vocabulary -- The fixed, finite set of tool or action identifiers a target-native format recognizes. The vocabulary for each spec-registered target is enumerated in the Target Registry companion." Then update req-tg-009 to use this defined term in place of the ad-hoc phrases.
- [F9 / Content-identity adoption-bypass pinning (T4)] 8.5.1 (req-tg-009) -- Replace "an existing on-disk artifact whose bytes match the source" with "an existing on-disk artifact whose bytes are identical to the bytes the implementation would write from the currently-resolved source". Add a note that symlinks and hardlinks MUST be resolved to their target content before byte comparison.
Rejected findings
- sw-nit-r1-1 -- Pre-existing section-attribution inconsistency for req-tg-006 (Appendix C records section "8.5" but requirement lives under "8.5.1"). Not introduced by this PR; out of scope for this editorial-patch review. File as a separate housekeeping issue.
- sw-nit-r1-2 -- Test coverage breadth (4 distinct MUST/MUST NOT clauses vs test_count 1) is a CI/conformance-suite concern, not a spec-text fix. Out of scope for the spec-guardian text panel; route to the conformance-test maintainer.
Linter notes (2 check(s) failed)
- [6] Count consistency: Section 1.3 ("107 normative statements") and the Appendix C trailer ("Total normative statements: 107") were not updated; Appendix D carries no revision row for req-tg-009 (last row still reads "106 -> 107"). Meanwhile the actual anchor count and the generated CONFORMANCE.json/md both report 108. Prose and generated data disagree.
- [11] 8 non-spec
.pyfiles were modified in this PR (agent_integrator.py,targets.py, and 6 test files). This is a combined code+spec PR; consider also runningapm-review-panelfor the code-side changes.
Linter handoff: Wave 5 linter check 6 (count consistency across Section 1.3, Appendix C trailer, and Appendix D) WILL FAIL on the current file state: the prose reads "107 normative statements" while CONFORMANCE.json/md reports 108. After the drafter applies fold items F2 and F3, re-run the full linter suite to confirm reconciliation. Check 5 (anchor uniqueness) should PASS -- req-tg-009 introduces a new unique anchor with no collision against the existing 107 anchors. Check 1 (ASCII-only) should PASS -- the PR does not introduce non-ASCII bytes. Post-fold verification priorities: (1) confirm Appendix D row count matches Appendix C trailer count, (2) confirm Section 8.7 and 11.3.2 Consumer enumerations include req-tg-009, (3) confirm the editorial note after req-tg-009 does not accidentally duplicate the existing editorial note after req-tg-006.
Full per-panel findings
Spec Swagger Editor -- shocked_meter 3/10, confidence high
Summary: req-tg-009 is a well-structured normative requirement with clear conformance conditions and sound RFC 8174 keyword discipline. However, the PR omits four housekeeping updates that prior revisions (0.1.21-0.1.23) consistently maintained: the count sites and the conformance-class enumeration lists. Additionally, the section placement under "Lossy agent conversion" is taxonomically dishonest, and the "approved capability set" discriminator lacks a normative or editorial registry pointer. None of these findings would break a conformant implementation; all are addressable in a follow-up fold without anchor renumbering.
New recommended findings (4)
- [sw-rec-r1-1] 1.3 / Appendix C trailer / Appendix D -- Count-consistency drift: the PR adds req-tg-009 bringing the real anchor count to 108, but Section 1.3 still reads "107 normative statements", the Appendix C trailer still reads "Total normative statements: 107 (102 MUST, 5 SHOULD)", and Appendix D carries no revision-history row for the 107->108 bump. Meanwhile the generated CONFORMANCE.json/md correctly reports 108. Every prior revision-history entry (0.1.21, 0.1.22, 0.1.23) diligently recorded its count delta; omitting this one breaks the established amendment-trail contract.
Recommended fix: Update Section 1.3 to "108 normative statements", update the Appendix C trailer to "Total normative statements: 108 (103 MUST, 5 SHOULD)", and add an Appendix D row (e.g. 0.1.24 | 2026-08-03 | Added [req-tg-009] (Section 8.5.1, consumer MUST): fail-closed agent deployment when source tools fall outside target vocabulary. Statement count: 107 -> 108 (103 MUST, 5 SHOULD).). - [sw-rec-r1-2] 8.7 / 11.3.2 -- Conformance class enumeration gap: Section 8.7 enumerates req-tg-001 through req-tg-008 for the Consumer class but omits the new req-tg-009. Section 11.3.2 Consumer enumeration likewise stops at req-tg-008. An implementer using either section as their conformance checklist will miss the new fail-closed requirement.
Recommended fix: Append ", req-tg-009" after "req-tg-008" in both the Section 8.7 Consumer bullet and the Section 11.3.2 Consumer enumeration list. - [sw-rec-r1-3] 8.5.1 -- Heading-honesty / section-taxonomy mismatch: req-tg-009 is placed under "8.5.1 Lossy agent conversion" but its semantics (hard fail-closed, MUST NOT write the target artifact) are categorically different from req-tg-006's semantics (lossy-but-permissive: emit a diagnostic but proceed with writing). An implementer reading the heading will form a false mental model of the obligation beneath it.
Recommended fix: Either (a) rename Section 8.5.1 to a broader title such as "8.5.1 Agent capability-set evaluation", or (b) introduce a new subsection (e.g. "8.5.1.1 Fail-closed vocabulary enforcement") to host req-tg-009 separately. Option (b) preserves the existing req-tg-006 section title and avoids anchor renumbering. - [sw-rec-r1-4] 8.5.1 (req-tg-009 text) -- Under-specified discriminator: req-tg-009 references "a fixed, enumerable capability vocabulary" and "the target's approved capability set" but provides no normative pointer to where this per-target vocabulary is registered. Unlike req-tg-006, which includes an explicit editorial note deferring concrete encodings, req-tg-009 contains no comparable deferral note.
Recommended fix: Append an editorial note after req-tg-009 similar to the one after req-tg-006, naming the non-normative Target Registry companion as the source of the per-target approved capability set.
New nit findings (2)
- [sw-nit-r1-1] Appendix C table section-reference inconsistency (pre-existing but compounded by this PR): req-tg-006 is physically located under "8.5.1 Lossy agent conversion" but its Appendix C row and manifest entry both record section "8.5". The new req-tg-009 correctly records section "8.5.1".
- [sw-nit-r1-2] Test coverage breadth: req-tg-009 contains four distinct testable MUST/MUST NOT clauses but binds only one conformance test (test_count: 1). A future Mode-B PR could narrow one clause without test breakage.
Preserved strengths confirmed
- Anchor uniqueness maintained (no duplicate id across the 108 post-PR anchors)
- Monotonic numbering preserved (req-tg-009 takes next free slot after req-tg-008)
- RFC 8174 keyword discipline upheld (all four normative claims carry explicit MUST/MUST NOT)
- Manifest and Appendix C table entry are mutually consistent (both record section 8.5.1, keyword MUST, class consumer)
Spec Oci Editor -- shocked_meter 3/10, confidence high
Summary: req-tg-009 is a well-constructed fail-closed gate that correctly encodes the OCI distribution lesson of never letting content-identity equality bypass a policy check. Three recommended follow-ups: normative anchor for the approved set, an atomicity SHOULD clause, and the count bump. Two nits address symlink edge-case coverage and ascending-section sort order. None of these gaps enable a supply-chain bypass in current form. Ship with follow-ups.
New recommended findings (3)
- [oci-rec-r1-1] 8.5.1 (req-tg-009) -- The approved capability set referenced by req-tg-009 has no normative anchor. The OpenAPM Target Registry is explicitly labeled "non-normative" and "informational supplement". A MUST-level fail-closed gate whose acceptance predicate is defined in a non-normative companion creates a conformance ambiguity: two implementations could disagree on what constitutes the approved set and produce divergent pass/fail outcomes for the same agent.
Recommended fix: Append a sentence to req-tg-009 delegating the approved capability set to the OpenAPM Target Registry companion, version-pinned by the spec version the consumer declares conformance to; require a conformance test suite to pin the exact companion version it validates against. - [oci-rec-r1-2] 8.5.1 (req-tg-009) -- req-tg-009 mandates "zero bytes, no partial file" as an outcome but does not prescribe an atomicity mechanism. Without at least a SHOULD-level atomic-write-or-cleanup clause, a conformant implementation could stream-write during validation and leave a partial file on crash -- violating the stated "zero bytes" outcome.
Recommended fix: Add an editorial note or a SHOULD clause recommending write-to-temporary-then-atomic-rename, with an explicit carve-out for unrecoverable process termination (e.g. SIGKILL). - [oci-rec-r1-3] 1.3 / Appendix C -- Post-PR, Section 1.3 claims "107 normative statements" and the Appendix C trailer claims "Total normative statements: 107". After req-tg-009 is added, CONFORMANCE.json reports 108. A spec artifact whose internal count disagrees with its own enumeration is analogous to an OCI manifest whose declared layer count disagrees with its layers array.
Recommended fix: Bump Section 1.3 and the Appendix C trailer to 108 (103 MUST, 5 SHOULD); add an Appendix D row documenting the 107 -> 108 bump.
New nit findings (2)
- [oci-nit-r1-1] req-tg-009 uses "bytes match the source" to cover the content-identity adoption bypass, but no clause covers symlinks/hardlinks in the deploy root satisfying byte-identity comparison via resolved content. Low severity: an attacker with deploy-root write access can bypass this via direct file placement anyway.
- [oci-nit-r1-2] The Appendix C table places req-tg-009 (section 8.5.1) after req-tg-008 (section 8.5.3), out of ascending section order. Functionally harmless but could confuse automated validators expecting monotonic section progression.
Preserved strengths confirmed
- The explicit ordering requirement ("MUST be performed prior to any content-identity adoption fast-path") directly encodes the OCI lesson that policy gates must not be bypassable by digest/content-address equality -- well-constructed.
- The "zero bytes, no partial file" outcome requirement is stronger than many comparable specs.
- Section 10.9 (req-sc-002) continues to provide a strong fail-closed extraction baseline for archive path-traversal, complementing the new agent-deployment gate.
- The hash envelope convention remains anchored to the algo:hex pattern, consistent with content-addressable best practice.
Spec Pkgmgr Editor -- shocked_meter 4/10, confidence high
Summary: req-tg-009 is a well-motivated defensive gate. The primary concern is a blast-radius ambiguity: the requirement text does not explicitly state whether failure is per-agent or per-install. Secondary concerns: undeclared composition order with req-tg-008, count drift, and adoption-fast-path comparison-target pinning. All addressable as followup edits without blocking the normative intent.
New blocking findings (1)
- [pm-blk-r1-1] 8.5.1 (req-tg-009) -- The requirement text says "the implementation MUST NOT write the agent's target artifact (zero bytes, no partial file)" but is silent on the blast radius: does one agent with an unsupported tool cause only that agent's artifact to be skipped, or does it abort the entire install operation? The PR body's trade-offs section says "Fail-closed per agent, not per install", but that prose is non-normative and will not ship with the spec. Two conformant implementations could diverge on blast radius.
Recommended fix: Append after "(zero bytes, no partial file)": "This gate is evaluated per agent primitive independently; failure for one agent MUST NOT prevent deployment of other, vocabulary-conformant agent primitives from the same dependency or install operation."
New recommended findings (4)
- [pm-rec-r1-1] 8.5.1 (req-tg-009) vs 8.5.3 (req-tg-008) -- req-tg-008 establishes a target-restriction filter; req-tg-009 introduces a per-tool vocabulary gate evaluated independently. The spec does not state their composition order.
Recommended fix: Add a sentence establishing that req-tg-009's evaluation applies only to agents whose target survives req-tg-008's intersection filter. - [pm-rec-r1-2] Section 1.3, Appendix C trailer, Appendix D -- The PR does NOT update Section 1.3 (still "107"), the Appendix C trailer (still "107"), or Appendix D (no new row), while CONFORMANCE.json correctly reports 108.
Recommended fix: Update all three prose count sites to 108 (103 MUST, 5 SHOULD) and add a 0.1.24 Appendix D row. - [pm-rec-r1-3] 8.5.1 (req-tg-009) -- The phrase "an existing on-disk artifact whose bytes match the source" does not define what "the source" means in the presence of lockfile re-resolution -- freshly-rendered content or a cached/lockfile-recorded value.
Recommended fix: Replace with "an existing on-disk artifact whose bytes are identical to the bytes the implementation would write from the currently-resolved source". - [pm-rec-r1-4] 8.5.1 (req-tg-009) -- The requirement references "a fixed, enumerable capability vocabulary" but does not specify where this vocabulary is defined or how a consumer discovers it.
Recommended fix: Add an editorial note reserving future normative pinning via the Target Registry companion.
New nit findings (2)
- [pm-nit-r1-1] req-tg-009 is placed inside Section 8.5.1 ("Lossy agent conversion") though it describes a distinct concern. Consider a new subsection.
- [pm-nit-r1-2] Verify the section attribution (8.5.1) matches the intended structural home given the heading mismatch.
Preserved strengths confirmed
- Conformance class separation: req-tg-009 correctly scopes to consumer class only.
- The fail-closed pattern mirrors the established defensive pattern from req-sc-009/req-sc-010.
- The manifest YAML and CONFORMANCE.json rollup are mechanically consistent with the new requirement.
Spec Tag Architect -- shocked_meter 4/10, confidence high
Summary: req-tg-009 is a well-motivated fail-closed gate with a sound architectural posture. However, it introduces "approved capability set" as a load-bearing normative concept without defining it in Terminology or cross-referencing the Target Registry as its authority. This creates a portability gap. Additionally, the spec's internal count sites were not updated from 107 to 108. The terminology surface also now carries three overlapping capability-related noun-phrases without explicit reconciliation. None of these issues break implementability for a single consumer, but they weaken interoperability guarantees and architectural self-consistency. Ship with follow-up amendments to close the vocabulary-authority gap and reconcile counts.
New recommended findings (3)
- [tag-rec-r1-1] 8.5.1 (req-tg-009) -- req-tg-009 introduces "the target's approved capability set" and "a fixed, enumerable capability vocabulary" as load-bearing normative concepts without defining them in Section 3 (Terminology), without cross-referencing the Target Registry companion, and without specifying a resolution mechanism. Two conformant implementations MAY legitimately hard-code DIFFERENT approved sets for the same target identifier and both pass conformance while producing divergent accept/reject outcomes.
Recommended fix: Add a cross-reference sentence naming the Target Registry v0.1 companion as the vocabulary source, with a pinned-snapshot allowance and a staleness diagnostic. - [tag-rec-r1-2] 1.3 / Appendix C trailer -- The spec's own internal count sites were not updated by this PR, while CONFORMANCE.json correctly reports 108. The spec's prose and its machine-readable contract surface disagree on cardinality.
Recommended fix: Update Section 1.3 and the Appendix C trailer to 108 (103 MUST, 5 SHOULD); add an Appendix D row documenting the transition. - [tag-rec-r1-3] 8.5.1 / Section 3 -- The spec now uses three overlapping but non-identical concepts for "capability" within Section 8.5-8.5.3: "source-declared capability restriction" (Section 3, req-tg-006), "fixed, enumerable capability vocabulary" (req-tg-009), and "approved capability set" (also req-tg-009). Meanwhile req-tg-008 introduces a distinct "target subset authorized by the consumer". The spec never states the relationship between a restriction and a vocabulary or reconciles the noun-phrases.
Recommended fix: Add a Section 3 Terminology row for "Target capability vocabulary" and have req-tg-009 back-reference this single defined term.
New nit findings (2)
- [tag-nit-r1-1] Appendix D (Revision history) has no row for the addition of req-tg-009. Every prior normative addition since 0.1.3 has recorded a revision-history row. The missing row breaks the established pattern.
- [tag-nit-r1-2] req-tg-009's Appendix C row reports section "8.5.1" but the heading is "Lossy agent conversion", a distinct architectural concern from vocabulary gating. Consider its own sub-subsection.
Preserved strengths confirmed
- Machine-readable requirements manifest was correctly updated with the new requirement row and section reference.
- The conformance test binding (test_count: 1 with a concrete test path) maintains the established CI-binding discipline.
- The fail-closed posture of req-tg-009 is architecturally sound and consistent with the existing fail-closed pattern in req-sc-009.
- The adoption-fast-path override clause closes a real bypass vector and is well-formulated as a temporal ordering MUST.
This panel is advisory. It does not block merge. Re-apply the spec-review label after addressing feedback to re-run.
… integrity Remove src/apm_cli/integration/mcp_integrator_install.py from the broad 'Effective install target selection' row -- its selector duplicated the existing 'MCP target-selection precedence' row, which already owns that file exclusively. Remove the second duplicate 'Effective package target authorization' row (src/apm_cli/install/target_filter.py also duplicated). Both duplicates were on origin/main before PR #2440 landed and blocked the shepherd owner-touch gate (parse_owner_table raises GateError on duplicate selectors). This commit is a prerequisite shepherd gate repair, not a Kiro product behavior change. Add a focused regression test (test_cross_row_duplicate_selector_fails_closed) that constructs two distinct rows sharing one selector and asserts the gate emits 'duplicate canonical owner selector' fail-closed. Mutation-break verified: disabling the guard flips the test to FAILED; restoring it returns PASSED. Mirror repair to .github/instructions/architecture.instructions.md (the two files must remain byte-identical; there is no separate generation step). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9c7e3f39-dd3e-4fc6-bc4e-c64ffeaf1685
#2089) Docs-sync advisory (3 patches in primitives-and-targets.md): - Update kiro target bullet to mention agents deployment using 'deploy to' phrasing (avoids ambiguity with apm compile); align to 'Kiro IDE/CLI v3'. - Fix agents compatibility matrix Kiro column: unsupported -> compiled. - Add cell note: agents/kiro = compiled explaining frontmatter filtering and fail-closed tools gate. Spec guardian F1-F5 (openapm-v0.1.md + test_manifest_reqs.py): - F1: Append per-agent blast-radius clause to req-tg-009: failure for one agent MUST NOT prevent deployment of other vocabulary-conformant agents. - F2: Update normative statement count 107 -> 108 (103 MUST, 5 SHOULD) in Section 1.3, Appendix C trailer; add Appendix D row 0.1.24 for req-tg-009. - F3: Add req-tg-009 to Section 8.7 and Section 11.3.2 Consumer conformance enumerations; update pinned verbatim assertion in test_manifest_reqs.py. - F4: Add editorial note after req-tg-009 naming Target Registry companion as vocabulary authority and mandating version-pinning for conformance. - F5: Add composition/order sentence: gate applies only to targets in the effective intersection computed under req-tg-008. Copilot inline items: - Replace diagnostics._diagnostics private attribute accesses with the public diagnostics.by_category().get(cat, []) API (3 sites in test_kiro_target.py; import CATEGORY_ERROR at module level). - Normalize tool whitespace: tools_out was assigned tools_raw (unstripped) even though validation used the stripped tools_strs; fix to emit stripped values so checked bytes equal written bytes. - Add regression/mutation evidence: test_kiro_agents_tools_whitespace_stripped_in_output (strips and validates). - Add stale-managed-agent regression: test_kiro_agents_stale_managed_file_removed_when_tools_become_incompatible asserts that an agent whose tools become incompatible is skipped (not in target_paths) and can be cleaned up by sync_for_target. CHANGELOG: - Normalize Kiro CHANGELOG entry: end with (#2089), remove noisy inline refs that deviate from the repo convention. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9c7e3f39-dd3e-4fc6-bc4e-c64ffeaf1685
APM Review Panel:
|
| Persona | B | R | N | Takeaway |
|---|---|---|---|---|
| Python Architect | 0 | 1 | 1 | Single-owner discipline upheld in _preflight_render_kiro_agent; adopt comparison uses rendered bytes (adopt-bypass closed). One latent defect: materialize_project_target_profiles creates dirs unconditionally, bypassing auto_create=False. |
| CLI Logging Expert | 0 | 0 | 2 | Diagnostic messages are ASCII-safe, actionable, and consistently structured. Two nits on multi-agent diagnostic grouping and silent stale-file removal. |
| DevX UX Expert | 0 | 0 | 3 | Per-agent fail-closed behavior matches npm error model. Single-string tools error message omits full approved set; tool list duplicated across 4 docs. |
| Supply Chain Security | 0 | 0 | 2 | Fail-closed allowlist, path traversal guard, adopt-bypass prevention all correct. Two nits: empty-string tool error message clarity; no dedicated kiro traversal test. |
| OSS Growth Hacker | 0 | 0 | 2 | Feature IS delivered (contrary to one discarded finding). Fail-closed messaging can be reframed as protective; Codex tool scope warnings are a releasable story. |
| Auth Expert | -- | -- | -- | Inactive: no auth, credential, token, or host classification changes. |
| Doc Writer | 0 | 3 | 3 | Spec F1-F5 correctly applied. Tool set duplicated in 4 docs (drift risk). Missing Common Pitfalls bullet for fail-closed. ide-tool-integration section doubled in length. |
| Test Coverage Expert | 0 | 0 | 1 | Critical surfaces well-defended. YAML scalar-string tools path untested (nit only -- branch behavior identical to list path). |
| Performance Expert | 0 | 0 | 3 | O(N) loop with frozenset membership (O(1)). Lazy mkdir. No hot-path regressions. Three negligible nits. |
B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.
Top 5 follow-ups
- [Doc Writer] Consolidate approved-tool-set into targets-matrix.md with cross-refs in the 4 downstream docs to eliminate drift risk -- four copies today are all accurate but will diverge when Kiro adds capability tags
- [Python Architect] Add auto_create=False guard in materialize_project_target_profiles to prevent latent directory creation for non-opt-in targets -- latent only, no current code path triggers it, but worth hardening before it bites
- [Doc Writer] Add Common Pitfalls bullet in instructions-and-agents.md explaining fail-closed behavior when unlisted tools are declared -- most actionable surprise for authors targeting multiple runtimes
- [Doc Writer] Trim ide-tool-integration.md Kiro section to a brief paragraph + cross-ref to targets-matrix.md (once follow-up 1 lands)
- [Test Coverage Expert] Add YAML scalar-string tools path test (tools: read) for completeness -- branch is structurally identical to list path but currently unexercised
Architecture
classDiagram
direction LR
class BaseIntegrator {
<<Base>>
+_LF_NORMALIZED_DEPLOY bool
+is_content_identical_to_source(target, source) bool
+try_adopt_identical(target, source, paths) bool
+_check_adopt_or_skip(target, source, ...) tuple
+check_collision(target, rel, managed, force) bool
+sync_remove_files(root, managed, prefix) dict
+validate_deploy_path(rel, root) bool
}
class AgentIntegrator {
<<Concrete>>
+integrate_agents_for_target(target, pkg, root)
+_preflight_render_kiro_agent(source, diag, pkg) tuple
+_kiro_agent_relpath(source, install_path) str
+sync_for_target(target, pkg, root)
+KIRO_AGENT_ALLOWED_TOOLS frozenset
}
class TargetProfile {
<<ValueObject>>
+root_dir str
+auto_create bool
+primitives dict~str PrimitiveMapping~
}
class PrimitiveMapping {
<<ValueObject>>
+subdir str
+extension str
+format_id str
}
class DiagnosticCollector {
<<Collect-then-render>>
+error(message, package)
+by_category() dict
+render_summary()
}
BaseIntegrator <|-- AgentIntegrator
AgentIntegrator ..> TargetProfile : reads
AgentIntegrator ..> DiagnosticCollector : writes errors
TargetProfile *-- PrimitiveMapping : primitives
class AgentIntegrator:::touched
class DiagnosticCollector:::touched
class TargetProfile:::touched
classDef touched fill:#fff3b0,stroke:#d47600
flowchart TD
A["apm install --target kiro"] --> B{"kiro TargetProfile has agents primitive?"}
B -- No --> Z["skip target"]
B -- Yes --> C["integrate_agents_for_target(kiro, pkg, root)"]
C --> D{"auto_create=False AND .kiro/ missing?"}
D -- Yes --> Z
D -- No --> E["find_agent_files(pkg.install_path)"]
E --> F{"agent_files empty?"}
F -- Yes --> Z
F -- No --> H["for source_file in agent_files"]
H --> I["_kiro_agent_relpath(source, install_path)"]
I --> J["ensure_path_within(target_path, agents_dir)"]
J --> K{"PathTraversalError?"}
K -- Yes --> L["diagnostics.warn + files_skipped += 1"]
K -- No --> M["_preflight_render_kiro_agent(source, diag, pkg)"]
M --> N{"ok=True?"}
N -- No --> O["files_skipped += 1, continue"]
N -- Yes --> P{"target_path.exists() byte-match rendered?"}
P -- Yes --> Q["files_adopted += 1, continue"]
P -- No --> R{"check_collision?"}
R -- Yes --> S["files_skipped += 1"]
R -- No --> T["[lazy] agents_dir.mkdir() + write_text_lf"]
T --> U["files_integrated += 1"]
U --> H
Recommendation
Zero blocking findings across all panels. The feature is complete: implementation, tests, docs, and spec alignment are all present. The five recommended follow-ups are doc-consolidation hygiene (dw-001/002/003), a latent-only defensive guard (pa-01), and a coverage-completeness nit (tce-1) -- none affect correctness or user-facing behavior on this commit. Ship now; file follow-up issues for priorities 1-3 within the current milestone.
Full per-persona findings
Python Architect
- [recommended]
materialize_project_target_profiles()unconditionally creates the target root directory for every named target, bypassingTargetProfile.auto_create=False. If a non-opt-in target (e.g. kiro) is passed,.kiro/would be created without user consent. Guard onprofile.auto_createor document that callers must pre-filter.
Location:src/apm_cli/integration/targets.py(materialize_project_target_profiles) - [nit] adopt comparison in
_check_adopt_or_skipstructurally cannot match for transformed formats (codex_agent -> TOML); a brief comment noting this prevents future developers from "fixing" the always-false adopt path.
Location:src/apm_cli/integration/agent_integrator.py
CLI Logging Expert
- [nit]
lossy_agent_compilationrenders detail strings deduplicated below the item list; in multi-agent scenarios the Fix: line may not obviously associate with its agent. - [nit]
sync_for_targetremoves stale files silently; a verbose-mode breadcrumb would aid debugging.
DevX UX Expert
- [nit] single-string tools error message omits the full approved capability set that the list-case message includes
Location:src/apm_cli/integration/agent_integrator.py(~line 578) - [nit] approved tool set repeated verbatim in 4 docs -- drift risk when Kiro adds capability tags
- [nit] CHANGELOG entry (13 lines) substantially longer than sibling entries
Supply Chain Security Expert
- [nit] empty or whitespace-only tool string (e.g.
tools: ['']) correctly fails closed but produces a confusing empty-looking capability tag in the error message
Location:src/apm_cli/integration/agent_integrator.py(tools_strs comprehension) - [nit] no dedicated kiro_agent path traversal test (guard is inherited and correct; purely coverage-depth nit)
OSS Growth Hacker
- [nit] fail-closed behavior is positioned as a restriction; reframing as "APM protects your Kiro config from agents with unrecognized capabilities" converts a potential friction point into a trust signal
- [nit] Codex tool scope warnings (new
_warn_codex_tools_dropped) are a releasable story: "APM catches agent permission drift across targets"
Auth Expert -- inactive
Inactive: PR touches only agent integrator (deploy-time file write) and target profile. No auth, credential, token, host classification, or git authorization changes.
Doc Writer
- [recommended] Approved tool set duplicated verbatim in 4 docs (ide-tool-integration.md, targets-matrix.md, instructions-and-agents.md, package-authoring.md). Consolidate to targets-matrix.md with cross-references from the other three.
- [recommended] ide-tool-integration.md Kiro section doubled in length; cutting to cross-ref (per dw-001) would restore it to hub-page density.
- [recommended] Missing Common Pitfalls bullet in instructions-and-agents.md for fail-closed behavior -- most actionable surprise for multi-target authors.
- [nit] Access-date annotations in 4 user-facing docs; appropriate only for spec Appendix D, not user docs (will read as stale).
- [nit] In instructions-and-agents.md, Kiro paragraph precedes Codex paragraph, disrupting the verbatim->compiled->unsupported reading order that matches the table below.
- [nit] Kiro row in "What compiles where" table is 3x longer than sibling rows and includes an inline URL citation; no other row does this.
Test Coverage Expert
- [nit] YAML scalar string tools path (
tools: read) has no dedicated test; all 26 unit tests use list format. Branch behavior is structurally identical but currently unexercised.
Performance Expert
- [nit] Duplicate
isinstance(fm, dict)check in_write_codex_agent-- ~2ns cost, negligible. - [nit]
printable_ascii_text()is O(len(name)) -- called only on error paths, not hot. - [nit]
materialize_project_target_profilescallsdeploy_path.is_dir()+ conditionalmkdirper target (~10 stat calls max, <1ms total).
This panel is advisory. It does not block merge. Re-apply the
panel-review label after addressing feedback to re-run.
…tions after owner repair The canonical owner table repair (commit f007f76) modified .github/instructions/architecture.instructions.md to remove two duplicate owner selectors. The APM self-check (apm audit --ci) detected a hash drift: the file's sha256 in apm.lock.yaml still recorded the pre-repair bytes. Update to the post-repair sha256. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9c7e3f39-dd3e-4fc6-bc4e-c64ffeaf1685
Force GitHub to recompute merge commit for CI after the prior lockfile fix commit (1fa24d7). The APM Self-Check was evaluating a stale merge ref that predated the hash update. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9c7e3f39-dd3e-4fc6-bc4e-c64ffeaf1685
… instructions The previous lockfile commit (1fa24d7) updated only the local_deployed_file_hashes section. The deployment ledger entries (kind: project-relative records) also record a content_hash field that the apm audit --ci content-integrity check reads directly. Update the ledger record's content_hash to match the post-repair SHA-256 of .github/instructions/architecture.instructions.md. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9c7e3f39-dd3e-4fc6-bc4e-c64ffeaf1685
APM Spec Guardian:
|
| Panel | Verdict | Shocked | New B | New R | New N |
|---|---|---|---|---|---|
| Spec Swagger Editor | ship_with_followups | 8/10 | 0 | 1 | 1 |
| Spec Oci Editor | ship_with_followups | 8/10 | 0 | 0 | 1 |
| Spec Pkgmgr Editor | ship_with_followups | 7/10 | 0 | 0 | 1 |
| Spec Tag Architect | ship_with_followups | 8/10 | 0 | 1 | 1 |
B = new blocking findings, R = new recommended, N = new nits.
Counts are signal strength, not gates. The maintainer ships.
Convergent themes (flagged by 2+ panels)
- T5 -- RFC 2119 MUST keyword inside non-normative editorial note -- precedented but under-documented convention. All four panels flag the "MUST pin" phrasing following req-tg-009. Swagger and tag raise it as recommended (demote the keyword or promote to a standalone req-id in v0.1.1); pkgmgr notes it as a nit. Oci investigated the existing corpus and found the pattern precedented (7 plain Editorial note blocks already carry MUST-level procedural language, e.g. the resolved_commit and antigravity notes, and even the sole "(non-normative)" tagged note embeds a MUST), concluding this is an established, if under-documented, convention rather than a novel defect. No panelist treats it as blocking; the note's own text time-bounds the concern with "future revision may promote". (supporting: sw-rec-r2-1, tag-rec-r2-1, pm-nit-r2-1, oci-nit-r2-1)
Defer to v0.1.1
- [F10 / Resolve MUST-in-editorial-note layering ambiguity holistically] Section 8.5.1 editorial note + Section 1.3 Conventions -- Either (a) promote the version-pinning obligation to a standalone normative requirement (e.g. req-tg-010) in Section 11.3 Conformance Methodology and replace the editorial note's MUST phrasing with a forward-reference to the new req, OR (b) add a one-sentence clarification to Section 1.3/Conventions documenting that plain "Editorial note" blocks in this specification may carry binding procedural language (per the 7-instance existing precedent identified by oci). Option (a) is preferred if the version-pinning obligation is load-bearing for interop; option (b) if the intent is merely procedural guidance. In either case, apply the chosen fix consistently across all 7+ existing editorial-note MUST instances, not just this one.
Rejected findings
- tag-nit-r2-1 -- The panelist's own text concedes "still cosmetic for v0.1". F7 (heading taxonomy split of req-tg-009 into sub-clauses) is already tracked at v0.1.1 priority. The suggestion that the structural split is "slightly more urgent" given the growth to five obligations does not change its timeline classification -- the five obligations within req-tg-009 remain individually testable per swagger's preserved-strengths confirmation, so no conformance or interop harm results from their co-location in v0.1. Re-prioritization is not warranted; F7 remains correctly slotted for v0.1.1.
Linter notes (1 check(s) failed)
- [11] 9 non-spec
.pyfiles were modified across the full PR (unchanged from round 1; this round's fold touched only the spec markdown and one conformance-test string). This is a combined code+spec PR by design (Mode B requires the code change and its spec anchor to land together); consider also runningapm-review-panelfor the code-side changes if that has not already happened. This is advisory only and does not affect the spec artifact's shippability.
Note: the synthesizer recommends ship; the linter found 1 issue worth folding first. In this case check 11 is a structural/scope observation about the PR pairing code with spec, not a defect in the spec artifact itself, so it does not block the fold_and_ship recommendation.
Linter handoff: Wave 5 linter verification targets for the final state (drafter fold commit 6188428, no additional folds this round): (1) Check 6 (count consistency): PASS -- all three sites (Section 1.3 prose, Appendix C trailer summary, Appendix D changelog row 0.1.24) are reconciled at 108 total normative statements / 103 MUST / 5 SHOULD. (2) Check 5 (anchor uniqueness): PASS -- req-tg-009 is the sole new anchor; no renumbering of existing req-ids occurred. (3) No fold_now items were applied this round, so no post-fold diff verification is needed; the drafter's prior fold commit is the final mergeable state. (4) Round-1 deferred items F6-F9 plus new F10 remain open for v0.1.1 and are NOT expected to be resolved in this PR -- the linter should not flag their absence. (5) Confirmed clean: no fold or defer item text introduces a forbidden vendor/foundation token. (6) The editorial note following req-tg-009 still contains "MUST pin" (deferred as F10); the linter's normative-count check should NOT count this toward the 108 tally because it resides in an editorial-note block without a req-id anchor, consistent with how the spec's existing editorial-note MUST instances are already excluded from the count.
Full per-panel findings
Spec Swagger Editor -- shocked_meter 8/10, confidence high
Summary: The drafter's fold commit cleanly closes 3 of 4 round-1 recommended findings; the 4th (heading taxonomy) was honestly deferred to v0.1.1 as F7. Count consistency, conformance-class enumeration, and the capability-vocabulary cross-reference are all resolved. One new recommended finding emerges: the fold introduced a stray RFC 2119 MUST keyword inside an editorial note block that is conventionally non-normative in this spec, creating a category ambiguity for conformance testers. This is easily fixable by lowercasing to informative voice, consistent with the note's own sentence forecasting a future normative promotion. No blockers, no regressions. The artifact is shipable with this follow-up tracked.
Round-1 closure: 3 of 4 recommended findings fully closed: sw-rec-r1-1 (count consistency) closed by Section 1.3 bump to 108, Appendix C trailer bump to 108 (103 MUST, 5 SHOULD), and Appendix D row 0.1.24 added -- all three prose sites now agree with CONFORMANCE.json. sw-rec-r1-2 (enumeration gap) closed by appending req-tg-009 to both Section 8.7 and Section 11.3.2 Consumer enumerations, confirmed by the updated regression oracle in test_manifest_reqs.py. sw-rec-r1-4 (registry cross-reference) closed by the new editorial note naming the Target Registry companion as the vocabulary authority. sw-rec-r1-3 (heading taxonomy rename) was correctly deferred to v0.1.1 as synthesizer fold item F7 -- deferred_clean.
New recommended findings (1)
- [sw-rec-r2-1] Section 8.5.1, editorial note following req-tg-009 -- The editorial note contains "A conformance test suite MUST pin the exact companion version it validates against." This embeds an RFC 2119 MUST keyword inside a block that is conventionally non-normative in this specification. The note block has no req-XX-NNN anchor and is not enumerated in any conformance class, so the MUST is either (a) mis-capitalized informative voice, or (b) an un-anchored normative requirement that escapes conformance tracking.
Recommended fix: Replace "MUST pin" with "is expected to pin" -- or, if the binding is intentional, promote the clause to a standalone req-XX-NNN anchor and increment the normative-statement count accordingly.
New nit findings (1)
- [sw-nit-r2-1] The Appendix D row 0.1.24 description runs well beyond the column width established by prior rows. Consider trimming to match the table's existing cadence.
Preserved strengths confirmed
- req-tg-009 anchor remains unique with no renumbering of existing ids.
- All cross-references from the new text resolve to existing anchors.
- The four distinct MUST/MUST NOT sub-clauses within req-tg-009 remain individually testable and do not contradict each other.
- The per-agent independence clause and the req-tg-008 composition sentence compose cleanly without mutual contradiction.
- The conformance-class placement remains correct: req-tg-009 is enumerated under Consumer in both Section 8.7 and Section 11.3.2.
Spec Oci Editor -- shocked_meter 8/10, confidence high
Summary: All three round-1 recommended findings are resolved: closed, closed, and honestly deferred. The blast-radius clause and req-tg-008 composition sentence introduce no new supply-chain ordering ambiguity or TOCTOU. I investigated whether the MUST-in-editorial-note pattern (which swagger and tag flag as a category concern) is actually novel: it is NOT -- the spec's existing corpus already contains plain "Editorial note" blocks with embedded MUST-level procedural language (e.g. the resolved_commit note, the antigravity note), and even the one "Editorial note (non-normative)" instance contains a MUST (mirror operators). So this is a precedented, if slightly under-documented, spec convention, not a new defect introduced by this PR. One new nit suggesting the convention be documented explicitly. Ship with the acknowledged v0.1.1 followups.
Round-1 closure: oci-rec-r1-1 (normative anchor): CLOSED via editorial note with version-pinned companion delegation. oci-rec-r1-3 (count consistency): CLOSED, all sites reconciled at 108. oci-rec-r1-2 (atomicity): DEFERRED CLEAN to v0.1.1 as F6, honestly acknowledged, no misleading closure claim.
New nit findings (1)
- [oci-nit-r2-1] Section 1.3/Conventions does not explicitly codify the distinction between plain "Editorial note" (which the corpus already uses 7 times, some carrying MUST-level procedural language) and "Editorial note (non-normative)" (1 instance). The distinction is inferrable from precedent but a first-time reader might question whether the new req-tg-009 note's MUST is binding. Cosmetic -- the existing evidence is consistent and the distinction is defensible.
Preserved strengths confirmed
- Content-identity adoption fast-path exemption carve-out remains explicit and correctly ordered.
- Fail-closed default (zero bytes, no partial file) is retained as the singular output contract.
- The composition sentence with req-tg-008 is deterministic; no TOCTOU or lazy-evaluation non-determinism is introduced.
- The per-agent-primitive independence clause is architecturally sound from a supply-chain audit perspective.
- Normative-count reconciliation infrastructure is now consistent at 108.
Spec Pkgmgr Editor -- shocked_meter 7/10, confidence high
Summary: Round-1 blocker (pm-blk-r1-1) is fully closed: the per-agent blast-radius sentence pins scope unambiguously and the req-tg-008 composition clause introduces no cross-agent evaluation dependency. All applicable recommended findings are closed; pm-rec-r1-3 is honestly deferred to v0.1.1. No new blocking or recommended findings. One nit (MUST keyword in non-normative editorial note). The fold is precise, deterministic, and introduces no new ambiguity in the dependency-resolution or lockfile-determinism domains. Ship with the v0.1.1 followup for F9.
Round-1 blocker closure: pm-blk-r1-1: closed. Evidence: The sentence "This gate is evaluated per agent primitive independently; failure for one agent MUST NOT prevent deployment of other, vocabulary-conformant agent primitives from the same dependency or install operation." is verbatim the recommended fix and pins blast radius unambiguously. The composition sentence with req-tg-008 does NOT introduce cross-agent evaluation dependency because the intersection is a static set function of (manifest declared targets, consumer supported targets), not influenced by any individual agent's pass/fail outcome. Two conformant implementations will compute the same intersection and independently evaluate each surviving agent, with no ordering or outcome dependency between agents. Remaining concern: none.
Round-1 recommended closure: pm-rec-r1-1 (composition order): closed. pm-rec-r1-2 (count consistency): closed. pm-rec-r1-4 (vocabulary discovery): closed via editorial note naming Target Registry companion. pm-rec-r1-3 (lockfile re-resolution pinning): honestly deferred to v0.1.1 as F9.
New nit findings (1)
- [pm-nit-r2-1] The editorial note contains "A conformance test suite MUST pin the exact companion version it validates against" -- an RFC 2119 keyword inside a non-normative editorial note. The note's own "future revision may promote" sentence mitigates confusion, but a pedantic reader may attempt to count this as a normative statement without a req-id.
Preserved strengths confirmed
- Fail-closed default remains intact and is now explicitly scoped per-agent, strengthening the guarantee.
- Content-identity fast-path non-exemption clause preserved verbatim -- cache-poisoning vector remains closed.
- Actionable diagnostic requirement unchanged.
- The new composition sentence with req-tg-008 adds a dependency-resolution-style evaluation ordering that is sound: the intersection is a pure function of declared inputs, not of gate outcomes.
Spec Tag Architect -- shocked_meter 8/10, confidence high
Summary: All fold-now items (F1-F5) are verifiable in the diff and substantively close the round-1 findings. All three of my round-1 findings are closed or honestly deferred without compounding the terminology overload. One new recommended finding (MUST keyword inside a non-normative editorial note -- time-bounded, non-blocking). One nit on the growing structural weight of req-tg-009, reinforcing the already-deferred F7 split. No regressions; the per-agent independence clause actively strengthens abuse-resistance. Ship with the documented v0.1.1 follow-ups.
Round-1 closure: tag-rec-r1-1 (vocabulary authority cross-reference): CLOSED via the new editorial note. tag-rec-r1-2 (count consistency): CLOSED, all sites at 108. tag-rec-r1-3 (terminology reconciliation): HONESTLY DEFERRED as F8 to v0.1.1; the new note's phrasing functions as a partial definitional gloss rather than compounding the terminology overload.
New recommended findings (1)
- [tag-rec-r2-1] Section 8.5.1, editorial note after req-tg-009 -- The editorial note's "A conformance test suite MUST pin the exact companion version it validates against" embeds an RFC 2119 keyword inside a non-normative editorial note, a layering ambiguity. This is explicitly time-bounded by the note's own "future revision" sentence, so it does not block v0.1 shipment, but the v0.1.1 promotion pass should elevate this to a standalone normative requirement (e.g. req-tg-010) rather than leaving the load-bearing interop guarantee in informative prose.
Recommended fix: When the v0.1.1 cycle opens: extract the version-pinning obligation into a new normative requirement (req-tg-010 or similar) in Section 11.3 Conformance Methodology; remove the editorial note's MUST phrasing and replace with a forward-reference to the new req.
New nit findings (1)
- [tag-nit-r2-1] req-tg-009 now spans five distinct behavioral obligations in one normative paragraph. The per-agent independence clause is architecturally a separate positive guarantee from the surrounding negative fail-closed gate. The already-deferred structural split (F7) is slightly more urgent given this growth, though still cosmetic for v0.1. (Synthesizer note: rejected as a re-prioritization signal -- see Rejected findings above.)
Preserved strengths confirmed
- Fail-closed security posture remains intact and is now strengthened by explicit content-identity fast-path non-exemption -- the blast-radius guarantee is tighter than round 1.
- Self-containment: the editorial note provides the missing cross-reference to the Target Registry companion that round 1 identified as a gap.
- Forward-compatibility signal: the "future revision may promote" sentence and the Appendix D changelog entry make the spec's evolutionary intent machine-traceable.
- Per-agent independence clause improves abuse-resistance: a single malformed agent primitive cannot denial-of-service an entire install operation.
This panel is advisory. It does not block merge. Re-apply the spec-review label after addressing feedback to re-run.
* chore: release v0.28.0 Bump pyproject.toml and uv.lock to 0.28.0 and convert the [Unreleased] CHANGELOG block into [0.28.0] - 2026-08-04 with one "so what" entry per user-facing PR merged since v0.27.0. MINOR is warranted: registry object-form dependencies gained new `skills:`/`targets:` manifest fields (#2166) and two new xAI Grok targets landed (#2420), alongside the Kiro agents primitive (#2440). Lint mirror is green locally (ruff check + format, pylint R0801, auth-signals). Post-merge: tag v0.28.0 to trigger the release workflow. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 11dbb707-3685-4a9e-80a4-19c73831232a * refactor(install): extract argv boundary helpers to unblock length gate The CI file-length guardrail (2100 lines) failed on src/apm_cli/commands/install.py at 2111 lines -- drift that landed on main via #2166 and #2200, surfaced here because CI evaluates the merge commit. Move `_get_invocation_argv` and `_split_argv_at_double_dash` (plus the explanatory block comment on Click's `--` swallowing) into the new `apm_cli/install/argv.py`. `commands/mcp.py` already reached through `commands/install.py` for both helpers, so they were never install-specific; `commands/install.py` re-exports them so the `_get_invocation_argv` test seam keeps working unchanged. install.py: 2111 -> 2080 lines. Ratchet the architecture invariant budget 2150 -> 2100 to match the CI guardrail. Validation: lint mirror green (ruff check + format, pylint R0801, auth-signals), architecture boundary lint clean, file-length guard clean, 2084 tests pass across tests/unit/install/ and tests/integration/test_architecture_authorities.py. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 11dbb707-3685-4a9e-80a4-19c73831232a --------- Co-authored-by: danielmeppiel <danielmeppiel@users.noreply.github.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 11dbb707-3685-4a9e-80a4-19c73831232a
feat(kiro): deploy agents primitive to .kiro/agents/ + req-tg-009 (#2089)
TL;DR
APM now compiles agent primitives to
.kiro/agents/<relative-stem>.mdfor Kiro IDE/CLI v3(ref: https://kiro.dev/docs/custom-agents/, accessed 2026-08-03). Only
description,model, andtoolsfrontmatter are emitted;nameand unknown fields are stripped.Tools are permission-bearing: the install fails closed -- no file written, no directory
created -- if any tool value is outside Kiro's approved capability set. A new normative
requirement req-tg-009 (Section 8.5.1) anchors the fail-closed evaluation order, and seven
integration lifecycle scenarios prove the feature through the real APM binary.
Problem (WHY)
instructions,skills, andhooksinKNOWN_TARGETSbut noagentsprimitive. Agents authored in
.apm/agents/were silently undeployed for Kiro users._check_adopt_or_skip()ranBEFORE
_write_kiro_agent()validated tools. A pre-placed.kiro/agents/X.mdmatchingsource bytes (even with invalid tools) was adopted without validation, bypassing the
fail-closed gate per req-tg-009.
src/apm_cli/integration/withouta spec anchor, manifest row, and
@pytest.mark.reqmarker fails CI conformance.Rule requires integration-with-fixtures tier (real binary + real filesystem effects).
Approach (WHAT)
"agents": PrimitiveMapping("agents", ".md", "kiro_agent")added toKNOWN_TARGETS["kiro"]_preflight_render_kiro_agent()-- single owner of render+validate, runs before adopt/mkdiragents_dir.mkdir(): directory created only when a write actually proceedsApmLifecycleRunner+ real CLI binaryImplementation (HOW)
src/apm_cli/integration/agent_integrator.py-- adds_preflight_render_kiro_agent()as the single owner of kiro render+validate (returns
(rendered_str|None, bool)). Theintegration loop for
kiro_agentcalls preflight first; on failure it skips withouttouching the filesystem. Adopt comparison now uses rendered content.
_write_kiro_agent()delegates to preflight (belt-and-suspenders). Adds
normalize_crlf_to_lfimport.src/apm_cli/integration/targets.py-- addsagentsPrimitiveMapping; updatescomment to reference Kiro CLI v3 unified harness.
tests/integration/test_kiro_agent_lifecycle.py-- new file; 7 scenarios viaApmLifecycleRunner+IsolatedApmEnvironment+LocalPackageFactory:compatible deploy/reinstall (idempotency), nested path identity, stale removal,
coexistence with steering/hooks, incompatible-tools fail-closed (no partial write),
real-binary update replacement (v1->v2 commit->reinstall proves bytes change),
and target autodetection (
.kiro/present + no--targetflag -> agent deploys).tests/spec_conformance/test_manifest_reqs.py--@pytest.mark.req("req-tg-009")conformance test;
assert_spec_containsanchors verify req-tg-009 prose in spec body.docs/src/content/docs/specs/openapm-v0.1.md-- req-tg-009 at Section 8.5.1and Appendix C traceability row.
Docs + CHANGELOG + CONFORMANCE -- targets-matrix agents column, instructions-and-agents
table, ide-tool-integration Kiro section, package-authoring tools constraint; CONFORMANCE
regenerated (108 requirements).
Diagrams
The corrected
kiro_agentdispatch loop: preflight fires before any adopt, collision,or directory mutation. Pre-placed invalid-tools targets cannot be adopted via byte-match.
flowchart LR subgraph Source["Source: .apm/agents/"] S1["agent.agent.md"] S2["team/worker.agent.md"] end subgraph Preflight["_preflight_render_kiro_agent()"] P1["parse frontmatter"]:::new P2["validate tools"]:::new P3["render filtered output"]:::new end subgraph Gate["fail-closed gate"] G1["unsupported tool?"]:::new G2["skip: no write, no mkdir"]:::new end subgraph Adopt["adopt: compare rendered bytes"] A1["existing matches rendered?"]:::new A2["adopt, no write"]:::new end subgraph Target[".kiro/agents/"] D1["agent.md"]:::new D2["team/worker.md"]:::new end S1 --> P1 S2 --> P1 P1 --> P2 P2 --> G1 G1 -->|yes| G2 G1 -->|no| P3 P3 --> A1 A1 -->|yes| A2 A1 -->|no| D1 P3 --> D2 classDef new stroke-dasharray: 5 5; class P1,P2,P3,G1,G2,A1,A2,D1,D2 new;Trade-offs
agent deploys the valid agent and emits an error diagnostic for the invalid one. Consistent
with how
codex_agenthandles unsupported surfaces.the transformed output against the on-disk file. On lockfile wipe, a format-transformed file
falls through to
check_collision(same as all format-transform targets -- accepted trade-off).agents_dir.mkdir()..kiro/agents/is not created when every agent is invalid.Behavioral improvement for kiro_agent; other formats keep eager mkdir.
modelis passed through opaquely. Kiro may warn at runtime ifunavailable. A live catalog check would require network access and a stale allowlist.
detect_by_dir=Truedrives consumer target selection, not packageauthorization. A package declaring
targets: [kiro]combined with.kiro/autodetectiondeploys agents; a package without a target declaration reaches kiro only if the consumer's
apm.yml or
--targetflag explicitly selects it. This is req-tg-008 semantics unchanged.Benefits
apm installtime -- no manual file copying.with a diagnostic naming the exact unsupported value(s) and the approved capability set.
mutation for
kiro_agent.Validation
CI-mirror lint chain (all green, HEAD d75cb30)
Test suite results
Scenario Evidence
apm install -t kirodeploys agent with filtered frontmatter (name/color stripped, body preserved)test_kiro_target.py::test_kiro_agents_deploy_plain_body_no_frontmattertest_kiro_target.py::test_kiro_agents_strip_name_and_unknown_frontmattertest_kiro_agent_lifecycle.py::test_kiro_agent_compatible_deploy_and_reinstall.apm/agents/team/X.agent.md->.kiro/agents/team/X.md(path identity)test_kiro_target.py::test_kiro_agents_nested_path_identity_derivationtest_kiro_agent_lifecycle.py::test_kiro_agent_nested_path_identitytest_kiro_target.py::test_kiro_agents_idempotent_second_deploytest_kiro_agent_lifecycle.py::test_kiro_agent_compatible_deploy_and_reinstalltest_kiro_agent_lifecycle.py::test_kiro_agent_update_replacement.kiro/agents/records from ledger and filesystemtest_kiro_target.py::test_kiro_agents_sync_removes_managed_filetest_kiro_agent_lifecycle.py::test_kiro_agent_stale_removaltest_kiro_target.py::test_kiro_agents_fail_closed_incompatible_toolstest_kiro_target.py::test_kiro_agents_no_agents_dir_created_for_all_invalidtest_kiro_agent_lifecycle.py::test_kiro_agent_incompatible_tools_fail_closedtest_kiro_target.py::test_kiro_agents_preflight_before_adopt_bypasstest_manifest_reqs.py::test_kiro_agent_tools_gate_fails_closed_before_adopt.kiro/autodetects kiro target without--targetflagtest_kiro_agent_lifecycle.py::test_kiro_target_autodetectiontest_manifest_reqs.py::test_kiro_agent_tools_gate_fails_closed_before_adopt(orphan_check: 108)test_kiro_target.py::test_kiro_agents_tools_whitespace_stripped_in_outputtest_kiro_target.py::test_kiro_agents_stale_managed_file_removed_when_tools_become_incompatibleHow to test
uv run --extra dev pytest tests/unit/integration/test_kiro_target.py -q-- 26 tests pass (includes whitespace normalization and stale reconcile regression tests).uv run --extra dev python -m tests.spec_conformance.orphan_check-- 108 requirements aligned..kiro/present: author.apm/agents/helper.agent.mdwithtools: [read]; runapm install(no--target); verify.kiro/agents/helper.mdexists with filtered frontmatter.tools: [read, BADTOOL]and reinstall -- expect diagnostic namingBADTOOL; verify no write; verify.kiro/agents/not created if absent.BASE_REF=703dd9e758fa bash tests/spec_conformance/mode_b_detector.sh-- exit 0.Closes #2089
Official sources (all accessed 2026-08-03):
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com