@amsterdamdatalabs/enact-extensions 0.1.58 → 0.1.62

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.
@@ -16,7 +16,16 @@ export interface FileAction {
16
16
  action: "create" | "update" | "remove" | "remove-dir" | "skip";
17
17
  reason: string;
18
18
  }
19
+ interface FilePathStat {
20
+ isFile(): boolean;
21
+ isDirectory(): boolean;
22
+ isSymbolicLink(): boolean;
23
+ }
19
24
  export interface FileOps {
25
+ /** Observe the filesystem after all operations planned so far. */
26
+ lstat(rel: string): FilePathStat | undefined;
27
+ /** Whether a path exists after all operations planned so far. */
28
+ exists(rel: string): boolean;
20
29
  /** Write `content`; false when the file already has exactly those bytes. */
21
30
  write(rel: string, content: string | Buffer, reason?: string): boolean;
22
31
  /** Remove a file; false when it is not there. */
@@ -27,10 +36,9 @@ export interface FileOps {
27
36
  removeDir(rel: string, reason?: string): boolean;
28
37
  /** Remove a directory only when it is empty. */
29
38
  rmdirIfEmpty(rel: string): void;
30
- /** Create or repoint a managed symlink. */
31
- symlink(rel: string, target: string, reason?: string): boolean;
32
- /** Remove a managed symlink, dangling or not. */
39
+ /** Remove a legacy managed symlink, dangling or not, without following it. */
33
40
  removeSymlink(rel: string, reason?: string): boolean;
34
41
  }
35
42
  export declare function makeFileOps(repo: string, dryRun: boolean, actions: FileAction[]): FileOps;
43
+ export {};
36
44
  //# sourceMappingURL=file-ops.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-ops.d.ts","sourceRoot":"","sources":["../../src/internal/file-ops.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,MAAM,CAAC;IAC/D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,4EAA4E;IAC5E,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACvE,iDAAiD;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9C,4EAA4E;IAC5E,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3C,kDAAkD;IAClD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjD,gDAAgD;IAChD,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,2CAA2C;IAC3C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,iDAAiD;IACjD,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtD;AAMD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAmFzF"}
1
+ {"version":3,"file":"file-ops.d.ts","sourceRoot":"","sources":["../../src/internal/file-ops.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,MAAM,CAAC;IAC/D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,YAAY;IACpB,MAAM,IAAI,OAAO,CAAC;IAClB,WAAW,IAAI,OAAO,CAAC;IACvB,cAAc,IAAI,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,OAAO;IACtB,kEAAkE;IAClE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAC7C,iEAAiE;IACjE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,4EAA4E;IAC5E,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACvE,iDAAiD;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9C,4EAA4E;IAC5E,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3C,kDAAkD;IAClD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjD,gDAAgD;IAChD,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,8EAA8E;IAC9E,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtD;AAMD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAqJzF"}
@@ -1,31 +1,115 @@
1
- import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, readlinkSync, rmdirSync, rmSync, symlinkSync, writeFileSync, } from "node:fs";
1
+ import { lstatSync, mkdirSync, readdirSync, readFileSync, rmdirSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
3
  const abs = (repo, rel) => join(repo, ...rel.split("/"));
4
4
  const DEFAULT_REASON = "managed by enact-repo install";
5
5
  export function makeFileOps(repo, dryRun, actions) {
6
- return {
6
+ const removedRoots = new Set();
7
+ const virtualFiles = new Map();
8
+ const virtualDirs = new Set();
9
+ const underRemovedRoot = (rel) => [...removedRoots].some((root) => rel === root || rel.startsWith(`${root}/`));
10
+ const virtualLstat = (rel) => {
11
+ if (virtualFiles.has(rel)) {
12
+ return { isFile: () => true, isDirectory: () => false, isSymbolicLink: () => false };
13
+ }
14
+ if (virtualDirs.has(rel)) {
15
+ return { isFile: () => false, isDirectory: () => true, isSymbolicLink: () => false };
16
+ }
17
+ if (underRemovedRoot(rel))
18
+ return undefined;
19
+ return lstatSync(abs(repo, rel), { throwIfNoEntry: false });
20
+ };
21
+ const hasSymlinkAncestor = (rel) => {
22
+ const parts = rel.split("/").slice(0, -1);
23
+ for (let i = 1; i <= parts.length; i++) {
24
+ const st = virtualLstat(parts.slice(0, i).join("/"));
25
+ if (!st)
26
+ return false;
27
+ if (st.isSymbolicLink())
28
+ return true;
29
+ if (!st.isDirectory())
30
+ return false;
31
+ }
32
+ return false;
33
+ };
34
+ const markRemoved = (rel) => {
35
+ for (const path of virtualFiles.keys())
36
+ if (path === rel || path.startsWith(`${rel}/`))
37
+ virtualFiles.delete(path);
38
+ for (const path of virtualDirs)
39
+ if (path === rel || path.startsWith(`${rel}/`))
40
+ virtualDirs.delete(path);
41
+ removedRoots.add(rel);
42
+ };
43
+ const markWritten = (rel, content) => {
44
+ const parts = rel.split("/").slice(0, -1);
45
+ for (let i = 1; i <= parts.length; i++) {
46
+ const dirRel = parts.slice(0, i).join("/");
47
+ if (!virtualLstat(dirRel))
48
+ virtualDirs.add(dirRel);
49
+ }
50
+ virtualFiles.set(rel, content);
51
+ };
52
+ const virtualDirectoryIsEmpty = (rel) => {
53
+ const prefix = `${rel}/`;
54
+ if ([...virtualFiles.keys(), ...virtualDirs].some((path) => path.startsWith(prefix)))
55
+ return false;
56
+ if (underRemovedRoot(rel))
57
+ return true;
58
+ return readdirSync(abs(repo, rel)).every((name) => virtualLstat(`${rel}/${name}`) === undefined);
59
+ };
60
+ const fileAlreadyHasContent = (rel, existing, content) => {
61
+ if (!existing?.isFile() || existing.isSymbolicLink())
62
+ return false;
63
+ return (virtualFiles.get(rel) ?? readFileSync(abs(repo, rel))).equals(content);
64
+ };
65
+ const writeToDisk = (path, existing, content) => {
66
+ if (dryRun)
67
+ return;
68
+ if (existing?.isSymbolicLink())
69
+ rmSync(path, { force: true });
70
+ mkdirSync(dirname(path), { recursive: true });
71
+ writeFileSync(path, content);
72
+ };
73
+ const ops = {
74
+ lstat(rel) {
75
+ return virtualLstat(rel);
76
+ },
77
+ exists(rel) {
78
+ return virtualLstat(rel) !== undefined;
79
+ },
7
80
  write(rel, content, reason) {
8
81
  const path = abs(repo, rel);
9
82
  const buf = Buffer.isBuffer(content) ? content : Buffer.from(content);
10
- const existed = existsSync(path);
83
+ if (hasSymlinkAncestor(rel)) {
84
+ throw new Error(`Refusing to write managed file through a symlinked ancestor: ${rel}`);
85
+ }
86
+ const existing = virtualLstat(rel);
87
+ const existed = existing !== undefined;
11
88
  // Byte-identical is a no-op, so a re-install reports nothing and stays
12
- // idempotent rather than churning mtimes and dry-run output.
13
- if (existed && readFileSync(path).equals(buf))
89
+ // idempotent rather than churning mtimes and dry-run output. A symlink is
90
+ // never a managed file even when its target has identical bytes.
91
+ if (fileAlreadyHasContent(rel, existing, buf))
14
92
  return false;
15
93
  actions.push({ file: rel, action: existed ? "update" : "create", reason: reason ?? DEFAULT_REASON });
16
- if (!dryRun) {
17
- mkdirSync(dirname(path), { recursive: true });
18
- writeFileSync(path, buf);
19
- }
94
+ writeToDisk(path, existing, buf);
95
+ markWritten(rel, buf);
20
96
  return true;
21
97
  },
22
98
  remove(rel, reason) {
23
99
  const path = abs(repo, rel);
24
- if (!existsSync(path))
100
+ if (hasSymlinkAncestor(rel))
101
+ return false;
102
+ const existing = virtualLstat(rel);
103
+ if (!existing)
25
104
  return false;
26
105
  actions.push({ file: rel, action: "remove", reason: reason ?? DEFAULT_REASON });
27
- if (!dryRun)
28
- rmSync(path, { force: true });
106
+ if (!dryRun) {
107
+ if (existing.isSymbolicLink())
108
+ unlinkSync(path);
109
+ else
110
+ rmSync(path, { force: true });
111
+ }
112
+ markRemoved(rel);
29
113
  return true;
30
114
  },
31
115
  // Recorded rather than silently passed over: a retained file that appears
@@ -36,58 +120,47 @@ export function makeFileOps(repo, dryRun, actions) {
36
120
  },
37
121
  removeDir(rel, reason) {
38
122
  const path = abs(repo, rel);
39
- if (!existsSync(path))
123
+ if (hasSymlinkAncestor(rel))
124
+ return false;
125
+ const existing = virtualLstat(rel);
126
+ if (!existing)
40
127
  return false;
41
128
  actions.push({ file: rel, action: "remove-dir", reason: reason ?? "directory" });
42
- // macOS may create .DS_Store while Finder or a launched host observes a
43
- // root being rebuilt. Retry Node's documented transient recursive-delete
44
- // errors (including ENOTEMPTY) rather than leaving an owned root half
45
- // removed.
46
- if (!dryRun)
47
- rmSync(path, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
129
+ if (!dryRun) {
130
+ if (existing.isSymbolicLink())
131
+ unlinkSync(path);
132
+ else
133
+ rmSync(path, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
134
+ }
135
+ markRemoved(rel);
48
136
  return true;
49
137
  },
50
138
  rmdirIfEmpty(rel) {
51
139
  const path = abs(repo, rel);
52
- if (existsSync(path) && readdirSync(path).length === 0) {
140
+ if (hasSymlinkAncestor(rel))
141
+ return;
142
+ const existing = virtualLstat(rel);
143
+ if (existing?.isDirectory() && !existing.isSymbolicLink() && virtualDirectoryIsEmpty(rel)) {
53
144
  actions.push({ file: rel, action: "remove-dir", reason: "empty directory" });
54
- if (!dryRun)
145
+ if (!dryRun && lstatSync(path, { throwIfNoEntry: false })?.isDirectory())
55
146
  rmdirSync(path);
147
+ markRemoved(rel);
56
148
  }
57
149
  },
58
- // Symlinks need lstat, not existsSync: existsSync FOLLOWS a symlink, so it
59
- // reports false for a dangling one -- exactly the state a link can be in
60
- // mid-uninstall, once its target is already gone.
61
- symlink(rel, target, reason) {
62
- const path = abs(repo, rel);
63
- const st = lstatSync(path, { throwIfNoEntry: false });
64
- if (st?.isSymbolicLink() && readlinkSync(path) === target)
65
- return false;
66
- actions.push({
67
- file: rel,
68
- action: st ? "update" : "create",
69
- reason: reason ?? (st ? "replacing stale entry with managed symlink" : "managed symlink"),
70
- });
71
- if (!dryRun) {
72
- // Whatever is there (a stale real directory from a pre-symlink install,
73
- // a wrong-target link, ...) sits inside a path this installer
74
- // exclusively generates -- safe to replace outright.
75
- if (st)
76
- rmSync(path, { recursive: true, force: true });
77
- mkdirSync(dirname(path), { recursive: true });
78
- symlinkSync(target, path);
79
- }
80
- return true;
81
- },
82
150
  removeSymlink(rel, reason) {
83
151
  const path = abs(repo, rel);
84
- if (!lstatSync(path, { throwIfNoEntry: false }))
152
+ if (hasSymlinkAncestor(rel))
153
+ return false;
154
+ const existing = virtualLstat(rel);
155
+ if (!existing?.isSymbolicLink())
85
156
  return false;
86
157
  actions.push({ file: rel, action: "remove", reason: reason ?? "managed symlink" });
87
158
  if (!dryRun)
88
- rmSync(path, { recursive: true, force: true });
159
+ unlinkSync(path);
160
+ markRemoved(rel);
89
161
  return true;
90
162
  },
91
163
  };
164
+ return ops;
92
165
  }
93
166
  //# sourceMappingURL=file-ops.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-ops.js","sourceRoot":"","sources":["../../src/internal/file-ops.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,MAAM,EACN,WAAW,EACX,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAuC1C,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,GAAW,EAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAEjF,MAAM,cAAc,GAAG,+BAA+B,CAAC;AAEvD,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAAe,EAAE,OAAqB;IAC9E,OAAO;QACL,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM;YACxB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACtE,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;YACjC,uEAAuE;YACvE,6DAA6D;YAC7D,IAAI,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC5D,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,IAAI,cAAc,EAAE,CAAC,CAAC;YACrG,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC9C,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC3B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,CAAC,GAAG,EAAE,MAAM;YAChB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,IAAI,cAAc,EAAE,CAAC,CAAC;YAChF,IAAI,CAAC,MAAM;gBAAE,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,0EAA0E;QAC1E,mEAAmE;QACnE,IAAI,CAAC,GAAG,EAAE,MAAM;YACd,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YACpD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,SAAS,CAAC,GAAG,EAAE,MAAM;YACnB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,IAAI,WAAW,EAAE,CAAC,CAAC;YACjF,wEAAwE;YACxE,yEAAyE;YACzE,sEAAsE;YACtE,WAAW;YACX,IAAI,CAAC,MAAM;gBAAE,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;YAC5F,OAAO,IAAI,CAAC;QACd,CAAC;QAED,YAAY,CAAC,GAAG;YACd,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5B,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;gBAC7E,IAAI,CAAC,MAAM;oBAAE,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAED,2EAA2E;QAC3E,yEAAyE;QACzE,kDAAkD;QAClD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM;YACzB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5B,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;YACtD,IAAI,EAAE,EAAE,cAAc,EAAE,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,MAAM;gBAAE,OAAO,KAAK,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,GAAG;gBACT,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;gBAChC,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,4CAA4C,CAAC,CAAC,CAAC,iBAAiB,CAAC;aAC1F,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,wEAAwE;gBACxE,8DAA8D;gBAC9D,qDAAqD;gBACrD,IAAI,EAAE;oBAAE,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvD,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC9C,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC5B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,aAAa,CAAC,GAAG,EAAE,MAAM;YACvB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC9D,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,IAAI,iBAAiB,EAAE,CAAC,CAAC;YACnF,IAAI,CAAC,MAAM;gBAAE,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"file-ops.js","sourceRoot":"","sources":["../../src/internal/file-ops.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/internal/platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/E,eAAO,MAAM,QAAQ,SAAS,CAAC;AAE/B,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,QAAQ,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CA0C9G,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAqH/D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAO3E,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cAAc,EAAmD,CAAC;AAEhG,eAAO,MAAM,0BAA0B,EAAE,kBAAkB,EAA0C,CAAC;AAEtG,eAAO,MAAM,aAAa;aACxB,MAAM,EAAE,WAAW;aACnB,MAAM,EAAE,WAAW;aACnB,QAAQ,EAAE,aAAa;aACvB,KAAK,EAAE,oBAAoB;aAC3B,UAAU,EAAE,aAAa;aACzB,IAAI,EAAE,aAAa;CACX,CAAC;AAqCX,0EAA0E;AAC1E,eAAO,MAAM,oBAAoB,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAGlE,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWrH;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAG1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,cAAc,CASvE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,kBAAkB,CAE/E"}
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/internal/platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/E,eAAO,MAAM,QAAQ,SAAS,CAAC;AAE/B,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,QAAQ,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CA0C9G,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAsH/D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAO3E,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cAAc,EAAmD,CAAC;AAEhG,eAAO,MAAM,0BAA0B,EAAE,kBAAkB,EAA0C,CAAC;AAEtG,eAAO,MAAM,aAAa;aACxB,MAAM,EAAE,WAAW;aACnB,MAAM,EAAE,WAAW;aACnB,QAAQ,EAAE,aAAa;aACvB,KAAK,EAAE,oBAAoB;aAC3B,UAAU,EAAE,aAAa;aACzB,IAAI,EAAE,aAAa;CACX,CAAC;AAqCX,0EAA0E;AAC1E,eAAO,MAAM,oBAAoB,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAGlE,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWrH;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAG1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,cAAc,CASvE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,kBAAkB,CAE/E"}
@@ -56,6 +56,7 @@ export const MANIFEST_FIELDS = {
56
56
  "targets",
57
57
  "skills",
58
58
  "agents",
59
+ "profileSources",
59
60
  "commands",
60
61
  "hooks",
61
62
  "mcpServers",
@@ -1 +1 @@
1
- {"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/internal/platform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/internal/platform.ts"],"names":[],"mappings":"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"}
@@ -4,20 +4,6 @@ import type { ProjectionPlatform } from "./internal/types.js";
4
4
  * every skill whose SKILL.md sets `disable-model-invocation: true`.
5
5
  */
6
6
  export declare function materializeCodexSkillMetadata(skillsSource: string, targetSkills: string): void;
7
- /**
8
- * Project the bundle into a self-contained Claude Code plugin root at
9
- * `targetRoot` (`.claude-plugin/plugin.json`, skills/, host-flagged
10
- * hooks/hooks.json, .mcp.json, README.md) WITHOUT registering any marketplace
11
- * or touching a Claude home. The derived manifest is computed in memory from
12
- * the canonical `.agents/plugin.json`; nothing is written back to the source.
13
- *
14
- * `options.symlinkSkills` (default false, preserving prior behavior for any
15
- * other caller): when true, the `skills` component is NOT copied into
16
- * `targetRoot` at all. This is for callers (the repo-local claude installer)
17
- * that place a relative symlink to a shared skills tree at that path
18
- * themselves — copying here would just be overwritten or leave stale
19
- * duplicate bytes behind.
20
- */
21
7
  /**
22
8
  * Project the bundle into a self-contained plugin root for `platform` at
23
9
  * `targetRoot` (manifest, skills/, hooks, mcp, README) WITHOUT registering any
@@ -31,16 +17,12 @@ export declare function materializeCodexSkillMetadata(skillsSource: string, targ
31
17
  * name safe. Hand-writing loose per-host files instead was what forced a flat,
32
18
  * un-namespaced shared skills pool in the first place.
33
19
  */
34
- export declare function projectPluginRoot(pluginRoot: string, targetRoot: string, platform: ProjectionPlatform, options?: {
35
- symlinkSkills?: boolean;
36
- }): {
20
+ export declare function projectPluginRoot(pluginRoot: string, targetRoot: string, platform: ProjectionPlatform): {
37
21
  name: string;
38
22
  version: string;
39
23
  };
40
24
  /** Claude-specific alias, kept because it names the common case at call sites. */
41
- export declare function projectClaudePluginRoot(pluginRoot: string, targetRoot: string, options?: {
42
- symlinkSkills?: boolean;
43
- }): {
25
+ export declare function projectClaudePluginRoot(pluginRoot: string, targetRoot: string): {
44
26
  name: string;
45
27
  version: string;
46
28
  };
@@ -1 +1 @@
1
- {"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../src/projection.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAkB,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAqE9E;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAY9F;AAOD;;;;;;;;;;;;;GAaG;AACH;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAiDnC;AAED,kFAAkF;AAClF,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAEnC"}
1
+ {"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../src/projection.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAkB,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAqE9E;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAY9F;AAOD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,kBAAkB,GAC3B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA+CnC;AAED,kFAAkF;AAClF,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAEjH"}
@@ -97,20 +97,6 @@ function stringField(manifest, key) {
97
97
  const value = manifest[key];
98
98
  return typeof value === "string" && value.trim() ? value : undefined;
99
99
  }
100
- /**
101
- * Project the bundle into a self-contained Claude Code plugin root at
102
- * `targetRoot` (`.claude-plugin/plugin.json`, skills/, host-flagged
103
- * hooks/hooks.json, .mcp.json, README.md) WITHOUT registering any marketplace
104
- * or touching a Claude home. The derived manifest is computed in memory from
105
- * the canonical `.agents/plugin.json`; nothing is written back to the source.
106
- *
107
- * `options.symlinkSkills` (default false, preserving prior behavior for any
108
- * other caller): when true, the `skills` component is NOT copied into
109
- * `targetRoot` at all. This is for callers (the repo-local claude installer)
110
- * that place a relative symlink to a shared skills tree at that path
111
- * themselves — copying here would just be overwritten or leave stale
112
- * duplicate bytes behind.
113
- */
114
100
  /**
115
101
  * Project the bundle into a self-contained plugin root for `platform` at
116
102
  * `targetRoot` (manifest, skills/, hooks, mcp, README) WITHOUT registering any
@@ -124,7 +110,7 @@ function stringField(manifest, key) {
124
110
  * name safe. Hand-writing loose per-host files instead was what forced a flat,
125
111
  * un-namespaced shared skills pool in the first place.
126
112
  */
127
- export function projectPluginRoot(pluginRoot, targetRoot, platform, options = {}) {
113
+ export function projectPluginRoot(pluginRoot, targetRoot, platform) {
128
114
  const enact = readManifestFile(pluginRoot, "enact");
129
115
  const manifest = manifestForPlatform(platform, enact);
130
116
  const validation = validateManifest(platform, manifest);
@@ -138,7 +124,6 @@ export function projectPluginRoot(pluginRoot, targetRoot, platform, options = {}
138
124
  rmSync(targetRoot, { recursive: true, force: true });
139
125
  mkdirSync(targetRoot, { recursive: true });
140
126
  const agentsEntry = cleanRel(manifest.agents) ?? cleanRel(DEFAULT_PATHS.agents);
141
- const skillsEntry = cleanRel(manifest.skills) ?? cleanRel(DEFAULT_PATHS.skills);
142
127
  const hooksFileRel = cleanRel(manifest.hooks) ?? cleanRel(DEFAULT_PATHS.hooks) ?? "hooks/hooks.json";
143
128
  // Hosts disagree on the MCP config filename: Cursor reads `mcp.json`, the
144
129
  // rest read `.mcp.json`. Copying the canonical name verbatim left Cursor
@@ -147,8 +132,6 @@ export function projectPluginRoot(pluginRoot, targetRoot, platform, options = {}
147
132
  const mcpEntry = cleanRel(manifest.mcpServers) ?? cleanRel(DEFAULT_PATHS.mcpServers);
148
133
  const mcpTargetName = DEFAULT_MCP_FILENAME[platform];
149
134
  for (const entry of projectionEntries(manifest, platform)) {
150
- if (options.symlinkSkills && entry === skillsEntry)
151
- continue;
152
135
  const sourcePath = resolve(pluginRoot, entry);
153
136
  if (!existsSync(sourcePath))
154
137
  continue;
@@ -174,7 +157,7 @@ export function projectPluginRoot(pluginRoot, targetRoot, platform, options = {}
174
157
  return { name, version: stringField(manifest, "version") ?? "0.0.0" };
175
158
  }
176
159
  /** Claude-specific alias, kept because it names the common case at call sites. */
177
- export function projectClaudePluginRoot(pluginRoot, targetRoot, options = {}) {
178
- return projectPluginRoot(pluginRoot, targetRoot, "claude", options);
160
+ export function projectClaudePluginRoot(pluginRoot, targetRoot) {
161
+ return projectPluginRoot(pluginRoot, targetRoot, "claude");
179
162
  }
180
163
  //# sourceMappingURL=projection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"projection.js","sourceRoot":"","sources":["../src/projection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"projection.js","sourceRoot":"","sources":["../src/projection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "enact-factory",
3
+ "version": "0.8.1",
4
+ "description": "Enact Factory governance plugin for Goal and Stage workflows, external judgment contracts, and MCP registration.",
5
+ "author": {
6
+ "name": "amsterdamdatalabs"
7
+ },
8
+ "homepage": "https://amsterdamdatalabs.com",
9
+ "repository": "https://dev.azure.com/amsterdamdatalabs/enact/_git/enact-os",
10
+ "license": "UNLICENSED",
11
+ "keywords": [
12
+ "enact-factory",
13
+ "governance",
14
+ "workitem",
15
+ "goal",
16
+ "stage",
17
+ "stage-verifier",
18
+ "loop-grader",
19
+ "pipeline",
20
+ "mcp"
21
+ ],
22
+ "targets": [
23
+ "claude",
24
+ "codex",
25
+ "cursor",
26
+ "enact",
27
+ "kimi"
28
+ ],
29
+ "skills": "./skills/",
30
+ "agents": "./agents/",
31
+ "references": "./references/",
32
+ "hooks": "./hooks/hooks.json",
33
+ "mcpServers": "./.mcp.json",
34
+ "validate": "node scripts/validate.mjs",
35
+ "interface": {
36
+ "displayName": "Enact Factory",
37
+ "shortDescription": "Factory MCP server and Goal/Stage governance skills for WorkItem and Azure DevOps delivery.",
38
+ "longDescription": "Orchestrator plugin. Owns non-binding local agents (architect, code-reviewer, critic, executor, explore, planner), Goal and Stage workflow skills, and distinct external judgment contracts: stage-verify for StageVerifier and loop-grade for LoopGrader. No bundled Codex agent is an independent judgment seat.",
39
+ "developerName": "amsterdamdatalabs",
40
+ "category": "Developer Tools",
41
+ "composerIcon": "./assets/icon.png",
42
+ "logo": "./assets/logo.png",
43
+ "capabilities": [
44
+ "model-agnostic agents",
45
+ "goal and stage workflow skills",
46
+ "external StageVerifier contract",
47
+ "external LoopGrader contract",
48
+ "mcp tools",
49
+ "workitem management",
50
+ "pipeline governance",
51
+ "azure devops ci/cd strategy"
52
+ ]
53
+ },
54
+ "factory": {
55
+ "firstParty": true,
56
+ "operatorScope": "global"
57
+ }
58
+ }
@@ -0,0 +1,30 @@
1
+ name = "architect"
2
+ description = "Non-binding architectural review with evidence pointers for planning and external judgment briefings"
3
+ model = "gpt-5.6-sol"
4
+ claude_model = "opus"
5
+ cursor_model = "default"
6
+ model_reasoning_effort = "xhigh"
7
+ sandbox_mode = "danger-full-access"
8
+ tools = "Read, Grep, Glob, Bash"
9
+ developer_instructions = """
10
+ Agent definition: non-binding read-only architectural reviewer with evidence pointers.
11
+
12
+ Role:
13
+ - Read-only architectural reviewer.
14
+ - Diagnose root causes from code and docs already on disk.
15
+ - Produce architectural findings and a recommendation with concrete evidence pointers.
16
+
17
+ Rules:
18
+ - Never edit files.
19
+ - Never speculate when you can read the source.
20
+ - Cite exact file paths and line references for material claims.
21
+ - Call out tradeoffs, not just the favored direction.
22
+ - Never act as StageVerifier or LoopGrader, claim external independence, or call loop judgment and closure tools.
23
+
24
+ Output contract:
25
+ - status: ADVISORY
26
+ - recommendation: PROCEED, REVISE, or ESCALATE
27
+ - reasons: concise bullet list
28
+ - evidencePointers: file references
29
+ - tradeoffs: short list
30
+ """
@@ -0,0 +1,27 @@
1
+ name = "code-reviewer"
2
+ description = "Non-binding local diff review that prepares findings for an external StageVerifier"
3
+ model = "gpt-5.6-sol"
4
+ claude_model = "opus"
5
+ cursor_model = "default"
6
+ model_reasoning_effort = "xhigh"
7
+ sandbox_mode = "danger-full-access"
8
+ tools = "Read, Grep, Glob, Bash"
9
+ developer_instructions = """
10
+ Agent definition: non-binding local diff reviewer that prepares findings for external judgment.
11
+
12
+ Role:
13
+ - Review an implementation batch before external StageVerifier dispatch.
14
+ - Prioritize correctness, regressions, and missing verification over style.
15
+
16
+ Rules:
17
+ - Never edit files.
18
+ - Review only from the actual diff and surrounding code.
19
+ - Every finding must cite a file reference and explain impact.
20
+ - If no actionable issues remain, report that no local findings were found; do not emit a binding approval token.
21
+ - Never act as StageVerifier or LoopGrader, claim external independence, or call loop judgment and closure tools.
22
+
23
+ Output contract:
24
+ - status: ADVISORY
25
+ - findings: severity-ordered list with evidence
26
+ - residual_risks: optional short list
27
+ """
@@ -0,0 +1,35 @@
1
+ name = "critic"
2
+ description = "Non-binding adversarial debate participant for high-risk planning decisions"
3
+ model = "gpt-5.6-sol"
4
+ claude_model = "opus"
5
+ cursor_model = "default"
6
+ model_reasoning_effort = "xhigh"
7
+ sandbox_mode = "danger-full-access"
8
+ tools = "Read, Grep, Glob, Bash"
9
+ developer_instructions = """
10
+ Agent definition: non-binding adversarial debate participant for high-risk planning decisions.
11
+
12
+ Role:
13
+ - Attack weak assumptions in plans, proposals, and risky implementation choices.
14
+ - Operate as an adversarial reviewer, not a collaborator trying to be agreeable.
15
+
16
+ Rules:
17
+ - Never edit files.
18
+ - Surface the strongest counterargument first.
19
+ - Prefer concrete failure modes over vague concern language.
20
+ - When a decision looks sound, say that plainly instead of inventing objections.
21
+ - Never act as StageVerifier or LoopGrader, claim external independence, or call loop judgment and closure tools.
22
+
23
+ Round protocol:
24
+ 1. Independent critique.
25
+ 2. Cross-attack on the competing argument.
26
+ 3. Defend, refine, or concede.
27
+
28
+ Output contract:
29
+ - position
30
+ - strongest_objections
31
+ - failure_modes
32
+ - concessions
33
+ - final_recommendation
34
+ - status: ADVISORY
35
+ """
@@ -0,0 +1,28 @@
1
+ name = "executor"
2
+ description = "Focused implementation worker for small, reviewable diffs with verification"
3
+ model = "gpt-5.6-luna"
4
+ claude_model = "sonnet"
5
+ cursor_model = "composer-2.5"
6
+ model_reasoning_effort = "high"
7
+ sandbox_mode = "danger-full-access"
8
+ developer_instructions = """
9
+ Agent definition: focused implementation worker for small, reviewable diffs with verification.
10
+
11
+ Role:
12
+ - Implement the requested change with the smallest viable diff.
13
+ - Run focused verification before claiming completion.
14
+
15
+ Rules:
16
+ - Stay inside the stated scope.
17
+ - Match existing code patterns.
18
+ - Do not add abstractions unless the code clearly needs them.
19
+ - Do not stop at code changes; include the verification result.
20
+ - Before dispatching or relaying work, require Factory's exact { planPath, sha256, approvedBy, approvedAt } approval record and rehash planPath; missing approval or byte drift is blocking.
21
+ - Preserve remote System.State verbatim with separate execution, review, and PR axes; unknown remote state blocks rather than mapping to a local status.
22
+ - If blocked after repeated failed attempts, report the blocker clearly.
23
+
24
+ Output contract:
25
+ - changes_made
26
+ - verification
27
+ - blockers_or_followups
28
+ """
@@ -0,0 +1,25 @@
1
+ name = "explore"
2
+ description = "Codebase sweep agent for absolute-path findings and quote-friendly evidence"
3
+ model = "gpt-5.6-luna"
4
+ claude_model = "haiku"
5
+ cursor_model = "default"
6
+ model_reasoning_effort = "high"
7
+ sandbox_mode = "danger-full-access"
8
+ developer_instructions = """
9
+ Agent definition: codebase sweep agent for absolute-path findings and quote-friendly evidence.
10
+
11
+ Role:
12
+ - Find relevant files, symbols, and relationships quickly.
13
+ - Return enough context for another agent to act without repeating the search.
14
+
15
+ Rules:
16
+ - Never edit files.
17
+ - Use absolute paths in results.
18
+ - Prefer breadth first: search multiple relevant areas before narrowing.
19
+ - Explain how the files connect instead of returning a raw list.
20
+
21
+ Output contract:
22
+ - findings
23
+ - relationships
24
+ - recommended_next_step
25
+ """
@@ -0,0 +1,29 @@
1
+ name = "planner"
2
+ description = "Structured implementation planner that never writes production code"
3
+ model = "gpt-5.6-terra"
4
+ claude_model = "opus"
5
+ cursor_model = "default"
6
+ model_reasoning_effort = "xhigh"
7
+ sandbox_mode = "danger-full-access"
8
+ developer_instructions = """
9
+ Agent definition: structured implementation planner that never writes production code.
10
+
11
+ Role:
12
+ - Turn a goal into a small, reviewable execution plan with clear acceptance criteria.
13
+ - You do not implement code.
14
+
15
+ Rules:
16
+ - Never write production code.
17
+ - Prefer 3 to 6 concrete steps.
18
+ - Include dependencies, risks, and verification expectations.
19
+ - After authorized review, emit the Factory-owned approval record exactly as { planPath, sha256, approvedBy, approvedAt }; sha256 is the exact plan-byte digest and changes invalidate approval.
20
+ - For board effects, preserve remote System.State verbatim, model execution, review, and PR as separate axes, and mark unknown remote states blocking.
21
+ - Escalate unresolved product-direction choices instead of guessing.
22
+
23
+ Output contract:
24
+ - plan_summary
25
+ - steps
26
+ - acceptance_criteria
27
+ - risks_and_open_questions
28
+ - plan_approval_record
29
+ """
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "enact-repo",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Baseline agent setup for any repository: the full Enact skill catalog plus guard, briefing, and code-review-graph hooks and MCP tooling, installed at repo scope.",
5
5
  "author": {
6
6
  "name": "amsterdamdatalabs"
@@ -25,6 +25,9 @@
25
25
  "opencode"
26
26
  ],
27
27
  "skills": "./skills/",
28
+ "profileSources": [
29
+ "enact-factory"
30
+ ],
28
31
  "hooks": "./hooks/hooks.json",
29
32
  "mcpServers": "./.mcp.json",
30
33
  "assets": [
@@ -14,6 +14,10 @@ not global/user install — see `factory.operatorScope: "project"` in
14
14
  - `skills/` — the full first-party Enact skill catalog (38 skills, copied verbatim from
15
15
  `enact-m5`'s `.agents/skill-catalog/`), covering debugging, refactors, TDD, code review,
16
16
  research, orchestration, and more.
17
+ - `profileSources` — the six canonical profiles declared by sibling `enact-factory`:
18
+ `architect`, `code-reviewer`, `critic`, `executor`, `explore`, and `planner`. Their TOML
19
+ sources remain in `extensions/enact-factory/agents/`; `enact-repo` projects them into each
20
+ host's documented native project directory rather than carrying copied profile bodies.
17
21
  - `.mcp.json` — `code-review-graph` (`crg serve`), `lean-ctx` (stdio passthrough to
18
22
  `lean-ctx mcp`, run via `enact-hook lean-ctx mcp` so repo-local `LEAN_CTX_*` dirs are
19
23
  resolved at runtime from `cwd`), and `azure-devops` (`azure-devops-mcp`) MCP servers.
@@ -77,6 +81,10 @@ install is reconciliation, not enrollment. The command writes direct native proj
77
81
  `.opencode/agents` and `.opencode/skills`. It also writes each host's
78
82
  native MCP and hook configuration where supported. It never writes a plugin root, marketplace,
79
83
  or plugin registration.
84
+ For every selected host it also projects the declared Factory profiles: Claude, Cursor, Kimi,
85
+ and OpenCode receive Markdown under their native `agents/` directory; Codex receives canonical
86
+ TOML under `.codex/agents/`. The source declaration is validated at install time and an invalid,
87
+ missing, symlinked, or colliding profile source stops reconciliation before owned roots change.
80
88
  Kimi hooks are global-only and are installed by `enact-vps`, not by this bundle. OpenCode's
81
89
  process-level hook carrier is separate from this repo-local installer; OpenCode bundles always
82
90
  install their native local files and remove legacy plugin roots. The installer rebuilds the owned
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amsterdamdatalabs/enact-extensions",
3
- "version": "0.1.58",
3
+ "version": "0.1.62",
4
4
  "description": "Create and validate Enact multi-platform plugin manifests",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -19,6 +19,8 @@
19
19
  "scripts/enact-extensions.mjs",
20
20
  "scripts/lib",
21
21
  "extensions/enact-repo",
22
+ "extensions/enact-factory/.agents/plugin.json",
23
+ "extensions/enact-factory/agents",
22
24
  "extensions/enact-loop"
23
25
  ],
24
26
  "publishConfig": {
@@ -232,8 +232,9 @@ try {
232
232
  if (!report.lock.valid) {
233
233
  if (report.lock.missingFiles.length) console.log(` missing: ${report.lock.missingFiles.join(", ")}`);
234
234
  if (report.lock.driftedFiles.length) console.log(` drifted: ${report.lock.driftedFiles.join(", ")}`);
235
- if (report.lock.jsonIssues.length) console.log(` json: ${report.lock.jsonIssues.join(", ")}`);
236
235
  if (report.lock.tomlIssues.length) console.log(` toml: ${report.lock.tomlIssues.join(", ")}`);
236
+ if (report.lock.symlinkIssues.length) console.log(` symlink: ${report.lock.symlinkIssues.join(", ")}`);
237
+ if (report.lock.rootIssues.length) console.log(` owned root: ${report.lock.rootIssues.join(", ")}`);
237
238
  }
238
239
 
239
240
  for (const [host, info] of Object.entries(report.hosts)) {
@@ -47,7 +47,7 @@
47
47
 
48
48
  import { spawnSync } from "node:child_process";
49
49
  import { createHash } from "node:crypto";
50
- import { existsSync, lstatSync, readdirSync, readFileSync, readlinkSync } from "node:fs";
50
+ import { existsSync, lstatSync, readdirSync, readFileSync } from "node:fs";
51
51
  import { homedir } from "node:os";
52
52
  import { basename, join } from "node:path";
53
53
  import * as TOML from "@iarna/toml";
@@ -301,43 +301,57 @@ function runHookDoctor(repo, enactHook) {
301
301
  // lock integrity — every canonical managed file present + hash match, plus
302
302
  // no foreign content inside an owned root.
303
303
  // ---------------------------------------------------------------------------
304
+ function firstSymlinkComponent(repo, rel) {
305
+ const parts = rel.split("/");
306
+ for (let i = 1; i <= parts.length; i++) {
307
+ const component = parts.slice(0, i).join("/");
308
+ const st = lstatSync(abs(repo, component), { throwIfNoEntry: false });
309
+ if (!st) return null;
310
+ if (st.isSymbolicLink()) return component;
311
+ }
312
+ return null;
313
+ }
314
+
315
+ function managedSymlinkIssue(repo, rel) {
316
+ const component = firstSymlinkComponent(repo, rel);
317
+ if (!component) return null;
318
+ return component === rel
319
+ ? `${rel} (managed path is a symlink)`
320
+ : `${rel} (managed path traverses symlink ${component})`;
321
+ }
322
+
304
323
  function checkLockIntegrity(repo, name, lock) {
305
324
  const missingFiles = [];
306
325
  const driftedFiles = [];
326
+ const symlinkIssues = [];
327
+ const recordSymlinkIssue = (rel) => {
328
+ const issue = managedSymlinkIssue(repo, rel);
329
+ if (issue) symlinkIssues.push(issue);
330
+ return issue !== null;
331
+ };
332
+ recordSymlinkIssue(lockRel(name));
307
333
  for (const [rel, { sha256: want }] of Object.entries(lock.files)) {
334
+ if (recordSymlinkIssue(rel)) continue;
308
335
  if (!existsSync(abs(repo, rel))) missingFiles.push(rel);
309
336
  else if (fileSha(repo, rel) !== want) driftedFiles.push(rel);
310
337
  }
311
338
  const tomlIssues = [];
312
339
  for (const [rel, record] of Object.entries(lock.toml)) {
340
+ if (recordSymlinkIssue(rel)) continue;
313
341
  const path = abs(repo, rel);
314
342
  const found = existsSync(path) ? findBlock(readFileSync(path, "utf8"), name) : null;
315
343
  if (!found || sha256(found.block) !== record.sha256) tomlIssues.push(rel);
316
344
  }
317
- // Managed symlinks carry no content hash, so `lock.files`-style verification
318
- // does not reach them. Verify by the link's own mechanism: it must BE a
319
- // symlink, point where the lock says, and actually resolve.
320
- //
321
- // lstatSync, never existsSync: existsSync follows the link and returns false
322
- // for a dangling one, so it cannot tell "absent" from "present but broken".
323
- const symlinkIssues = [];
324
- for (const [rel, record] of Object.entries(lock.symlinks ?? {})) {
325
- const path = abs(repo, rel);
326
- const st = lstatSync(path, { throwIfNoEntry: false });
327
- if (!st) {
328
- symlinkIssues.push(`${rel} (missing)`);
329
- continue;
330
- }
331
- if (!st.isSymbolicLink()) {
332
- symlinkIssues.push(`${rel} (not a symlink)`);
333
- continue;
334
- }
335
- const target = readlinkSync(path);
336
- if (target !== record.target) {
337
- symlinkIssues.push(`${rel} (target is ${target}, expected ${record.target})`);
338
- continue;
339
- }
340
- if (!existsSync(path)) symlinkIssues.push(`${rel} (dangling -> ${target})`);
345
+ for (const rel of Object.keys(lock.gitignore ?? {})) recordSymlinkIssue(rel);
346
+ if (lock.config) recordSymlinkIssue(CONFIG_PATH);
347
+ for (const record of Object.values(lock.displaced?.files ?? {})) {
348
+ if (typeof record?.storedAt === "string") recordSymlinkIssue(record.storedAt);
349
+ }
350
+ const legacySymlinks = Object.keys(lock.symlinks ?? {}).sort();
351
+ if (legacySymlinks.length > 0) {
352
+ symlinkIssues.push(
353
+ `legacy lock records managed symlinks; re-run install to replace them with real files: ${legacySymlinks.join(", ")}`,
354
+ );
341
355
  }
342
356
  const rootIssues = [];
343
357
  for (const root of lock.ownedRoots ?? []) {
@@ -363,7 +377,13 @@ function checkLockIntegrity(repo, name, lock) {
363
377
  rootIssues.push(`${rel} (foreign directory)`);
364
378
  return;
365
379
  }
366
- for (const entry of readdirSync(path, { withFileTypes: true })) visit(`${rel}/${entry.name}`);
380
+ for (const entry of readdirSync(path, { withFileTypes: true })) {
381
+ // Finder can recreate this metadata immediately after an authoritative
382
+ // install removes it. It is never installer-owned output, so doctor
383
+ // must not report an OS-generated entry as a managed-root violation.
384
+ if (entry.name === ".DS_Store") continue;
385
+ visit(`${rel}/${entry.name}`);
386
+ }
367
387
  };
368
388
  if (existsSync(abs(repo, root))) visit(root);
369
389
  }
@@ -401,7 +421,6 @@ function checkNativeHostPresence(repo, lock, host) {
401
421
  ...Object.keys(lock.files ?? {}),
402
422
  ...Object.keys(lock.merged ?? {}),
403
423
  ...Object.keys(lock.toml ?? {}),
404
- ...Object.keys(lock.symlinks ?? {}),
405
424
  ].filter((rel) => isNativeHostPath(host, rel));
406
425
  const nativePaths = [...new Set(rels)].sort();
407
426
  return {
@@ -297,6 +297,76 @@ export function parseRepoHosts(host, manifest) {
297
297
  return REPO_HOSTS.filter((h) => parts.includes(h));
298
298
  }
299
299
 
300
+ function safeDeclaredProfileSource(name, manifestPath) {
301
+ if (typeof name !== "string" || !/^[a-z][a-z0-9-]*$/.test(name)) {
302
+ throw new Error(`${manifestPath} profileSources entries must be plugin names`);
303
+ }
304
+ return name;
305
+ }
306
+
307
+ function assertRegularProfileSourceDirectory(path, label) {
308
+ const state = lstatSync(path, { throwIfNoEntry: false });
309
+ if (!state?.isDirectory() || state.isSymbolicLink()) {
310
+ throw new Error(`${label} must be a regular, non-symlink directory: ${path}`);
311
+ }
312
+ }
313
+
314
+ function assertRegularProfileSourceFile(path, label) {
315
+ const state = lstatSync(path, { throwIfNoEntry: false });
316
+ if (!state?.isFile() || state.isSymbolicLink()) {
317
+ throw new Error(`${label} must be a regular, non-symlink file: ${path}`);
318
+ }
319
+ }
320
+
321
+ function assertRegularProfileSourceTree(path) {
322
+ assertRegularProfileSourceDirectory(path, "profile source agents directory");
323
+ for (const entry of readdirSync(path, { withFileTypes: true })) {
324
+ const child = join(path, entry.name);
325
+ const state = lstatSync(child, { throwIfNoEntry: false });
326
+ if (state?.isSymbolicLink()) {
327
+ throw new Error(`profile source agent entry must not be a symlink: ${child}`);
328
+ }
329
+ if (state?.isDirectory()) {
330
+ assertRegularProfileSourceTree(child);
331
+ } else if (!state?.isFile()) {
332
+ throw new Error(`profile source agent entry must be a regular file: ${child}`);
333
+ }
334
+ }
335
+ }
336
+
337
+ function declaredProfileAgentDirs(pluginRoot, manifest, manifestPath) {
338
+ if (manifest.profileSources === undefined) return [];
339
+ if (!Array.isArray(manifest.profileSources) || manifest.profileSources.length === 0) {
340
+ throw new Error(`${manifestPath} profileSources must be a non-empty array of plugin names`);
341
+ }
342
+ const names = manifest.profileSources.map((name) => safeDeclaredProfileSource(name, manifestPath));
343
+ if (new Set(names).size !== names.length) throw new Error(`${manifestPath} profileSources must not repeat a plugin`);
344
+
345
+ return names.map((name) => {
346
+ const sourceRoot = resolve(pluginRoot, "..", name);
347
+ assertRegularProfileSourceDirectory(sourceRoot, "profile source root");
348
+ const sourceAgentsMetaDir = join(sourceRoot, ".agents");
349
+ assertRegularProfileSourceDirectory(sourceAgentsMetaDir, "profile source manifest directory");
350
+ const sourceManifestPath = join(sourceRoot, ".agents", "plugin.json");
351
+ assertRegularProfileSourceFile(sourceManifestPath, "profile source manifest");
352
+ const sourceManifest = readJsonStrict(sourceManifestPath, sourceManifestPath);
353
+ if (sourceManifest.name !== name) {
354
+ throw new Error(`${sourceManifestPath} must declare name ${JSON.stringify(name)}`);
355
+ }
356
+ const rawAgents = sourceManifest.agents;
357
+ if (typeof rawAgents !== "string" || !rawAgents.trim()) {
358
+ throw new Error(`${sourceManifestPath} must declare agents for profile source ${name}`);
359
+ }
360
+ const agentsRel = rawAgents.trim().replace(/^\.\//, "").replace(/\/+$/, "");
361
+ if (isAbsolute(agentsRel) || agentsRel.split("/").includes("..")) {
362
+ throw new Error(`${sourceManifestPath} agents must be a safe plugin-relative path`);
363
+ }
364
+ const agentsDir = resolve(sourceRoot, agentsRel);
365
+ assertRegularProfileSourceTree(agentsDir);
366
+ return { name, agentsDir };
367
+ });
368
+ }
369
+
300
370
  export function readBundle(pluginRoot) {
301
371
  const manifestPath = join(pluginRoot, ".agents", "plugin.json");
302
372
  if (!existsSync(manifestPath)) {
@@ -322,6 +392,7 @@ export function readBundle(pluginRoot) {
322
392
  name: manifest.name,
323
393
  version: typeof manifest.version === "string" ? manifest.version : "0.0.0",
324
394
  skillsDir: component("skills"),
395
+ profileAgentDirs: declaredProfileAgentDirs(pluginRoot, manifest, manifestPath),
325
396
  hooks: hooksPath ? readJsonStrict(hooksPath, hooksPath) : null,
326
397
  mcpServers,
327
398
  };
@@ -395,23 +466,30 @@ function addNativeSkills(plan, bundle, host) {
395
466
  });
396
467
  }
397
468
 
398
- function addNativeAgents(plan, pluginRoot, host) {
399
- const source = join(pluginRoot, "agents");
400
- if (!existsSync(source)) return;
469
+ function addNativeAgents(plan, bundle, pluginRoot, host) {
470
+ const sources = [join(pluginRoot, "agents"), ...bundle.profileAgentDirs.map(({ agentsDir }) => agentsDir)].filter(
471
+ (source) => existsSync(source),
472
+ );
401
473
  const targetRel = HOST_AGENTS_DIR[host];
402
- stageDir(`enact-repo-${host}-agents-`, (staging) => {
403
- const target = join(staging, "agents");
404
- projectNativeAgentsDir(source, target, host);
405
- for (const rel of listFilesRecursive(target)) {
406
- plan.files.set(`${targetRel}/${rel}`, readFileSync(join(target, rel)));
407
- }
408
- });
474
+ for (const source of sources) {
475
+ stageDir(`enact-repo-${host}-agents-`, (staging) => {
476
+ const target = join(staging, "agents");
477
+ projectNativeAgentsDir(source, target, host);
478
+ for (const rel of listFilesRecursive(target)) {
479
+ const targetPath = `${targetRel}/${rel}`;
480
+ if (plan.files.has(targetPath)) {
481
+ throw new Error(`Native ${host} agent collision at ${targetPath}; profile sources must have distinct names`);
482
+ }
483
+ plan.files.set(targetPath, readFileSync(join(target, rel)));
484
+ }
485
+ });
486
+ }
409
487
  }
410
488
 
411
489
  // Host adapters write only documented native project files.
412
490
  const HOST_ADAPTERS = {
413
491
  claude(plan, bundle, pluginRoot) {
414
- addNativeAgents(plan, pluginRoot, "claude");
492
+ addNativeAgents(plan, bundle, pluginRoot, "claude");
415
493
  addNativeSkills(plan, bundle, "claude");
416
494
  const mcp = jsonMerge(plan, ".mcp.json");
417
495
  for (const [name, def] of Object.entries(bundle.mcpServers))
@@ -425,7 +503,7 @@ const HOST_ADAPTERS = {
425
503
  },
426
504
 
427
505
  codex(plan, bundle, pluginRoot) {
428
- addNativeAgents(plan, pluginRoot, "codex");
506
+ addNativeAgents(plan, bundle, pluginRoot, "codex");
429
507
  addNativeSkills(plan, bundle, "codex");
430
508
  if (Object.keys(bundle.mcpServers).length > 0) plan.toml.set(".codex/config.toml", { tables: bundle.mcpServers });
431
509
  if (bundle.hooks) {
@@ -444,7 +522,7 @@ const HOST_ADAPTERS = {
444
522
  },
445
523
 
446
524
  cursor(plan, bundle, pluginRoot) {
447
- addNativeAgents(plan, pluginRoot, "cursor");
525
+ addNativeAgents(plan, bundle, pluginRoot, "cursor");
448
526
  addNativeSkills(plan, bundle, "cursor");
449
527
  if (bundle.hooks) {
450
528
  const dropped = unmappedCursorHookEvents(bundle.hooks);
@@ -470,7 +548,7 @@ const HOST_ADAPTERS = {
470
548
  },
471
549
 
472
550
  kimi(plan, bundle, pluginRoot) {
473
- addNativeAgents(plan, pluginRoot, "kimi");
551
+ addNativeAgents(plan, bundle, pluginRoot, "kimi");
474
552
  addNativeSkills(plan, bundle, "kimi");
475
553
  const mcp = jsonMerge(plan, ".kimi-code/mcp.json");
476
554
  for (const [name, def] of Object.entries(bundle.mcpServers)) {
@@ -479,7 +557,7 @@ const HOST_ADAPTERS = {
479
557
  },
480
558
 
481
559
  opencode(plan, bundle, pluginRoot) {
482
- addNativeAgents(plan, pluginRoot, "opencode");
560
+ addNativeAgents(plan, bundle, pluginRoot, "opencode");
483
561
  addNativeSkills(plan, bundle, "opencode");
484
562
  const mcp = jsonMerge(plan, "opencode.json");
485
563
  for (const [name, def] of Object.entries(deriveOpenCodeMcp({ mcpServers: bundle.mcpServers }).mcp)) {
@@ -507,7 +585,6 @@ export function buildPlan(pluginRoot, bundle, hosts, repo) {
507
585
  json: new Map(),
508
586
  toml: new Map(),
509
587
  gitignore: new Map(),
510
- symlinks: new Map(),
511
588
  skills: new Set(),
512
589
  };
513
590
  plan.gitignore.set(GITIGNORE_PATH, GITIGNORE_LINES);
@@ -545,6 +622,37 @@ function assignJsonPath(doc, path, value) {
545
622
  at[path.at(-1)] = jsonValue(value);
546
623
  }
547
624
 
625
+ function renderRootJson(value, indent = 0, prefixWidth = 0) {
626
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
627
+ if (Array.isArray(value)) {
628
+ if (value.length === 0) return "[]";
629
+ const compact = `[${value.map((entry) => JSON.stringify(entry)).join(", ")}]`;
630
+ if (value.every((entry) => entry === null || typeof entry !== "object") && prefixWidth + compact.length <= 120) {
631
+ return compact;
632
+ }
633
+ const padding = " ".repeat(indent);
634
+ const childPadding = " ".repeat(indent + 2);
635
+ return `[\n${value
636
+ .map((entry, index) => {
637
+ const suffix = index === value.length - 1 ? "" : ",";
638
+ return `${childPadding}${renderRootJson(entry, indent + 2)}${suffix}`;
639
+ })
640
+ .join("\n")}\n${padding}]`;
641
+ }
642
+
643
+ const entries = Object.entries(value);
644
+ if (entries.length === 0) return "{}";
645
+ const padding = " ".repeat(indent);
646
+ const childPadding = " ".repeat(indent + 2);
647
+ return `{\n${entries
648
+ .map(([key, entry], index) => {
649
+ const prefix = `${childPadding}${JSON.stringify(key)}: `;
650
+ const suffix = index === entries.length - 1 ? "" : ",";
651
+ return `${prefix}${renderRootJson(entry, indent + 2, prefix.length)}${suffix}`;
652
+ })
653
+ .join("\n")}\n${padding}}`;
654
+ }
655
+
548
656
  /** Build the exact native files from the bundle, without reading a repo file. */
549
657
  function materializeAuthoritativeFiles(plan, bundle) {
550
658
  const files = new Map(plan.files);
@@ -562,7 +670,9 @@ function materializeAuthoritativeFiles(plan, bundle) {
562
670
  if (!Array.isArray(at[key])) at[key] = [];
563
671
  at[key].push(jsonValue(entry.value));
564
672
  }
565
- files.set(rel, Buffer.from(`${JSON.stringify(doc, null, 2)}\n`));
673
+ const rendered =
674
+ rel === ".mcp.json" || rel === "opencode.json" ? renderRootJson(doc) : JSON.stringify(doc, null, 2);
675
+ files.set(rel, Buffer.from(`${rendered}\n`));
566
676
  }
567
677
  for (const [rel, toml] of plan.toml) files.set(rel, Buffer.from(renderTomlBlock(bundle.name, toml.tables)));
568
678
  for (const [rel, lines] of plan.gitignore) files.set(rel, Buffer.from(`${lines.join("\n")}\n`));
@@ -581,7 +691,7 @@ function isBoundaryOrAncestor(rel, boundaries) {
581
691
 
582
692
  function clearOwnedRoot(repo, root, boundaries, ops) {
583
693
  const rootPath = abs(repo, root);
584
- const rootState = lstatSync(rootPath, { throwIfNoEntry: false });
694
+ const rootState = ops.lstat(root);
585
695
  if (!rootState) return;
586
696
  if (!rootState.isDirectory() || rootState.isSymbolicLink()) {
587
697
  ops.removeSymlink(root, "replacing non-directory owned root");
@@ -593,7 +703,7 @@ function clearOwnedRoot(repo, root, boundaries, ops) {
593
703
  }
594
704
  const visit = (rel) => {
595
705
  const path = abs(repo, rel);
596
- const state = lstatSync(path, { throwIfNoEntry: false });
706
+ const state = ops.lstat(rel);
597
707
  if (!state) return;
598
708
  // A boundary is entirely outside this deployment. Do not descend into it:
599
709
  // logs/caches are owned by their runtime, not by this installer.
@@ -641,6 +751,15 @@ function runAuthoritativeRepoInstall(pluginRoot, options, context) {
641
751
  );
642
752
  }
643
753
 
754
+ // Current plans cannot create links. Remove every exact link recorded by a
755
+ // legacy lock before rebuilding roots, first cutting any linked ancestor so
756
+ // a descendant record can never escape the repository. FileOps carries this
757
+ // state virtually during --dry-run, keeping its plan identical to a real run.
758
+ for (const rel of Object.keys(prev.symlinks ?? {})) {
759
+ replaceSymlinkAncestors(rel, ops);
760
+ ops.removeSymlink(rel, "legacy managed symlink hard cut");
761
+ }
762
+
644
763
  // A reconciliation owns the complete declared component surface, not just
645
764
  // the hosts selected for this invocation. Otherwise a previous host's
646
765
  // root would become an accidental preservation zone when the host list is
@@ -661,7 +780,7 @@ function runAuthoritativeRepoInstall(pluginRoot, options, context) {
661
780
 
662
781
  const files = {};
663
782
  for (const [rel, content] of desired) {
664
- replaceSymlinkAncestors(repo, rel, ops);
783
+ replaceSymlinkAncestors(rel, ops);
665
784
  ops.write(rel, content, "authoritative bundle projection");
666
785
  files[rel] = { sha256: sha256(content) };
667
786
  }
@@ -689,7 +808,6 @@ function runAuthoritativeRepoInstall(pluginRoot, options, context) {
689
808
  version: bundle.version,
690
809
  hosts,
691
810
  files: sortObject(files),
692
- symlinks: {},
693
811
  toml: {},
694
812
  gitignore: {},
695
813
  config,
@@ -770,12 +888,16 @@ export const fileSha = (repo, rel) => sha256(readFileSync(abs(repo, rel)));
770
888
  *
771
889
  * Scoped to ancestors strictly inside the repo, and only those that are links.
772
890
  */
773
- function replaceSymlinkAncestors(repo, rel, ops) {
891
+ function replaceSymlinkAncestors(rel, ops) {
774
892
  const parts = rel.split("/").slice(0, -1);
775
893
  for (let i = 1; i <= parts.length; i++) {
776
894
  const dirRel = parts.slice(0, i).join("/");
777
- const st = lstatSync(abs(repo, dirRel), { throwIfNoEntry: false });
778
- if (st?.isSymbolicLink()) ops.removeSymlink(dirRel, "replacing a symlinked directory with real content");
895
+ const st = ops.lstat(dirRel);
896
+ if (st?.isSymbolicLink()) {
897
+ ops.removeSymlink(dirRel, "replacing a symlinked directory with real content");
898
+ return;
899
+ }
900
+ if (!st || !st.isDirectory()) return;
779
901
  }
780
902
  }
781
903
 
package/spec/enact.json CHANGED
@@ -70,6 +70,15 @@
70
70
  "description": "Relative path to the agents directory.",
71
71
  "default": "./agents/"
72
72
  },
73
+ "profileSources": {
74
+ "type": "array",
75
+ "description": "Named sibling plugins whose declared canonical agents directories are projected as native repo-local profiles by this bundle. This installer-only field is omitted from host manifests.",
76
+ "items": {
77
+ "type": "string",
78
+ "pattern": "^[a-z][a-z0-9-]*$"
79
+ },
80
+ "uniqueItems": true
81
+ },
73
82
  "commands": {
74
83
  "type": "string",
75
84
  "description": "Relative path to the commands directory (flat Markdown files).",