@orchestrator-claude/definitions 3.37.0 → 3.37.2

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 (73) hide show
  1. package/agents/adversarial-reviewer.md +6 -1
  2. package/agents/api-extractor.md +6 -0
  3. package/agents/azure-devops-engineer.md +1 -2
  4. package/agents/business-rule-miner.md +6 -0
  5. package/agents/cicd-platform-engineer.md +1 -2
  6. package/agents/ciclo-engineer.md +50 -21
  7. package/agents/code-archaeologist.md +6 -0
  8. package/agents/debug-sidecar.md +6 -0
  9. package/agents/doc-sidecar.md +6 -0
  10. package/agents/docs-guardian.md +9 -3
  11. package/agents/frontend-engineer.md +1 -2
  12. package/agents/{ai-architect.md → harness-architect.md} +8 -3
  13. package/agents/implementer.md +6 -1
  14. package/agents/legacy-discoverer.md +6 -0
  15. package/agents/legacy-synthesizer.md +6 -0
  16. package/agents/methodology-researcher.md +6 -1
  17. package/agents/operational-artifact-builder.md +6 -1
  18. package/agents/orchestrator.md +27 -87
  19. package/agents/planner.md +6 -1
  20. package/agents/presentation-engineer.md +29 -15
  21. package/agents/python-data-engineer.md +0 -1
  22. package/agents/researcher.md +6 -0
  23. package/agents/reviewer.md +6 -1
  24. package/agents/schema-extractor.md +6 -0
  25. package/agents/software-architect.md +10 -5
  26. package/agents/specifier.md +6 -1
  27. package/agents/task-generator.md +6 -1
  28. package/agents/test-sidecar.md +6 -0
  29. package/dist/scripts/generate-hooks-matcher.d.ts +106 -0
  30. package/dist/scripts/generate-hooks-matcher.d.ts.map +1 -0
  31. package/dist/scripts/generate-hooks-matcher.js +153 -0
  32. package/dist/scripts/generate-hooks-matcher.js.map +1 -0
  33. package/dist/scripts/generate-manifest.d.ts +22 -0
  34. package/dist/scripts/generate-manifest.d.ts.map +1 -1
  35. package/dist/scripts/generate-manifest.js +67 -2
  36. package/dist/scripts/generate-manifest.js.map +1 -1
  37. package/hooks/agent-git-guard.mjs +63 -11
  38. package/hooks/dangling-guard.mjs +42 -12
  39. package/hooks/gate-guardian.mjs +38 -8
  40. package/hooks/hooks.json +3 -9
  41. package/hooks/lib/api-client.ts +128 -9
  42. package/hooks/lib/capability-scanner.ts +462 -55
  43. package/hooks/lib/dispatch-marker.ts +214 -0
  44. package/hooks/lib/git-checkpoint.ts +34 -37
  45. package/hooks/lib/observations-helper.ts +14 -1
  46. package/hooks/lib/security-gate-core.ts +271 -0
  47. package/hooks/mailbox-listener.mjs +69 -17
  48. package/hooks/playwright-output-guard.mjs +40 -10
  49. package/hooks/post-implement.mjs +38 -8
  50. package/hooks/pre-agent-dispatch.mjs +137 -16
  51. package/hooks/pre-agent-dispatch.ts +82 -15
  52. package/hooks/security-gate-honest.mjs +302 -0
  53. package/hooks/security-gate-honest.ts +148 -0
  54. package/hooks/session-start.mjs +304 -106
  55. package/hooks/session-start.ts +317 -71
  56. package/hooks/subagent-start.mjs +7673 -22
  57. package/hooks/subagent-start.ts +367 -16
  58. package/hooks/subagent-stop.mjs +102 -62
  59. package/hooks/subagent-stop.ts +124 -28
  60. package/hooks/user-prompt.mjs +43 -13
  61. package/hooks/verification-before-completion.mjs +63 -11
  62. package/hooks/workflow-guard.mjs +45 -11
  63. package/hooks-settings-template.json +1 -7
  64. package/manifest.json +77 -61
  65. package/package.json +4 -2
  66. package/skills/checkpoint-protocol/SKILL.md +19 -4
  67. package/skills/ciclo-lane-dispatch/SKILL.md +117 -8
  68. package/skills/fase-1b-projecao/SKILL.md +150 -0
  69. package/skills/lane-1-entrevista/SKILL.md +173 -0
  70. package/skills/orchestrator/SKILL.md +11 -3
  71. package/skills/workflow-coordination/SKILL.md +3 -3
  72. package/hooks/post-compact.mjs +0 -7931
  73. package/hooks/post-compact.ts +0 -170
@@ -121,15 +121,80 @@ export function generateManifest(packageRoot = DEFAULT_PACKAGE_ROOT) {
121
121
  };
122
122
  return manifest;
123
123
  }
