@garygentry/feature-forge 0.1.5 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/README.md +19 -1
  2. package/adapters/GENERATION-REPORT.md +12 -12
  3. package/adapters/claude/.feature-forge-bundle.json +6 -0
  4. package/adapters/claude/references/forge-config-schema.json +2 -2
  5. package/adapters/claude/references/portable-root.md +8 -5
  6. package/adapters/claude/references/process-overview.md +1 -1
  7. package/adapters/claude/references/shared-conventions.md +24 -5
  8. package/adapters/claude/references/stack-resolution.md +4 -1
  9. package/adapters/claude/references/stacks/go.md +1 -1
  10. package/adapters/claude/references/stacks/python.md +1 -1
  11. package/adapters/claude/references/stacks/rust.md +1 -1
  12. package/adapters/claude/references/stacks/typescript.md +1 -1
  13. package/adapters/claude/scripts/epic-manifest.py +1379 -0
  14. package/adapters/claude/scripts/forge-bootstrap.py +991 -0
  15. package/adapters/claude/scripts/forge-init.sh +44 -0
  16. package/adapters/claude/scripts/forge-root.sh +30 -8
  17. package/adapters/claude/scripts/validate-traceability.py +150 -0
  18. package/adapters/claude/skills/forge/SKILL.md +5 -5
  19. package/adapters/claude/skills/forge-0-epic/SKILL.md +6 -10
  20. package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +2 -2
  21. package/adapters/claude/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  22. package/adapters/claude/skills/forge-1-prd/SKILL.md +2 -2
  23. package/adapters/claude/skills/forge-2-tech/SKILL.md +8 -7
  24. package/adapters/claude/skills/forge-2-tech/references/stack-discovery-checklist.md +4 -4
  25. package/adapters/claude/skills/forge-3-specs/SKILL.md +1 -1
  26. package/adapters/claude/skills/forge-4-backlog/SKILL.md +2 -2
  27. package/adapters/claude/skills/forge-5-loop/SKILL.md +2 -2
  28. package/adapters/claude/skills/forge-6-docs/SKILL.md +2 -2
  29. package/adapters/claude/skills/forge-bootstrap/SKILL.md +4 -4
  30. package/adapters/claude/skills/forge-fix/SKILL.md +1 -1
  31. package/adapters/claude/skills/forge-init/SKILL.md +1 -1
  32. package/adapters/claude/skills/forge-verify/SKILL.md +7 -2
  33. package/adapters/claude/skills/forge-verify/references/verification-checklists.md +1 -1
  34. package/adapters/codex/.feature-forge-bundle.json +6 -0
  35. package/adapters/codex/agents/{forge-researcher.md → forge-researcher.toml} +4 -4
  36. package/adapters/codex/agents/{forge-spec-writer.md → forge-spec-writer.toml} +4 -4
  37. package/adapters/codex/agents/{forge-verifier.md → forge-verifier.toml} +4 -4
  38. package/adapters/codex/references/forge-config-schema.json +2 -2
  39. package/adapters/codex/references/portable-root.md +8 -5
  40. package/adapters/codex/references/process-overview.md +1 -1
  41. package/adapters/codex/references/shared-conventions.md +24 -5
  42. package/adapters/codex/references/stack-resolution.md +4 -1
  43. package/adapters/codex/references/stacks/go.md +1 -1
  44. package/adapters/codex/references/stacks/python.md +1 -1
  45. package/adapters/codex/references/stacks/rust.md +1 -1
  46. package/adapters/codex/references/stacks/typescript.md +1 -1
  47. package/adapters/codex/scripts/epic-manifest.py +1379 -0
  48. package/adapters/codex/scripts/forge-bootstrap.py +991 -0
  49. package/adapters/codex/scripts/forge-init.sh +44 -0
  50. package/adapters/codex/scripts/forge-root.sh +30 -8
  51. package/adapters/codex/scripts/validate-traceability.py +150 -0
  52. package/adapters/codex/skills/forge/{forge.md → SKILL.md} +16 -6
  53. package/adapters/codex/skills/forge-0-epic/{forge-0-epic.md → SKILL.md} +26 -20
  54. package/adapters/codex/skills/forge-0-epic/references/edit-mode.md +2 -2
  55. package/adapters/codex/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  56. package/adapters/codex/skills/forge-1-prd/{forge-1-prd.md → SKILL.md} +18 -8
  57. package/adapters/codex/skills/forge-2-tech/{forge-2-tech.md → SKILL.md} +26 -15
  58. package/adapters/codex/skills/forge-2-tech/references/stack-discovery-checklist.md +4 -4
  59. package/adapters/codex/skills/forge-3-specs/{forge-3-specs.md → SKILL.md} +16 -6
  60. package/adapters/codex/skills/forge-4-backlog/{forge-4-backlog.md → SKILL.md} +15 -5
  61. package/adapters/codex/skills/forge-5-loop/{forge-5-loop.md → SKILL.md} +27 -17
  62. package/adapters/codex/skills/forge-6-docs/{forge-6-docs.md → SKILL.md} +17 -7
  63. package/adapters/codex/skills/forge-bootstrap/{forge-bootstrap.md → SKILL.md} +17 -7
  64. package/adapters/codex/skills/forge-fix/{forge-fix.md → SKILL.md} +12 -2
  65. package/adapters/codex/skills/forge-init/{forge-init.md → SKILL.md} +11 -1
  66. package/adapters/codex/skills/forge-verify/{forge-verify.md → SKILL.md} +24 -9
  67. package/adapters/codex/skills/forge-verify/references/verification-checklists.md +1 -1
  68. package/adapters/copilot/.feature-forge-bundle.json +6 -0
  69. package/adapters/copilot/references/forge-config-schema.json +2 -2
  70. package/adapters/copilot/references/portable-root.md +8 -5
  71. package/adapters/copilot/references/process-overview.md +1 -1
  72. package/adapters/copilot/references/shared-conventions.md +24 -5
  73. package/adapters/copilot/references/stack-resolution.md +4 -1
  74. package/adapters/copilot/references/stacks/go.md +1 -1
  75. package/adapters/copilot/references/stacks/python.md +1 -1
  76. package/adapters/copilot/references/stacks/rust.md +1 -1
  77. package/adapters/copilot/references/stacks/typescript.md +1 -1
  78. package/adapters/copilot/scripts/epic-manifest.py +1379 -0
  79. package/adapters/copilot/scripts/forge-bootstrap.py +991 -0
  80. package/adapters/copilot/scripts/forge-init.sh +44 -0
  81. package/adapters/copilot/scripts/forge-root.sh +30 -8
  82. package/adapters/copilot/scripts/validate-traceability.py +150 -0
  83. package/adapters/copilot/skills/forge/forge.md +16 -6
  84. package/adapters/copilot/skills/forge-0-epic/forge-0-epic.md +26 -20
  85. package/adapters/copilot/skills/forge-0-epic/references/edit-mode.md +2 -2
  86. package/adapters/copilot/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  87. package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +18 -8
  88. package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +26 -15
  89. package/adapters/copilot/skills/forge-2-tech/references/stack-discovery-checklist.md +4 -4
  90. package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +16 -6
  91. package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +15 -5
  92. package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +27 -17
  93. package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +17 -7
  94. package/adapters/copilot/skills/forge-bootstrap/forge-bootstrap.md +17 -7
  95. package/adapters/copilot/skills/forge-fix/forge-fix.md +12 -2
  96. package/adapters/copilot/skills/forge-init/forge-init.md +11 -1
  97. package/adapters/copilot/skills/forge-verify/forge-verify.md +24 -9
  98. package/adapters/copilot/skills/forge-verify/references/verification-checklists.md +1 -1
  99. package/adapters/cursor/.feature-forge-bundle.json +6 -0
  100. package/adapters/cursor/references/forge-config-schema.json +2 -2
  101. package/adapters/cursor/references/portable-root.md +8 -5
  102. package/adapters/cursor/references/process-overview.md +1 -1
  103. package/adapters/cursor/references/shared-conventions.md +24 -5
  104. package/adapters/cursor/references/stack-resolution.md +4 -1
  105. package/adapters/cursor/references/stacks/go.md +1 -1
  106. package/adapters/cursor/references/stacks/python.md +1 -1
  107. package/adapters/cursor/references/stacks/rust.md +1 -1
  108. package/adapters/cursor/references/stacks/typescript.md +1 -1
  109. package/adapters/cursor/scripts/epic-manifest.py +1379 -0
  110. package/adapters/cursor/scripts/forge-bootstrap.py +991 -0
  111. package/adapters/cursor/scripts/forge-init.sh +44 -0
  112. package/adapters/cursor/scripts/forge-root.sh +30 -8
  113. package/adapters/cursor/scripts/validate-traceability.py +150 -0
  114. package/adapters/cursor/skills/forge/forge.mdc +16 -6
  115. package/adapters/cursor/skills/forge-0-epic/forge-0-epic.mdc +26 -20
  116. package/adapters/cursor/skills/forge-0-epic/references/edit-mode.md +2 -2
  117. package/adapters/cursor/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  118. package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +18 -8
  119. package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +26 -15
  120. package/adapters/cursor/skills/forge-2-tech/references/stack-discovery-checklist.md +4 -4
  121. package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +16 -6
  122. package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +15 -5
  123. package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +27 -17
  124. package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +17 -7
  125. package/adapters/cursor/skills/forge-bootstrap/forge-bootstrap.mdc +17 -7
  126. package/adapters/cursor/skills/forge-fix/forge-fix.mdc +12 -2
  127. package/adapters/cursor/skills/forge-init/forge-init.mdc +11 -1
  128. package/adapters/cursor/skills/forge-verify/forge-verify.mdc +24 -9
  129. package/adapters/cursor/skills/forge-verify/references/verification-checklists.md +1 -1
  130. package/adapters/gemini/.feature-forge-bundle.json +6 -0
  131. package/adapters/gemini/gemini-extension.json +1 -1
  132. package/adapters/gemini/references/forge-config-schema.json +2 -2
  133. package/adapters/gemini/references/portable-root.md +8 -5
  134. package/adapters/gemini/references/process-overview.md +1 -1
  135. package/adapters/gemini/references/shared-conventions.md +24 -5
  136. package/adapters/gemini/references/stack-resolution.md +4 -1
  137. package/adapters/gemini/references/stacks/go.md +1 -1
  138. package/adapters/gemini/references/stacks/python.md +1 -1
  139. package/adapters/gemini/references/stacks/rust.md +1 -1
  140. package/adapters/gemini/references/stacks/typescript.md +1 -1
  141. package/adapters/gemini/scripts/epic-manifest.py +1379 -0
  142. package/adapters/gemini/scripts/forge-bootstrap.py +991 -0
  143. package/adapters/gemini/scripts/forge-init.sh +44 -0
  144. package/adapters/gemini/scripts/forge-root.sh +30 -8
  145. package/adapters/gemini/scripts/validate-traceability.py +150 -0
  146. package/adapters/gemini/skills/forge/forge.md +16 -6
  147. package/adapters/gemini/skills/forge-0-epic/forge-0-epic.md +26 -20
  148. package/adapters/gemini/skills/forge-0-epic/references/edit-mode.md +2 -2
  149. package/adapters/gemini/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
  150. package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +18 -8
  151. package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +26 -15
  152. package/adapters/gemini/skills/forge-2-tech/references/stack-discovery-checklist.md +4 -4
  153. package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +16 -6
  154. package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +15 -5
  155. package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +27 -17
  156. package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +17 -7
  157. package/adapters/gemini/skills/forge-bootstrap/forge-bootstrap.md +17 -7
  158. package/adapters/gemini/skills/forge-fix/forge-fix.md +12 -2
  159. package/adapters/gemini/skills/forge-init/forge-init.md +11 -1
  160. package/adapters/gemini/skills/forge-verify/forge-verify.md +24 -9
  161. package/adapters/gemini/skills/forge-verify/references/verification-checklists.md +1 -1
  162. package/dist/agent-targets.d.ts +20 -4
  163. package/dist/agent-targets.js +29 -4
  164. package/dist/apply.js +245 -18
  165. package/dist/cli.js +12 -6
  166. package/dist/hash.d.ts +5 -0
  167. package/dist/hash.js +7 -0
  168. package/dist/manifest.d.ts +4 -2
  169. package/dist/manifest.js +58 -2
  170. package/dist/placements.d.ts +69 -0
  171. package/dist/placements.js +116 -0
  172. package/dist/plan.d.ts +7 -0
  173. package/dist/plan.js +87 -1
  174. package/dist/rauf.d.ts +4 -4
  175. package/dist/rauf.js +3 -3
  176. package/dist/report.js +21 -0
  177. package/dist/source.d.ts +4 -3
  178. package/dist/source.js +4 -3
  179. package/dist/types.d.ts +163 -19
  180. package/dist/types.js +42 -11
  181. package/package.json +1 -1
  182. package/adapters/codex/agents/openai.yaml +0 -10
package/dist/types.d.ts CHANGED
@@ -32,19 +32,76 @@ export declare const EXIT: {
32
32
  readonly USAGE: 2;
33
33
  };
34
34
  export type ExitCode = (typeof EXIT)[keyof typeof EXIT];
35
- /** Manifest schema version; bumped only on a breaking manifest-shape change. */
36
- export declare const SCHEMA_VERSION: 1;
35
+ /**
36
+ * Manifest schema version. v2 (A4b) adds the optional `placements[]` array for agents whose
37
+ * install spans a second filesystem root (codex `.codex/agents`, copilot `.github/copilot-
38
+ * instructions.md`). A v1 manifest (no `placements`) is still read verbatim by the back-compat
39
+ * reader — bumped only on a breaking manifest-shape change.
40
+ */
41
+ export declare const SCHEMA_VERSION: 2;
42
+ /** Versions of the manifest this installer can READ (write is always SCHEMA_VERSION). */
43
+ export declare const READABLE_SCHEMA_VERSIONS: readonly [1, 2];
44
+ /** A manifest schemaVersion this installer accepts on read (back-compat v1 + current v2). */
45
+ export type ReadableSchemaVersion = (typeof READABLE_SCHEMA_VERSIONS)[number];
37
46
  /** The single namespace directory name written inside each agent's install location [D5]. */