124
+ /**
125
+ * Deep structural equality ignoring key order. Used to answer "did the manifest
126
+ * CONTENT change?" — the previous manifest is parsed from disk, so its key order
127
+ * comes from the file and cannot be compared by raw serialization.
128
+ */
129
+ function deepEqual(a, b) {
130
+ if (a === b)
131
+ return true;
132
+ if (typeof a !== typeof b || a === null || b === null)
133
+ return false;
134
+ if (typeof a !== 'object')
135
+ return false;
136
+ if (Array.isArray(a) || Array.isArray(b)) {
137
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)
138
+ return false;
139
+ return a.every((item, i) => deepEqual(item, b[i]));
140
+ }
141
+ const aKeys = Object.keys(a).sort();
142
+ const bKeys = Object.keys(b).sort();
143
+ if (aKeys.length !== bKeys.length || !aKeys.every((k, i) => k === bKeys[i]))
144
+ return false;
145
+ return aKeys.every((k) => deepEqual(a[k], b[k]));
146
+ }
147
+ /**
148
+ * True when two manifests differ ONLY by their `generatedAt` stamp — i.e. the
149
+ * substantive content (schema, namespace, version, and every definition entry
150
+ * with its content-derived checksum) is identical.
151
+ */
152
+ export function isManifestContentEqual(a, b) {
153
+ const { generatedAt: _a, ...restA } = a;
154
+ const { generatedAt: _b, ...restB } = b;
155
+ return deepEqual(restA, restB);
156
+ }
124
157
  /**
125
158
  * Thin writer: computes the manifest via generateManifest() and writes it to
126
159
  * <packageRoot>/manifest.json. This is the only function in this module that
127
160
  * performs I/O writes.
161
+ *
162
+ * IDEMPOTENT (S445 Task B). `generatedAt` is the only clock-derived field in the
163
+ * manifest — every other field is content-derived (SHA256 checksums). Stamping a
164
+ * fresh timestamp unconditionally meant that every `npm run build` produced a
165
+ * diff in the git-TRACKED manifest.json even when not a single byte of any
166
+ * definition had changed. Two costs, both real and both paid repeatedly: the
167
+ * working tree was left dirty after any build (and the release requires a clean
168
+ * tree), and readers were trained to wave away diffs in the one file whose diffs
169
+ * carry the checksum of every distributed definition.
170
+ *
171
+ * So `generatedAt` is preserved whenever the content is unchanged, and the write
172
+ * is skipped entirely when the resulting bytes would be identical (this also
173
+ * leaves mtime alone, so mtime-based caches elsewhere are not churned either).
174
+ * The field keeps its documented meaning and stays a real ISO instant: it now
175
+ * answers "when was this manifest generated", where before it answered "when was
176
+ * this build last run" — which is what made it non-reproducible.
128
177
  */
129
178
  export function writeManifest(packageRoot = DEFAULT_PACKAGE_ROOT) {
130
- const manifest = generateManifest(packageRoot);
179
+ const next = generateManifest(packageRoot);
131
180
  const outputPath = resolve(packageRoot, 'manifest.json');
132
- writeFileSync(outputPath, JSON.stringify(manifest, null, 2) + '\n');
181
+ let previousRaw = null;
182
+ let previous = null;
183
+ try {
184
+ previousRaw = readFileSync(outputPath, 'utf-8');
185
+ previous = JSON.parse(previousRaw);
186
+ }
187
+ catch {
188
+ // Absent or unparseable (cold start / corrupted) — fall through and write.
189
+ previous = null;
190
+ }
191
+ const manifest = previous && isManifestContentEqual(previous, next)
192
+ ? { ...next, generatedAt: previous.generatedAt }
193
+ : next;
194
+ const serialized = JSON.stringify(manifest, null, 2) + '\n';
195
+ if (previousRaw === serialized)
196
+ return manifest;
197
+ writeFileSync(outputPath, serialized);
133
198
  return manifest;
134
199
  }
135
200
  // ─── CLI Entry Guard ──────────────────────────────────────────────────────────
@@ -1 +1 @@
1
- {"version":3,"file":"generate-manifest.js","sourceRoot":"","sources":["../../src/scripts/generate-manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate-manifest.js","sourceRoot":"","sources":["../../src/scripts/generate-manifest.ts"],"names":[],"mappings":"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"}
@@ -2,19 +2,71 @@ import { createRequire as __createRequireShim } from 'node:module'; const requir
2
2
 
3
3
  // hooks/lib/api-client.ts
4
4
  import { readFileSync, writeFileSync, mkdirSync, statSync, unlinkSync, readdirSync } from "node:fs";
5
- import { join, dirname } from "node:path";
6
- import { fileURLToPath } from "node:url";
7
- var __filename = fileURLToPath(import.meta.url);
8
- var __dirname = dirname(__filename);
9
- var PROJECT_ROOT = join(__dirname, "..", "..", "..");
10
- var STATE_DIR = join(PROJECT_ROOT, ".orchestrator", ".state");
11
- var JWT_CACHE = join(STATE_DIR, "jwt-token");
12
- var DEBUG_LOG = join(STATE_DIR, "hook-debug.log");
5
+ import { join as join2 } from "node:path";
6
+ import { tmpdir } from "node:os";
7
+ import { createHash } from "node:crypto";
8
+
9
+ // ../project-root-resolver/dist/index.js
10
+ import { existsSync } from "node:fs";
11
+ import { dirname, join } from "node:path";
12
+ function hasProjectRootMarker(candidate, sentinel) {
13
+ return existsSync(join(candidate, ".git")) || existsSync(join(candidate, "package.json")) || existsSync(join(candidate, sentinel, ".root"));
14
+ }
15
+ function resolveProjectRoot(cwd, sentinel = ".orchestrator") {
16
+ const candidates = [];
17
+ let currentDir = cwd;
18
+ for (; ; ) {
19
+ if (existsSync(join(currentDir, sentinel))) {
20
+ candidates.push(currentDir);
21
+ }
22
+ const parentDir = dirname(currentDir);
23
+ if (parentDir === currentDir) {
24
+ break;
25
+ }
26
+ currentDir = parentDir;
27
+ }
28
+ const [innermost] = candidates;
29
+ if (innermost === void 0) {
30
+ return null;
31
+ }
32
+ for (const candidate of candidates) {
33
+ if (hasProjectRootMarker(candidate, sentinel)) {
34
+ return candidate;
35
+ }
36
+ }
37
+ return innermost;
38
+ }
39
+
40
+ // hooks/lib/api-client.ts
41
+ function resolveFallbackStateDir(cwd) {
42
+ const cwdHash = createHash("sha256").update(cwd).digest("hex").slice(0, 16);
43
+ return join2(tmpdir(), "orchestrator-hook-fallback", cwdHash);
44
+ }
45
+ var PROJECT_ROOT = (() => {
46
+ const resolved = resolveHookProjectRoot(process.cwd());
47
+ if (resolved !== null && hasProjectRootMarker(resolved, ".orchestrator")) {
48
+ return resolved;
49
+ }
50
+ return null;
51
+ })();
52
+ var STATE_DIR_OVERRIDE = process.env.ORCHESTRATOR_STATE_DIR;
53
+ var STATE_DIR = STATE_DIR_OVERRIDE !== void 0 && STATE_DIR_OVERRIDE !== "" ? STATE_DIR_OVERRIDE : PROJECT_ROOT !== null ? join2(PROJECT_ROOT, ".orchestrator", ".state") : resolveFallbackStateDir(process.cwd());
54
+ var JWT_CACHE = join2(STATE_DIR, "jwt-token");
55
+ var DEBUG_LOG = join2(STATE_DIR, "hook-debug.log");
13
56
  mkdirSync(STATE_DIR, { recursive: true });
57
+ if ((STATE_DIR_OVERRIDE === void 0 || STATE_DIR_OVERRIDE === "") && PROJECT_ROOT === null) {
58
+ log(
59
+ "API-CLIENT",
60
+ `PROJECT_ROOT: no marker-verified ".orchestrator" project root found above ${process.cwd()} \u2014 falling back to isolated state dir ${STATE_DIR} (RF-003)`
61
+ );
62
+ }
14
63
  var API_URL = process.env.ORCHESTRATOR_API_URL || "http://localhost:3001";
15
64
  var AUTH_EMAIL = process.env.ORCHESTRATOR_ADMIN_EMAIL || process.env.ORCHESTRATOR_AUTH_EMAIL || "system@orchestrator.local";
16
65
  var AUTH_PASSWORD = process.env.ORCHESTRATOR_ADMIN_PASSWORD || process.env.ORCHESTRATOR_AUTH_PASSWORD || "system123";
17
66
  var PROJECT_ID = process.env.ORCHESTRATOR_PROJECT_ID || "";
67
+ function resolveHookProjectRoot(cwd) {
68
+ return resolveProjectRoot(cwd);
69
+ }
18
70
  function log(prefix, msg) {
19
71
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d+Z$/, "Z");
20
72
  try {
@@ -24,11 +76,11 @@ function log(prefix, msg) {
24
76
  } catch {
25
77
  }
26
78
  }
27
- var LAST_COMPLETED_FILE = join(STATE_DIR, "last-completed-workflow.json");
79
+ var LAST_COMPLETED_FILE = join2(STATE_DIR, "last-completed-workflow.json");
28
80
  var LAST_COMPLETED_TTL_MS = 60 * 60 * 1e3;
29
- var INVOCATIONS_DIR = join(STATE_DIR, "invocations");
81
+ var INVOCATIONS_DIR = join2(STATE_DIR, "invocations");
30
82
  var INVOCATION_STATE_TTL_MS = 4 * 60 * 60 * 1e3;
31
- var DISPATCH_INTENT_DIR = join(STATE_DIR, "dispatch-intent");
83
+ var DISPATCH_INTENT_DIR = join2(STATE_DIR, "dispatch-intent");
32
84
  async function readStdin() {
33
85
  const chunks = [];
34
86
  for await (const chunk of process.stdin) {
@@ -3925,7 +3925,7 @@ var init_esm5 = __esm({
3925
3925
 
3926
3926
  // ../../node_modules/path-scurry/dist/esm/index.js
3927
3927
  import { posix, win32 } from "node:path";
3928
- import { fileURLToPath as fileURLToPath2 } from "node:url";
3928
+ import { fileURLToPath } from "node:url";
3929
3929
  import { lstatSync, readdir as readdirCB, readdirSync as readdirSync2, readlinkSync, realpathSync as rps } from "fs";
3930
3930
  import * as actualFS from "node:fs";
3931
3931
  import { lstat, readdir, readlink, realpath } from "node:fs/promises";
@@ -5057,7 +5057,7 @@ var init_esm6 = __esm({
5057
5057
  constructor(cwd = process.cwd(), pathImpl, sep2, { nocase, childrenCacheSize = 16 * 1024, fs = defaultFS } = {}) {
5058
5058
  this.#fs = fsFromOption(fs);
5059
5059
  if (cwd instanceof URL || cwd.startsWith("file://")) {
5060
- cwd = fileURLToPath2(cwd);
5060
+ cwd = fileURLToPath(cwd);
5061
5061
  }
5062
5062
  const cwdPath = pathImpl.resolve(cwd);
5063
5063
  this.roots = /* @__PURE__ */ Object.create(null);
@@ -6491,7 +6491,7 @@ var init_walker = __esm({
6491
6491
  });
6492
6492
 
6493
6493
  // ../../node_modules/glob/dist/esm/glob.js
6494
- import { fileURLToPath as fileURLToPath3 } from "node:url";
6494
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
6495
6495
  var defaultPlatform3, Glob;
6496
6496
  var init_glob = __esm({
6497
6497
  "../../node_modules/glob/dist/esm/glob.js"() {
@@ -6559,7 +6559,7 @@ var init_glob = __esm({
6559
6559
  if (!opts.cwd) {
6560
6560
  this.cwd = "";
6561
6561
  } else if (opts.cwd instanceof URL || opts.cwd.startsWith("file://")) {
6562
- opts.cwd = fileURLToPath3(opts.cwd);
6562
+ opts.cwd = fileURLToPath2(opts.cwd);
6563
6563
  }
6564
6564
  this.cwd = opts.cwd || "";
6565
6565
  this.root = opts.root;
@@ -6799,34 +6799,64 @@ var init_esm7 = __esm({
6799
6799
 
6800
6800
  // hooks/lib/api-client.ts
6801
6801
  import { readFileSync, writeFileSync, mkdirSync, statSync, unlinkSync, readdirSync } from "node:fs";
6802
- import { join as join2, dirname as dirname2 } from "node:path";
6803
- import { fileURLToPath } from "node:url";
6802
+ import { join as join2 } from "node:path";
6803
+ import { tmpdir } from "node:os";
6804
+ import { createHash } from "node:crypto";
6804
6805
 
6805
6806
  // ../project-root-resolver/dist/index.js
6806
6807
  import { existsSync } from "node:fs";
6807
6808
  import { dirname, join } from "node:path";
6809
+ function hasProjectRootMarker(candidate, sentinel) {
6810
+ return existsSync(join(candidate, ".git")) || existsSync(join(candidate, "package.json")) || existsSync(join(candidate, sentinel, ".root"));
6811
+ }
6808
6812
  function resolveProjectRoot(cwd, sentinel = ".orchestrator") {
6813
+ const candidates = [];
6809
6814
  let currentDir = cwd;
6810
6815
  for (; ; ) {
6811
6816
  if (existsSync(join(currentDir, sentinel))) {
6812
- return currentDir;
6817
+ candidates.push(currentDir);
6813
6818
  }
6814
6819
  const parentDir = dirname(currentDir);
6815
6820
  if (parentDir === currentDir) {
6816
- return null;
6821
+ break;
6817
6822
  }
6818
6823
  currentDir = parentDir;
6819
6824
  }
6825
+ const [innermost] = candidates;
6826
+ if (innermost === void 0) {
6827
+ return null;
6828
+ }
6829
+ for (const candidate of candidates) {
6830
+ if (hasProjectRootMarker(candidate, sentinel)) {
6831
+ return candidate;
6832
+ }
6833
+ }
6834
+ return innermost;
6820
6835
  }
6821
6836
 
6822
6837
  // hooks/lib/api-client.ts
6823
- var __filename = fileURLToPath(import.meta.url);
6824
- var __dirname = dirname2(__filename);
6825
- var PROJECT_ROOT = join2(__dirname, "..", "..", "..");
6826
- var STATE_DIR = join2(PROJECT_ROOT, ".orchestrator", ".state");
6838
+ function resolveFallbackStateDir(cwd) {
6839
+ const cwdHash = createHash("sha256").update(cwd).digest("hex").slice(0, 16);
6840
+ return join2(tmpdir(), "orchestrator-hook-fallback", cwdHash);
6841
+ }
6842
+ var PROJECT_ROOT = (() => {
6843
+ const resolved = resolveHookProjectRoot(process.cwd());
6844
+ if (resolved !== null && hasProjectRootMarker(resolved, ".orchestrator")) {
6845
+ return resolved;
6846
+ }
6847
+ return null;
6848
+ })();
6849
+ var STATE_DIR_OVERRIDE = process.env.ORCHESTRATOR_STATE_DIR;
6850
+ var STATE_DIR = STATE_DIR_OVERRIDE !== void 0 && STATE_DIR_OVERRIDE !== "" ? STATE_DIR_OVERRIDE : PROJECT_ROOT !== null ? join2(PROJECT_ROOT, ".orchestrator", ".state") : resolveFallbackStateDir(process.cwd());
6827
6851
  var JWT_CACHE = join2(STATE_DIR, "jwt-token");
6828
6852
  var DEBUG_LOG = join2(STATE_DIR, "hook-debug.log");
6829
6853
  mkdirSync(STATE_DIR, { recursive: true });
6854
+ if ((STATE_DIR_OVERRIDE === void 0 || STATE_DIR_OVERRIDE === "") && PROJECT_ROOT === null) {
6855
+ log(
6856
+ "API-CLIENT",
6857
+ `PROJECT_ROOT: no marker-verified ".orchestrator" project root found above ${process.cwd()} \u2014 falling back to isolated state dir ${STATE_DIR} (RF-003)`
6858
+ );
6859
+ }
6830
6860
  var API_URL = process.env.ORCHESTRATOR_API_URL || "http://localhost:3001";
6831
6861
  var AUTH_EMAIL = process.env.ORCHESTRATOR_ADMIN_EMAIL || process.env.ORCHESTRATOR_AUTH_EMAIL || "system@orchestrator.local";
6832
6862
  var AUTH_PASSWORD = process.env.ORCHESTRATOR_ADMIN_PASSWORD || process.env.ORCHESTRATOR_AUTH_PASSWORD || "system123";
@@ -2,34 +2,64 @@ import { createRequire as __createRequireShim } from 'node:module'; const requir
2
2
 
3
3
  // hooks/lib/api-client.ts
4
4
  import { readFileSync, writeFileSync, mkdirSync, statSync, unlinkSync, readdirSync } from "node:fs";
5
- import { join as join2, dirname as dirname2 } from "node:path";
6
- import { fileURLToPath } from "node:url";
5
+ import { join as join2 } from "node:path";
6
+ import { tmpdir } from "node:os";
7
+ import { createHash } from "node:crypto";
7
8
 
8
9
  // ../project-root-resolver/dist/index.js
9
10
  import { existsSync } from "node:fs";
10
11
  import { dirname, join } from "node:path";
12
+ function hasProjectRootMarker(candidate, sentinel) {
13
+ return existsSync(join(candidate, ".git")) || existsSync(join(candidate, "package.json")) || existsSync(join(candidate, sentinel, ".root"));
14
+ }
11
15
  function resolveProjectRoot(cwd, sentinel = ".orchestrator") {
16
+ const candidates = [];
12
17
  let currentDir = cwd;
13
18
  for (; ; ) {
14
19
  if (existsSync(join(currentDir, sentinel))) {
15
- return currentDir;
20
+ candidates.push(currentDir);
16
21
  }
17
22
  const parentDir = dirname(currentDir);
18
23
  if (parentDir === currentDir) {
19
- return null;
24
+ break;
20
25
  }
21
26
  currentDir = parentDir;
22
27
  }
28
+ const [innermost] = candidates;
29
+ if (innermost === void 0) {
30
+ return null;
31
+ }
32
+ for (const candidate of candidates) {
33
+ if (hasProjectRootMarker(candidate, sentinel)) {
34
+ return candidate;
35
+ }
36
+ }
37
+ return innermost;
23
38
  }
24
39
 
25
40
  // hooks/lib/api-client.ts
26
- var __filename = fileURLToPath(import.meta.url);
27
- var __dirname = dirname2(__filename);
28
- var PROJECT_ROOT = join2(__dirname, "..", "..", "..");
29
- var STATE_DIR = join2(PROJECT_ROOT, ".orchestrator", ".state");
41
+ function resolveFallbackStateDir(cwd) {
42
+ const cwdHash = createHash("sha256").update(cwd).digest("hex").slice(0, 16);
43
+ return join2(tmpdir(), "orchestrator-hook-fallback", cwdHash);
44
+ }
45
+ var PROJECT_ROOT = (() => {
46
+ const resolved = resolveHookProjectRoot(process.cwd());
47
+ if (resolved !== null && hasProjectRootMarker(resolved, ".orchestrator")) {
48
+ return resolved;
49
+ }
50
+ return null;
51
+ })();
52
+ var STATE_DIR_OVERRIDE = process.env.ORCHESTRATOR_STATE_DIR;
53
+ var STATE_DIR = STATE_DIR_OVERRIDE !== void 0 && STATE_DIR_OVERRIDE !== "" ? STATE_DIR_OVERRIDE : PROJECT_ROOT !== null ? join2(PROJECT_ROOT, ".orchestrator", ".state") : resolveFallbackStateDir(process.cwd());
30
54
  var JWT_CACHE = join2(STATE_DIR, "jwt-token");
31
55
  var DEBUG_LOG = join2(STATE_DIR, "hook-debug.log");
32
56
  mkdirSync(STATE_DIR, { recursive: true });
57
+ if ((STATE_DIR_OVERRIDE === void 0 || STATE_DIR_OVERRIDE === "") && PROJECT_ROOT === null) {
58
+ log(
59
+ "API-CLIENT",
60
+ `PROJECT_ROOT: no marker-verified ".orchestrator" project root found above ${process.cwd()} \u2014 falling back to isolated state dir ${STATE_DIR} (RF-003)`
61
+ );
62
+ }
33
63
  var API_URL = process.env.ORCHESTRATOR_API_URL || "http://localhost:3001";
34
64
  var AUTH_EMAIL = process.env.ORCHESTRATOR_ADMIN_EMAIL || process.env.ORCHESTRATOR_AUTH_EMAIL || "system@orchestrator.local";
35
65
  var AUTH_PASSWORD = process.env.ORCHESTRATOR_ADMIN_PASSWORD || process.env.ORCHESTRATOR_AUTH_PASSWORD || "system123";
package/hooks/hooks.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "hooks": {
3
3
  "SessionStart": [
4
4
  {
5
- "matcher": "startup|resume",
5
+ "matcher": "startup|resume|clear|compact|fork",
6
6
  "hooks": [
7
7
  { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start.mjs\"", "timeout": 10000 },
8
8
  { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/sprint-registry.mjs\"", "timeout": 5000 }
@@ -42,13 +42,13 @@
42
42
  ],
43
43
  "SubagentStart": [
44
44
  {
45
- "matcher": "(orchestrator:)?(implementer|specifier|planner|task-generator|reviewer|researcher)",
45
+ "matcher": "(orchestrator:)?(adversarial-reviewer|api-extractor|azure-devops-engineer|business-rule-miner|cicd-platform-engineer|ciclo-engineer|code-archaeologist|debug-sidecar|doc-sidecar|docs-guardian|frontend-engineer|harness-architect|implementer|legacy-discoverer|legacy-synthesizer|methodology-researcher|operational-artifact-builder|orchestrator|planner|presentation-engineer|python-data-engineer|researcher|reviewer|schema-extractor|software-architect|specifier|task-generator|test-sidecar)",
46
46
  "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/subagent-start.mjs\"", "timeout": 10000 }]
47
47
  }
48
48
  ],
49
49
  "SubagentStop": [
50
50
  {
51
- "matcher": "(orchestrator:)?(implementer|specifier|planner|task-generator|reviewer|researcher)",
51
+ "matcher": "(orchestrator:)?(adversarial-reviewer|api-extractor|azure-devops-engineer|business-rule-miner|cicd-platform-engineer|ciclo-engineer|code-archaeologist|debug-sidecar|doc-sidecar|docs-guardian|frontend-engineer|harness-architect|implementer|legacy-discoverer|legacy-synthesizer|methodology-researcher|operational-artifact-builder|orchestrator|planner|presentation-engineer|python-data-engineer|researcher|reviewer|schema-extractor|software-architect|specifier|task-generator|test-sidecar)",
52
52
  "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/subagent-stop.mjs\"", "timeout": 30000 }]
53
53
  }
54
54
  ],
@@ -67,12 +67,6 @@
67
67
  "matcher": "mcp__(plugin_orchestrator_)?orchestrator-tools__advancePhase",
68
68
  "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/post-implement.mjs\"", "timeout": 15000 }]
69
69
  }
70
- ],
71
- "PostCompact": [
72
- {
73
- "matcher": "",
74
- "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/post-compact.mjs\"", "timeout": 5000 }]
75
- }
76
70
  ]
77
71
  }
78
72
  }
@@ -4,21 +4,119 @@
4
4
  */
5
5
 
6
6
  import { readFileSync, writeFileSync, mkdirSync, statSync, unlinkSync, readdirSync } from 'node:fs';
7
- import { join, dirname } from 'node:path';
8
- import { fileURLToPath } from 'node:url';
9
- import { resolveProjectRoot } from '@orchestrator-claude/project-root-resolver';
10
-
11
- // Resolve paths relative to this file
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = dirname(__filename);
14
- const PROJECT_ROOT = join(__dirname, '..', '..', '..');
15
- const STATE_DIR = join(PROJECT_ROOT, '.orchestrator', '.state');
7
+ import { join } from 'node:path';
8
+ import { tmpdir } from 'node:os';
9
+ import { createHash } from 'node:crypto';
10
+ import {
11
+ resolveProjectRoot,
12
+ hasProjectRootMarker,
13
+ } from '@orchestrator-claude/project-root-resolver';
14
+
15
+ // S467 H-1 (TASK-004): `__filename`/`__dirname` (this file's own on-disk
16
+ // location) used to anchor PROJECT_ROOT below — removed together with that
17
+ // derivation. See the RF-001/RF-002/RF-003 comment block ahead of
18
+ // PROJECT_ROOT for why anchoring on this file's own location was the bug.
19
+
20
+ /**
21
+ * RF-003 (S467, H-1): pure, zero-throw fallback used when the calling
22
+ * session's own cwd has no resolvable, marker-verified `.orchestrator`
23
+ * project root (see PROJECT_ROOT below) — e.g. an arbitrary directory, or a
24
+ * bare/incidental sentinel that fails the marker check (RF-002). Isolated
25
+ * per-cwd via a stable hash so two distinct unresolved cwds never collide
26
+ * on the same fallback directory (verified:
27
+ * api-client-project-root-derivation.test.ts, RF-003 anti-collision case),
28
+ * and deliberately OUTSIDE this repo's own tree (os.tmpdir()) so it can
29
+ * never be mistaken for, or leak into, this repo's own `.orchestrator/.state`.
30
+ */
31
+ export function resolveFallbackStateDir(cwd: string): string {
32
+ const cwdHash = createHash('sha256').update(cwd).digest('hex').slice(0, 16);
33
+ return join(tmpdir(), 'orchestrator-hook-fallback', cwdHash);
34
+ }
35
+
36
+ // TD-224 Achado 0 (S426) superseded by S467 H-1 (RF-001/RF-002/RF-003): this
37
+ // used to derive PROJECT_ROOT via `resolveProjectRoot(__dirname)` —
38
+ // `__dirname` is the location of THIS FILE ON DISK, not the calling
39
+ // session's own working directory. Because the `orchestrator-local`
40
+ // marketplace resolves by `directory` (marketplace.json `source:
41
+ // "./packages/definitions"`), every hook process on this machine, for every
42
+ // session of every consumer project, has `__dirname` inside THIS repo's own
43
+ // checkout — so the walk-up always found and won on THIS repo's
44
+ // `.orchestrator` sentinel, regardless of which project's session actually
45
+ // invoked the hook. Cross-project state leakage (H-1).
46
+ //
47
+ // RF-001: anchor on `process.cwd()` — the session's own cwd — via the
48
+ // already-exported `resolveHookProjectRoot` wrapper below, instead of
49
+ // `__dirname`.
50
+ //
51
+ // RF-002: a bare `.orchestrator` sentinel with none of
52
+ // `.git`/`package.json`/`.orchestrator/.root` (e.g. a real user home
53
+ // directory that happens to carry a bare `.orchestrator` dir — measured
54
+ // S466/S467 against this very machine's `/home/cmac`) must NOT resolve to
55
+ // itself. `resolveProjectRoot`'s own backward-compatible fallback
56
+ // (innermost-wins when no candidate satisfies the marker check, ADR-P3)
57
+ // would otherwise happily return it — reject that case explicitly via the
58
+ // now-exported `hasProjectRootMarker` (ADR-P3, TASK-003) and fall through
59
+ // to RF-003.
60
+ //
61
+ // RF-003: never `throw` at module load. The prior comment here justified
62
+ // throwing by citing `.orchestrator/.state/.gitkeep` (tracked at this
63
+ // repo's own root) as a guarantee the sentinel is "always present" — that
64
+ // guarantee held only because the OLD code anchored on `__dirname` (always
65
+ // inside this repo). It stops applying once the anchor is `process.cwd()`
66
+ // of an arbitrary session: a hook process serving ANY unregistered cwd must
67
+ // still load and degrade gracefully into an isolated, per-cwd fallback
68
+ // state directory (`resolveFallbackStateDir` above), not crash every hook
69
+ // invocation for that session (RNF-001, availability).
70
+ //
71
+ // ORCHESTRATOR_STATE_DIR (TD-224 Achado 1, RACE-001) is resolved separately
72
+ // below and continues to win unconditionally over ALL of this — checked
73
+ // before any consumer of PROJECT_ROOT/STATE_DIR ever runs.
74
+ const PROJECT_ROOT = ((): string | null => {
75
+ const resolved = resolveHookProjectRoot(process.cwd());
76
+ if (resolved !== null && hasProjectRootMarker(resolved, '.orchestrator')) {
77
+ return resolved;
78
+ }
79
+ return null;
80
+ })();
81
+ // TD-224 Achado 1 (S426, RACE-001): ORCHESTRATOR_STATE_DIR, when set, wins
82
+ // outright over the .orchestrator-sentinel-derived PROJECT_ROOT — every
83
+ // state-file path below (JWT_CACHE, DEBUG_LOG, invocation/dispatch-intent
84
+ // state) resolves inside the override directory instead. Motivation:
85
+ // tests/unit/seam-conformance's execution extractor drives every exported
86
+ // function of this module for real (fetch mocked, everything else live) to
87
+ // build a route census; without this seam, the ONLY way to keep it from
88
+ // touching the REAL dev-session jwt-token cache was a backup/seed/restore
89
+ // dance around the real path — unsafe both under concurrent test-file
90
+ // execution (two vitest worker threads) and under process interruption (a
91
+ // kill between "seed" and "restore" corrupts the real cache with zero
92
+ // concurrency required). Pointing this override at an isolated temp
93
+ // directory removes the real path from the equation entirely: no window,
94
+ // concurrent or interrupted, in which it is ever opened. Unset in every
95
+ // production invocation — default derivation is unchanged.
96
+ const STATE_DIR_OVERRIDE = process.env.ORCHESTRATOR_STATE_DIR;
97
+ const STATE_DIR =
98
+ STATE_DIR_OVERRIDE !== undefined && STATE_DIR_OVERRIDE !== ''
99
+ ? STATE_DIR_OVERRIDE
100
+ : PROJECT_ROOT !== null
101
+ ? join(PROJECT_ROOT, '.orchestrator', '.state')
102
+ : resolveFallbackStateDir(process.cwd());
16
103
  const JWT_CACHE = join(STATE_DIR, 'jwt-token');
17
104
  const DEBUG_LOG = join(STATE_DIR, 'hook-debug.log');
18
105
 
19
106
  // Ensure state dir exists
20
107
  mkdirSync(STATE_DIR, { recursive: true });
21
108
 
109
+ // RF-003: log the fallback degradation, once, at module load — but only
110
+ // when it actually happened (override absent AND no marker-verified
111
+ // project root resolved for this cwd).
112
+ if ((STATE_DIR_OVERRIDE === undefined || STATE_DIR_OVERRIDE === '') && PROJECT_ROOT === null) {
113
+ log(
114
+ 'API-CLIENT',
115
+ `PROJECT_ROOT: no marker-verified ".orchestrator" project root found above ${process.cwd()} — ` +
116
+ `falling back to isolated state dir ${STATE_DIR} (RF-003)`
117
+ );
118
+ }
119
+
22
120
  // Config from env
23
121
  const API_URL = process.env.ORCHESTRATOR_API_URL || 'http://localhost:3001';
24
122
  // RFC-040 ADR-002 (S358, TASK-RBAC-02): hooks authenticate as the seeded
@@ -153,6 +251,27 @@ export function setEffectiveProjectId(projectId: string): void {
153
251
  PROJECT_ID = projectId;
154
252
  }
155
253
 
254
+ // --- Agent Identity Normalization (TD-214/TD-239 TASK-001) ---
255
+
256
+ /**
257
+ * Strip the plugin namespace from a dispatch name.
258
+ *
259
+ * Under plugin scope the harness namespaces every agent (`orchestrator:implementer`
260
+ * — measured in the S398 sandbox, RFC-040 §18.14); in project scope the same agent
261
+ * arrives bare (`implementer`). A guard that compares against the bare name only
262
+ * answers `false` for the namespaced form — and since hooks fail open, it disables
263
+ * itself in silence. Both forms MUST resolve to the same decision.
264
+ *
265
+ * Moved here from `pre-agent-dispatch.ts` (TD-214/TD-239 TASK-001) so every hook
266
+ * that needs identity normalization shares ONE implementation instead of
267
+ * hand-rolling its own `lastIndexOf(':')` substring logic — see TASK-002's
268
+ * consolidator test for the full list of consumers this is meant to unify.
269
+ */
270
+ export function normalizeAgentName(subagentType: string): string {
271
+ const i = subagentType.lastIndexOf(':');
272
+ return i === -1 ? subagentType : subagentType.slice(i + 1);
273
+ }
274
+
156
275
  // --- Types ---
157
276
 
158
277
  export interface WorkflowStatus {