38
47
  export declare const FEATURE_FORGE_NS: "feature-forge";
39
48
  /** Filename prefix for the hidden parent-sibling manifest, completed by the scope (§3, spec 05). */
40
49
  export declare const MANIFEST_PREFIX: ".feature-forge.";
50
+ /**
51
+ * How honestly an agent's install paths track current vendor docs (Finding 6 / A4).
52
+ * - "confirmed" — source-verified end-to-end (claude).
53
+ * - "verified-current" — matches the vendor's current docs, re-verified in A0 (2026-06-26).
54
+ * - "best-known" — plausible but not doc-confirmed for this scope; install proceeds,
55
+ * labeled honestly in the report so users know it may not be loaded.
56
+ * - "unsupported" — no usable install surface; not installed (reserved; none today).
57
+ */
58
+ export type Confidence = "confirmed" | "verified-current" | "best-known" | "unsupported";
59
+ /** How an agent consumes the bundle (documentation + future per-kind apply behavior). */
60
+ export type InstallKind = "skills" | "extension" | "rules" | "instructions";
61
+ /**
62
+ * Kind of a SECONDARY install placement (A4b). The primary bundle (the `feature-forge/` namespace
63
+ * dir) is always present and is never a placement; placements describe extra writes under a
64
+ * DIFFERENT filesystem root than the primary bundle:
65
+ * - "mirror" — copy a subset of bundle files flat into a second dir (codex `.codex/agents/`,
66
+ * where Codex loads custom agents — it does not read them from `.agents/skills`).
67
+ * - "managed-block" — write/merge a sentinel-delimited block into a (possibly user-owned) instructions
68
+ * file (copilot `.github/copilot-instructions.md`), preserving the rest of the file.
69
+ */
70
+ export type PlacementKind = "mirror" | "managed-block";
71
+ /** HTML-comment sentinels delimiting a `managed-block` placement (mirrors rauf's convention). */
72
+ export declare const MANAGED_BLOCK_START: "<!-- feature-forge:managed:start -->";
73
+ export declare const MANAGED_BLOCK_END: "<!-- feature-forge:managed:end -->";
74
+ /**
75
+ * Declarative descriptor of one secondary placement on an {@link AgentTarget} (A4b). Pure data, so a
76
+ * new agent (or a new second-root rule) stays one table edit (REQ-SCALE-01). The absolute root and
77
+ * destination are derived under a scope by {@link resolvePlacements}; nothing here is stored.
78
+ */
79
+ export interface PlacementSpec {
80
+ readonly kind: PlacementKind;
81
+ /** Second-root dir under the scope root, e.g. ".codex" (mirror) or ".github" (managed-block). */
82
+ readonly baseDir: string;
83
+ /**
84
+ * Path under `baseDir`. For "mirror" this is the destination DIR (e.g. "agents"); for
85
+ * "managed-block" this is the target FILE (e.g. "copilot-instructions.md").
86
+ */
87
+ readonly subpath: string;
88
+ /**
89
+ * "mirror" only: bundle-relative prefix selecting which source files to copy (e.g. "agents/").
90
+ * Files matching the prefix are copied FLAT (basename only) into the placement destination.
91
+ */
92
+ readonly sourcePrefix?: string;
93
+ }
41
94
  /**
42
95
  * One row of the static per-agent detection map (REQ-DET-01, REQ-DET-05). Adding a new
43
96
  * agent is exactly adding one entry to `AGENT_TARGETS` — no logic change (REQ-SCALE-01).
44
97
  *
45
98
  * The on-disk destination for an agent under a given scope is derived, not stored:
46
- * <scopeRoot>/<configDirName>/<installSubdir>/<FEATURE_FORGE_NS>/
47
- * where scopeRoot is the resolved home (global) or cwd (project).
99
+ * <scopeRoot>/<installBaseDir>/<installSubpath>/<FEATURE_FORGE_NS>/
100
+ * where scopeRoot is the resolved home (global) or cwd (project), and `installSubpath` may
101
+ * be "" (installed directly under `installBaseDir`). Detection (`configDirName`) is decoupled
102
+ * from the install location because some agents load content from a different tree than the
103
+ * dir that signals their presence (A4): codex detects ".codex" but loads skills from
104
+ * ".agents/skills"; copilot detects ".copilot" but instructions live under ".github".
48
105
  */
49
106
  export interface AgentTarget {
50
107
  /** Stable agent identifier. */
@@ -55,22 +112,36 @@ export interface AgentTarget {
55
112
  */
56
113
  readonly configDirName: string;
57
114
  /**
58
- * Sub-path under the config dir that holds the namespaced install dir, e.g.
59
- * "skills" (claude/codex/copilot), "rules" (cursor), "extensions" (gemini).
115
+ * Top-level dir under the scope root that holds the install AND is the containment boundary
116
+ * every write is checked against (REQ-SEC-02). Usually equals `configDirName`; decoupled for
117
+ * codex (".agents") and copilot (".github").
118
+ */
119
+ readonly installBaseDir: string;
120
+ /**
121
+ * Path under `installBaseDir` to the namespace parent, e.g. "skills" (claude/codex),
122
+ * "rules" (cursor), "extensions" (gemini), "" (copilot — directly under `.github`).
60
123
  */
61
- readonly installSubdir: string;
124
+ readonly installSubpath: string;
125
+ /** How this agent consumes the bundle (REQ-SCALE-01; per-kind placement extended in A4b). */
126
+ readonly installKind: InstallKind;
62
127
  /**
63
- * Informational: the skill-file form this agent's bundle uses — "SKILL.md" (claude),
64
- * "<name>.md" (codex/copilot/gemini), "<name>.mdc" (cursor). The installer copies the
128
+ * Informational: the skill-file form this agent's bundle uses — "SKILL.md" (claude, codex),
129
+ * "<name>.md" (copilot/gemini), "<name>.mdc" (cursor). The installer copies the
65
130
  * bundle verbatim (REQ-SCALE-02) and does not parse skill files, so this is documentation.
66
131
  */
67
132
  readonly skillFileForm: string;
133
+ /** Confidence for the default (global) scope. */
134
+ readonly confidence: Confidence;
135
+ /** Optional scope-specific override for project scope (e.g. gemini project = best-known). */
136
+ readonly projectConfidence?: Confidence;
137
+ /** Current vendor/docs URL for this target's install convention (surfaced in reports). */
138
+ readonly docsUrl: string;
68
139
  /**
69
- * Confidence in this row's paths. "confirmed" = source-verified (claude). "best-known"
70
- * = the TQ-1 paths (codex/copilot/cursor/gemini) to re-verify against each agent's current
71
- * docs at implementation (REQ-SCALE-01 isolated, localized correction).
140
+ * Secondary install placements under a DIFFERENT root than the primary bundle (A4b). Absent for
141
+ * agents whose whole install is the single namespace dir (claude/cursor/gemini). Declarative data
142
+ * only resolved to absolute roots by {@link resolvePlacements}; a new rule is one table edit.
72
143
  */
73
- readonly confidence: "confirmed" | "best-known";
144
+ readonly placements?: readonly PlacementSpec[];
74
145
  }
75
146
  /** Options for path resolution, injectable so tests never touch the real `~` (spec 02, spec 08). */
76
147
  export interface ResolveOpts {
@@ -95,6 +166,10 @@ export interface DetectionResult {
95
166
  readonly cliOnPath?: boolean;
96
167
  /** Resolved absolute install destination for the active scope (the `feature-forge/` namespace dir). */
97
168
  readonly destination: string;
169
+ /** Effective confidence for the active scope (REQ-DET-05; honest dry-run/list labeling, A4). */
170
+ readonly confidence: Confidence;
171
+ /** Current vendor/docs URL for this target (REQ-DET-05). */
172
+ readonly docsUrl: string;
98
173
  }
99
174
  /** One file recorded in the manifest inventory (REQ-SAFE-01). */
100
175
  export interface ManifestFile {
@@ -103,13 +178,30 @@ export interface ManifestFile {
103
178
  /** SHA-256 of the written bytes. Omitted for symlink mode (no per-file copy exists). */
104
179
  readonly sha256?: string;
105
180
  }
181
+ /**
182
+ * One persisted SECONDARY placement (manifest v2, A4b). Records the absolute second root + dest and
183
+ * an inventory of what we wrote there, so `update`/`uninstall` reconcile it exactly like the primary
184
+ * bundle but under its own containment boundary (`root`). For "managed-block", `files` holds a single
185
+ * entry whose `path` is the file basename and whose `sha256` fingerprints the block region we wrote
186
+ * (drift/clean detection); the rest of that file is user-owned and never recorded.
187
+ */
188
+ export interface Placement {
189
+ readonly kind: PlacementKind;
190
+ /** Absolute containment boundary every write for this placement is checked against (REQ-SEC-02). */
191
+ readonly root: string;
192
+ /** Absolute destination: a DIR ("mirror") or a FILE ("managed-block"). */
193
+ readonly destination: string;
194
+ /** Per-file inventory written under this placement (paths relative to `destination`'s dir). */
195
+ readonly files: ManifestFile[];
196
+ }
106
197
  /**
107
198
  * The persisted per-install manifest (REQ-SAFE-01/03), written as the hidden parent-sibling
108
199
  * `<installSubdir>/.feature-forge.<scope>.json` (spec 05). It is the sole record `list`/`update`/
109
200
  * `uninstall` use to tell installer-written content from user content and to detect drift.
110
201
  */
111
202
  export interface InstallManifest {
112
- readonly schemaVersion: typeof SCHEMA_VERSION;
203
+ /** Always {@link SCHEMA_VERSION} when written; v1 is still accepted on read (back-compat). */
204
+ readonly schemaVersion: ReadableSchemaVersion;
113
205
  readonly agent: AgentId;
114
206
  readonly scope: Scope;
115
207
  readonly mode: Mode;
@@ -124,7 +216,7 @@ export interface InstallManifest {
124
216
  readonly featureForgeVersion: string | null;
125
217
  /** SHA-256 over the source bundle's canonical (sorted-path) file set — drift anchor (OQ-4, spec 03). */
126
218
  readonly sourceHash: string;
127
- /** Pinned rauf coordinate recorded at install, e.g. "@garygentry/rauf@0.8.0"; `null` if `--skip-rauf` (spec 06). */
219
+ /** Pinned rauf coordinate recorded at install, e.g. "@garygentry/rauf@0.8.1"; `null` if `--skip-rauf` (spec 06). */
128
220
  readonly raufPin: string | null;
129
221
  /** ISO-8601 timestamps. */
130
222
  readonly installedAt: string;
@@ -137,6 +229,11 @@ export interface InstallManifest {
137
229
  readonly link?: {
138
230
  readonly target: string;
139
231
  };
232
+ /**
233
+ * Secondary placements written under a different root than the primary bundle (manifest v2, A4b).
234
+ * Absent on agents without a second-root rule (claude/cursor/gemini) and on legacy v1 manifests.
235
+ */
236
+ readonly placements?: Placement[];
140
237
  }
141
238
  /**
142
239
  * The per-file action the planner assigns by diffing source ⇆ destination ⇆ manifest (spec 04).
@@ -165,6 +262,36 @@ export interface PlannedAction {
165
262
  readonly files: FileAction[];
166
263
  /** Surfaced in the plan/report for visibility (spec 06); not a file action. */
167
264
  readonly raufPin?: string | null;
265
+ /**
266
+ * Resolved secondary-placement plans (A4b). Each carries its own absolute root + destination, the
267
+ * per-file diff actions, and (for "managed-block") the exact block content a real run will write —
268
+ * so dry-run shows, and `apply` performs, identical work. Absent when the agent has no placements.
269
+ */
270
+ readonly placements?: PlannedPlacement[];
271
+ }
272
+ /**
273
+ * One secondary placement's resolved plan (A4b): the dry-run = real-run unit for a second root. The
274
+ * planner fills `files` by diffing source ⇆ destination (same classifier as the primary bundle) and,
275
+ * for "managed-block", attaches the rendered `blockContent` the apply step writes between sentinels.
276
+ */
277
+ export interface PlannedPlacement {
278
+ readonly kind: PlacementKind;
279
+ /** Absolute containment boundary (REQ-SEC-02). */
280
+ readonly root: string;
281
+ /** Absolute destination dir ("mirror") or file ("managed-block"). */
282
+ readonly destination: string;
283
+ /**
284
+ * Per-file diff actions. "mirror" entries carry `srcRelpath` (the bundle-relative source to copy);
285
+ * "managed-block" has a single entry whose `relpath` is the file basename (no `srcRelpath`).
286
+ */
287
+ readonly files: PlacementFileAction[];
288
+ /** "managed-block" only: the rendered block body (without sentinels) a create/overwrite writes. */
289
+ readonly blockContent?: string;
290
+ }
291
+ /** A placement file action: a {@link FileAction} plus the bundle-relative source for "mirror" copies. */
292
+ export interface PlacementFileAction extends FileAction {
293
+ /** "mirror" only: bundle-relative source path to copy into `<destination>/<relpath>`. */
294
+ readonly srcRelpath?: string;
168
295
  }
169
296
  /** One agent's outcome in a run summary (REQ-OBS-01/03). */
170
297
  export interface AgentReport {
@@ -177,6 +304,10 @@ export interface AgentReport {
177
304
  /** Present iff `ok` is false. */
178
305
  readonly error?: InstallerError;
179
306
  readonly raufPin?: string | null;
307
+ /** Effective install-path confidence for the active scope (A4; honest report labeling). */
308
+ readonly confidence?: Confidence;
309
+ /** Vendor/docs URL for this target (A4; shown when confidence is not full). */
310
+ readonly docsUrl?: string;
180
311
  }
181
312
  /** The whole-run summary, rendered human-readable or as `--json` (REQ-OBS-01, REQ-DET-05). */
182
313
  export interface RunReport {
@@ -205,17 +336,30 @@ export interface RunReport {
205
336
  *
206
337
  * Verified ground truth: every bundle has `skills/` (11 skills), `references/`,
207
338
  * `scripts/forge-root.sh`, `agents/`; gemini adds a root `gemini-extension.json`,
208
- * codex adds `agents/openai.yaml`, cursor uses `.mdc` files.
339
+ * codex ships `skills/<name>/SKILL.md` + standalone `agents/<name>.toml` custom agents,
340
+ * cursor uses `.mdc` files.
341
+ *
342
+ * A4 per-agent reality check (A0 re-verified vendor docs, 2026-06-26):
343
+ * - codex — detects `.codex`, loads skills from `.agents/skills` (verified-current).
344
+ * The `.codex/agents/*.toml` second placement is added in A4b.
345
+ * - copilot — detects `.copilot`, but has no skills loader; the bundle is staged under
346
+ * `.github/feature-forge` and the managed instructions block (.github/
347
+ * copilot-instructions.md) is added in A4b (best-known).
348
+ * - cursor — `.cursor/rules/*.mdc` confirmed current (verified-current).
349
+ * - gemini — `~/.gemini/extensions/feature-forge` global confirmed; project scope is
350
+ * best-known (project extension install is not clearly documented).
209
351
  */
210
352
  export declare const AGENT_TARGETS: Readonly<Record<AgentId, AgentTarget>>;
211
353
  /**
212
354
  * Minimal integrity check (REQ-OPS-06, spec 03): a located bundle is valid iff `skills/` is a
213
- * non-empty dir, `scripts/forge-root.sh` exists, and — for gemini only — `gemini-extension.json`
214
- * exists at the bundle root. Defined here as data so the check is a localized table read.
355
+ * non-empty dir, the neutral bundle sentinel `.feature-forge-bundle.json` exists, every runtime
356
+ * helper script a skill can invoke is present (so helper-backed skills run after install on ANY
357
+ * agent), and — for gemini only — `gemini-extension.json` exists at the bundle root. Defined here
358
+ * as data so the check is a localized table read.
215
359
  */
216
360
  export declare const BUNDLE_REQUIRED_PATHS: {
217
361
  /** Required of every agent bundle. */
218
- readonly common: readonly ["skills", "scripts/forge-root.sh"];
362
+ readonly common: readonly ["skills", ".feature-forge-bundle.json", "scripts/forge-root.sh", "scripts/forge-init.sh", "scripts/epic-manifest.py", "scripts/validate-traceability.py", "scripts/forge-bootstrap.py"];
219
363
  /** Additional per-agent requirements. */
220
364
  readonly perAgent: Partial<Record<AgentId, readonly string[]>>;
221
365
  };
package/dist/types.js CHANGED
@@ -15,12 +15,22 @@
15
15
  export const AGENT_IDS = ["claude", "codex", "copilot", "cursor", "gemini"];
16
16
  /** Process exit codes (REQ-OBS-01/03, spec 07). */
17
17
  export const EXIT = { SUCCESS: 0, FAILURE: 1, USAGE: 2 };
18
- /** Manifest schema version; bumped only on a breaking manifest-shape change. */
19
- export const SCHEMA_VERSION = 1;
18
+ /**
19
+ * Manifest schema version. v2 (A4b) adds the optional `placements[]` array for agents whose
20
+ * install spans a second filesystem root (codex `.codex/agents`, copilot `.github/copilot-
21
+ * instructions.md`). A v1 manifest (no `placements`) is still read verbatim by the back-compat
22
+ * reader — bumped only on a breaking manifest-shape change.
23
+ */
24
+ export const SCHEMA_VERSION = 2;
25
+ /** Versions of the manifest this installer can READ (write is always SCHEMA_VERSION). */
26
+ export const READABLE_SCHEMA_VERSIONS = [1, 2];
20
27
  /** The single namespace directory name written inside each agent's install location [D5]. */
21
28
  export const FEATURE_FORGE_NS = "feature-forge";
22
29
  /** Filename prefix for the hidden parent-sibling manifest, completed by the scope (§3, spec 05). */
23
30
  export const MANIFEST_PREFIX = ".feature-forge.";
31
+ /** HTML-comment sentinels delimiting a `managed-block` placement (mirrors rauf's convention). */
32
+ export const MANAGED_BLOCK_START = "<!-- feature-forge:managed:start -->";
33
+ export const MANAGED_BLOCK_END = "<!-- feature-forge:managed:end -->";
24
34
  // ---------------------------------------------------------------------------
25
35
  // 6. Constants — the `AGENT_TARGETS` table
26
36
  // ---------------------------------------------------------------------------
@@ -31,23 +41,44 @@ export const MANIFEST_PREFIX = ".feature-forge.";
31
41
  *
32
42
  * Verified ground truth: every bundle has `skills/` (11 skills), `references/`,
33
43
  * `scripts/forge-root.sh`, `agents/`; gemini adds a root `gemini-extension.json`,
34
- * codex adds `agents/openai.yaml`, cursor uses `.mdc` files.
44
+ * codex ships `skills/<name>/SKILL.md` + standalone `agents/<name>.toml` custom agents,
45
+ * cursor uses `.mdc` files.
46
+ *
47
+ * A4 per-agent reality check (A0 re-verified vendor docs, 2026-06-26):
48
+ * - codex — detects `.codex`, loads skills from `.agents/skills` (verified-current).
49
+ * The `.codex/agents/*.toml` second placement is added in A4b.
50
+ * - copilot — detects `.copilot`, but has no skills loader; the bundle is staged under
51
+ * `.github/feature-forge` and the managed instructions block (.github/
52
+ * copilot-instructions.md) is added in A4b (best-known).
53
+ * - cursor — `.cursor/rules/*.mdc` confirmed current (verified-current).
54
+ * - gemini — `~/.gemini/extensions/feature-forge` global confirmed; project scope is
55
+ * best-known (project extension install is not clearly documented).
35
56
  */
36
57
  export const AGENT_TARGETS = {
37
- claude: { id: "claude", configDirName: ".claude", installSubdir: "skills", skillFileForm: "SKILL.md", confidence: "confirmed" },
38
- codex: { id: "codex", configDirName: ".codex", installSubdir: "skills", skillFileForm: "<name>.md", confidence: "best-known" },
39
- copilot: { id: "copilot", configDirName: ".copilot", installSubdir: "skills", skillFileForm: "<name>.md", confidence: "best-known" },
40
- cursor: { id: "cursor", configDirName: ".cursor", installSubdir: "rules", skillFileForm: "<name>.mdc", confidence: "best-known" },
41
- gemini: { id: "gemini", configDirName: ".gemini", installSubdir: "extensions", skillFileForm: "<name>.md", confidence: "best-known" },
58
+ claude: { id: "claude", configDirName: ".claude", installBaseDir: ".claude", installSubpath: "skills", installKind: "skills", skillFileForm: "SKILL.md", confidence: "confirmed", docsUrl: "https://docs.claude.com/en/docs/claude-code/skills" },
59
+ codex: { id: "codex", configDirName: ".codex", installBaseDir: ".agents", installSubpath: "skills", installKind: "skills", skillFileForm: "SKILL.md", confidence: "verified-current", docsUrl: "https://developers.openai.com/codex/skills", placements: [{ kind: "mirror", baseDir: ".codex", subpath: "agents", sourcePrefix: "agents/" }] },
60
+ copilot: { id: "copilot", configDirName: ".copilot", installBaseDir: ".github", installSubpath: "", installKind: "instructions", skillFileForm: "<name>.md", confidence: "best-known", docsUrl: "https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions", placements: [{ kind: "managed-block", baseDir: ".github", subpath: "copilot-instructions.md" }] },
61
+ cursor: { id: "cursor", configDirName: ".cursor", installBaseDir: ".cursor", installSubpath: "rules", installKind: "rules", skillFileForm: "<name>.mdc", confidence: "verified-current", docsUrl: "https://cursor.com/docs/context/rules" },
62
+ gemini: { id: "gemini", configDirName: ".gemini", installBaseDir: ".gemini", installSubpath: "extensions", installKind: "extension", skillFileForm: "<name>.md", confidence: "verified-current", projectConfidence: "best-known", docsUrl: "https://github.com/google-gemini/gemini-cli/blob/main/docs/extensions/index.md" },
42
63
  };
43
64
  /**
44
65
  * Minimal integrity check (REQ-OPS-06, spec 03): a located bundle is valid iff `skills/` is a
45
- * non-empty dir, `scripts/forge-root.sh` exists, and — for gemini only — `gemini-extension.json`
46
- * exists at the bundle root. Defined here as data so the check is a localized table read.
66
+ * non-empty dir, the neutral bundle sentinel `.feature-forge-bundle.json` exists, every runtime
67
+ * helper script a skill can invoke is present (so helper-backed skills run after install on ANY
68
+ * agent), and — for gemini only — `gemini-extension.json` exists at the bundle root. Defined here
69
+ * as data so the check is a localized table read.
47
70
  */
48
71
  export const BUNDLE_REQUIRED_PATHS = {
49
72
  /** Required of every agent bundle. */
50
- common: ["skills", "scripts/forge-root.sh"],
73
+ common: [
74
+ "skills",
75
+ ".feature-forge-bundle.json",
76
+ "scripts/forge-root.sh",
77
+ "scripts/forge-init.sh",
78
+ "scripts/epic-manifest.py",
79
+ "scripts/validate-traceability.py",
80
+ "scripts/forge-bootstrap.py",
81
+ ],
51
82
  /** Additional per-agent requirements. */
52
83
  perAgent: { gemini: ["gemini-extension.json"] },
53
84
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garygentry/feature-forge",
3
- "version": "0.1.5",
3
+ "version": "0.2.1",
4
4
  "description": "Cross-agent installer for the feature-forge skill suite — installs the canonical forge pipeline into Claude, Codex, Copilot, Cursor, or Gemini.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,10 +0,0 @@
1
- _generated:
2
- source: agents/
3
- regenerate: python3 scripts/build-adapters.py
4
- agents:
5
- - name: forge-researcher
6
- description: Explores the codebase to understand package structure, integration points, existing patterns, and conventions. Use during feature planning, especially when running /feature-forge:forge-2-tech. Returns a distilled integration report without polluting the main conversation's context window.
7
- - name: forge-spec-writer
8
- description: Authors exactly one numbered implementation spec document for a forge feature, to the quality bar in forge-3-specs. Dispatched by forge-3-specs as one of several parallel writers, after the shared foundation docs (00-core-definitions, 01-architecture-layout) are already written. Writes only its single assigned file and returns a requirement-coverage manifest.
9
- - name: forge-verifier
10
- description: Verifies feature forge pipeline artifacts for completeness, consistency, and quality. Delegates to this agent when running /feature-forge:forge-verify or when the user asks to check specs, backlog, or implementation for gaps. This agent has read-only tools and persistent memory — it cannot modify files, only analyze and report findings.