@orchestrator-claude/definitions 3.33.0 → 3.35.0

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 (56) hide show
  1. package/README.md +32 -0
  2. package/agents/adversarial-reviewer.md +2 -2
  3. package/agents/azure-devops-engineer.md +9 -1
  4. package/agents/cicd-platform-engineer.md +477 -0
  5. package/agents/ciclo-engineer.md +267 -0
  6. package/agents/debug-sidecar.md +5 -0
  7. package/agents/doc-sidecar.md +5 -0
  8. package/agents/frontend-engineer.md +173 -0
  9. package/agents/implementer.md +39 -23
  10. package/agents/methodology-researcher.md +2 -1
  11. package/agents/operational-artifact-builder.md +2 -1
  12. package/agents/orchestrator.md +54 -72
  13. package/agents/planner.md +2 -2
  14. package/agents/presentation-engineer.md +1 -1
  15. package/agents/python-data-engineer.md +214 -0
  16. package/agents/reviewer.md +16 -8
  17. package/agents/specifier.md +1 -1
  18. package/agents/task-generator.md +1 -1
  19. package/agents/test-sidecar.md +14 -3
  20. package/dist/install/DevCheckoutDetector.d.ts +30 -13
  21. package/dist/install/DevCheckoutDetector.d.ts.map +1 -1
  22. package/dist/install/DevCheckoutDetector.js +33 -16
  23. package/dist/install/DevCheckoutDetector.js.map +1 -1
  24. package/hooks/agent-git-guard.mjs +118 -0
  25. package/hooks/agent-git-guard.ts +166 -0
  26. package/hooks/hooks.json +78 -0
  27. package/hooks/playwright-output-guard.mjs +136 -0
  28. package/hooks/playwright-output-guard.ts +130 -0
  29. package/hooks/pre-agent-dispatch.mjs +346 -0
  30. package/hooks/pre-agent-dispatch.ts +287 -0
  31. package/hooks/session-start.mjs +8 -36
  32. package/hooks/session-start.ts +15 -72
  33. package/hooks/subagent-stop.mjs +0 -18
  34. package/hooks/subagent-stop.ts +29 -13
  35. package/hooks/verification-before-completion.mjs +105 -0
  36. package/hooks/verification-before-completion.ts +97 -0
  37. package/hooks-settings-template.json +19 -4
  38. package/manifest.json +125 -29
  39. package/package.json +1 -1
  40. package/personas/INDEX.md +46 -0
  41. package/skills/artifact-generator/SKILL.md +1 -1
  42. package/skills/artifact-production/SKILL.md +28 -0
  43. package/skills/backlog-synthesis/SKILL.md +8 -3
  44. package/skills/checkpoint-protocol/SKILL.md +7 -0
  45. package/skills/ciclo-lane-dispatch/SKILL.md +158 -0
  46. package/skills/infographic-engine/SKILL.md +116 -0
  47. package/skills/orchestrator/SKILL.md +95 -7
  48. package/skills/persona-library/SKILL.md +1 -1
  49. package/skills/project-conventions/SKILL.md +53 -30
  50. package/skills/project-management-enterprise/SKILL.md +1 -1
  51. package/skills/python-data-engineering/SKILL.md +792 -0
  52. package/skills/release/SKILL.md +29 -18
  53. package/skills/release/release.sh +65 -4
  54. package/skills/storybook-validated-loop/SKILL.md +110 -0
  55. package/skills/tdd-discipline/SKILL.md +16 -0
  56. package/skills/workflow-coordination/SKILL.md +117 -16
@@ -1 +1 @@
1
- {"version":3,"file":"DevCheckoutDetector.d.ts","sourceRoot":"","sources":["../../src/install/DevCheckoutDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA4BlD,qBAAa,mBAAmB;IAClB,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,MAAM,EAAE;IAEpD;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IAkBpC;;;;OAIG;IACH,OAAO,CAAC,mCAAmC;IAiB3C,OAAO,CAAC,eAAe;IASvB;;;OAGG;IACH,OAAO,CAAC,0BAA0B;IA4BlC,OAAO,CAAC,YAAY;CAOrB"}
1
+ {"version":3,"file":"DevCheckoutDetector.d.ts","sourceRoot":"","sources":["../../src/install/DevCheckoutDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA4BlD,qBAAa,mBAAmB;IAClB,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,MAAM,EAAE;IAEpD;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IAkBpC;;;;OAIG;IACH,OAAO,CAAC,mCAAmC;IAiB3C,OAAO,CAAC,eAAe;IASvB;;;;;OAKG;IACH,OAAO,CAAC,0BAA0B;IA4BlC,OAAO,CAAC,YAAY;CAOrB"}
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * DevCheckoutDetector — read-only dual-condition heuristic (RF-002 / spec
3
- * §5.1, ADR-004) for the "inverted precedence" risk between `.claude/agents`
4
- * (project-scope) and `.claude/skills` (user-scope, per Claude Code's
5
- * documentation): once the installer lands, `~/.claude/agents` resolves from
6
- * the distributed package while `<repo>/.claude/agents` remains the authored
7
- * source — they can diverge silently.
3
+ * §5.1, ADR-004) for the "inverted precedence" risk between the ADR-023
4
+ * canonical `packages/definitions/agents` (project-scope, authored source)
5
+ * and `~/.claude/skills` (user-scope, per Claude Code's documentation): once
6
+ * the installer lands, `~/.claude/agents` resolves from the distributed
7
+ * package while the monorepo's own authored source remains separate — they
8
+ * can diverge silently.
8
9
  *
9
10
  * Detection requires BOTH conditions (reduces false-positives, risk R-6):
10
11
  * (i) walk-up from `cwd` to the nearest ancestor `package.json` whose
@@ -12,13 +13,27 @@
12
13
  * (`@orchestrator-cli/core` — confirmed via direct Read of
13
14
  * `/home/cmac/workOrch-Claude/orchestrator/package.json`, plan
14
15
  * §11 Verify-Before-Assert);
15
- * (ii) that same ancestor's `.claude/agents/*.md` contains REAL files
16
- * (never symlinks — `lstatSync(...).isSymbolicLink()`, distinguishing
17
- * authored files from the C6/TD-204 INTERIM per-file symlinks) whose
18
- * slug (basename without `.md`) collides with `manifestSlugs`.
16
+ * (ii) that same ancestor's `packages/definitions/agents/*.md` contains
17
+ * REAL files (never symlinks — `lstatSync(...).isSymbolicLink()`,
18
+ * distinguishing authored files from the C6/TD-204 INTERIM per-file
19
+ * symlinks) whose slug (basename without `.md`) collides with
20
+ * `manifestSlugs`.
21
+ *
22
+ * REPOINTED (ADR-023 §7, S401): condition (ii) used to read
23
+ * `<root>/.claude/agents/` — the `.claude/` mirror. That mirror is being
24
+ * retired (RFC-040 §18.15 — `<repo>/.claude/{agents,skills}` gets deleted as
25
+ * part of the harness graduation to an installed-plugin route), which would
26
+ * silently blind this detector (measured, S401: with `.claude/agents`
27
+ * absent, `detect()` always returned `clean-install`, and the
28
+ * `cli-install.test.ts` TASK-034 regression guard caught it via a real,
29
+ * non-mocked `install` invocation timing out instead of aborting). Condition
30
+ * (ii) now reads `<root>/packages/definitions/agents/` — the ADR-023
31
+ * canonical SoT, which is NOT deleted by the travessia and is exactly the
32
+ * tree this monorepo's own contributors actually author. Condition (i) is
33
+ * unchanged.
19
34
  *
20
35
  * Never mutates anything — `detect()` only reads `package.json` and lists
21
- * `.claude/agents/`. This module is purely read-only by design.
36
+ * `packages/definitions/agents/`. This module is purely read-only by design.
22
37
  *
23
38
  * ---
24
39
  * MEASURED WARNING TEXT (TASK-036/AC-007 gate — CLOSED, S385):
@@ -49,8 +64,8 @@ const MONOREPO_PACKAGE_NAME = '@orchestrator-cli/core';
49
64
  * real practical risk it implies (silent drift), not a hypothetical.
50
65
  */
51
66
  const DEV_CHECKOUT_WARNING_REASON = 'Dev-checkout detectado: este cwd pertence ao monorepo orchestrator e ' +
52
- '`.claude/agents/` contém arquivos reais cujos slugs colidem com o ' +
53
- 'manifest do pacote. Precedência MEDIDA empiricamente (AC-007/TASK-036, ' +
67
+ '`packages/definitions/agents/` contém arquivos reais cujos slugs colidem ' +
68
+ 'com o manifest do pacote. Precedência MEDIDA empiricamente (AC-007/TASK-036, ' +
54
69
  'gate S385, 3/3 runs determinísticos por eixo, probe isolado): agents ' +
55
70
  'resolvem por PROJECT-scope (edições locais neste repo têm efeito ' +
56
71
  'imediato numa sessão live) e skills resolvem por USER-scope ' +
@@ -66,7 +81,7 @@ export class DevCheckoutDetector {
66
81
  this.manifestSlugs = manifestSlugs;
67
82
  }
68
83
  /**
69
- * Read-only detection. Never throws on a missing `.claude/agents`
84
+ * Read-only detection. Never throws on a missing `packages/definitions/agents`
70
85
  * directory or a missing/unparseable ancestor `package.json` — those
71
86
  * cases simply resolve to `'clean-install'`.
72
87
  */
@@ -114,11 +129,13 @@ export class DevCheckoutDetector {
114
129
  }
115
130
  }
116
131
  /**
117
- * Real (non-symlink) `.claude/agents/*.md` files at `root` whose slug
118
- * (basename without `.md`) collides with `manifestSlugs`.
132
+ * Real (non-symlink) `packages/definitions/agents/*.md` files at `root`
133
+ * whose slug (basename without `.md`) collides with `manifestSlugs`.
134
+ * Repointed from `.claude/agents/` to the ADR-023 canonical SoT (§7,
135
+ * S401) — see the module JSDoc "REPOINTED" note above.
119
136
  */
120
137
  findMatchingRealAgentSlugs(root) {
121
- const agentsDir = join(root, '.claude', 'agents');
138
+ const agentsDir = join(root, 'packages', 'definitions', 'agents');
122
139
  if (!existsSync(agentsDir)) {
123
140
  return [];
124
141
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DevCheckoutDetector.js","sourceRoot":"","sources":["../../src/install/DevCheckoutDetector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DevCheckoutDetector.js","sourceRoot":"","sources":["../../src/install/DevCheckoutDetector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ import { createRequire as __createRequireShim } from 'node:module'; const require = __createRequireShim(import.meta.url);
2
+
3
+ // hooks/lib/api-client.ts
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");
13
+ mkdirSync(STATE_DIR, { recursive: true });
14
+ var API_URL = process.env.ORCHESTRATOR_API_URL || "http://localhost:3001";
15
+ var AUTH_EMAIL = process.env.ORCHESTRATOR_ADMIN_EMAIL || process.env.ORCHESTRATOR_AUTH_EMAIL || "system@orchestrator.local";
16
+ var AUTH_PASSWORD = process.env.ORCHESTRATOR_ADMIN_PASSWORD || process.env.ORCHESTRATOR_AUTH_PASSWORD || "system123";
17
+ var PROJECT_ID = process.env.ORCHESTRATOR_PROJECT_ID || "";
18
+ function log(prefix, msg) {
19
+ const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d+Z$/, "Z");
20
+ try {
21
+ const line = `[${ts}] ${prefix}: ${msg}
22
+ `;
23
+ writeFileSync(DEBUG_LOG, line, { flag: "a" });
24
+ } catch {
25
+ }
26
+ }
27
+ var LAST_COMPLETED_FILE = join(STATE_DIR, "last-completed-workflow.json");
28
+ var LAST_COMPLETED_TTL_MS = 60 * 60 * 1e3;
29
+ var INVOCATIONS_DIR = join(STATE_DIR, "invocations");
30
+ var INVOCATION_STATE_TTL_MS = 4 * 60 * 60 * 1e3;
31
+ var DISPATCH_INTENT_DIR = join(STATE_DIR, "dispatch-intent");
32
+ async function readStdin() {
33
+ const chunks = [];
34
+ for await (const chunk of process.stdin) {
35
+ chunks.push(chunk);
36
+ }
37
+ const raw = Buffer.concat(chunks).toString("utf-8").trim();
38
+ if (!raw) return {};
39
+ try {
40
+ return JSON.parse(raw);
41
+ } catch {
42
+ return {};
43
+ }
44
+ }
45
+ function getField(obj, path) {
46
+ const parts = path.split(".");
47
+ let current = obj;
48
+ for (const part of parts) {
49
+ if (current == null || typeof current !== "object") return "";
50
+ current = current[part];
51
+ }
52
+ return current != null ? String(current) : "";
53
+ }
54
+ function outputPreToolUse(opts) {
55
+ const output = {
56
+ hookSpecificOutput: {
57
+ hookEventName: "PreToolUse",
58
+ permissionDecision: opts.decision,
59
+ ...opts.reason && { permissionDecisionReason: opts.reason },
60
+ ...opts.context && { additionalContext: opts.context }
61
+ }
62
+ };
63
+ console.log(JSON.stringify(output));
64
+ }
65
+
66
+ // hooks/agent-git-guard.ts
67
+ var HOOK = "AGENT-GIT-GUARD";
68
+ var defaultDeps = {
69
+ readStdin,
70
+ output: outputPreToolUse,
71
+ log,
72
+ getEnv: (key) => process.env[key]
73
+ };
74
+ var PUSH = /\bgit\s+push(\s|$)/;
75
+ var MERGE = /\bgit\s+merge(\s|$)/;
76
+ var GH_PR_MERGE = /\bgh\s+pr\s+merge(\s|$)/;
77
+ function commandIsPushOrMerge(command) {
78
+ return PUSH.test(command) || MERGE.test(command) || GH_PR_MERGE.test(command);
79
+ }
80
+ function evaluateGitGuard(command, agentId, agentType) {
81
+ if (!agentId) return { decision: "allow" };
82
+ if (!commandIsPushOrMerge(command)) return { decision: "allow" };
83
+ const who = agentType && agentType.length > 0 ? `Sub-agent '${agentType}'` : "Sub-agent";
84
+ return {
85
+ decision: "deny",
86
+ reason: `[AGENT-GIT-GUARD] ${who} is not permitted to run git push / git merge / gh pr merge. Per RFC-022 + TD-169, push and merge are owned EXCLUSIVELY by the main orchestrator (the main conversation). Make your changes locally and return them in your report \u2014 the orchestrator reviews, then pushes/merges. (Prevents the S288 unauthorized merge-to-main breach.)`
87
+ };
88
+ }
89
+ async function mainWithDeps(deps) {
90
+ const { readStdin: readStdin2, output, log: log2, getEnv } = deps;
91
+ const stdin = await readStdin2();
92
+ const command = getField(stdin, "tool_input.command") || getField(stdin, "command") || "";
93
+ const agentId = getField(stdin, "agent_id");
94
+ const agentType = getField(stdin, "agent_type");
95
+ if (getEnv("SKIP_AGENT_GIT_GUARD") === "true") {
96
+ log2(HOOK, `BYPASS (SKIP_AGENT_GIT_GUARD): ${command.slice(0, 60)}`);
97
+ return;
98
+ }
99
+ const result = evaluateGitGuard(command, agentId, agentType);
100
+ if (result.decision === "deny") {
101
+ log2(HOOK, `DENY (agent=${agentType || "unknown"}): ${command.slice(0, 80)}`);
102
+ output({ decision: "deny", reason: result.reason });
103
+ return;
104
+ }
105
+ log2(
106
+ HOOK,
107
+ `ALLOW (agent=${agentId ? agentType || "sub-agent" : "main"}): ${command.slice(0, 60)}`
108
+ );
109
+ }
110
+ async function main() {
111
+ await mainWithDeps(defaultDeps);
112
+ }
113
+ main().catch(() => process.exit(0));
114
+ export {
115
+ commandIsPushOrMerge,
116
+ evaluateGitGuard,
117
+ mainWithDeps
118
+ };
@@ -0,0 +1,166 @@
1
+ /**
2
+ * agent-git-guard.ts — PreToolUse[Bash] hook (TD-169 enforcement)
3
+ *
4
+ * BLOCKS `git push`, `git merge`, and `gh pr merge` when the command is run by a
5
+ * SUB-AGENT, while ALLOWING the main orchestrator (main conversation) to run them.
6
+ *
7
+ * Mechanism: Claude Code injects `agent_id` into PreToolUse stdin ONLY when the
8
+ * hook fires inside a sub-agent call (see hook-reference: "Present only when the
9
+ * hook fires inside a subagent call"). workflow-guard.ts uses the same signal for
10
+ * Write/Edit (the sub-agent branch of decideWorkflowGuardAction). This hook extends
11
+ * it to the git escape-to-remote path.
12
+ *
13
+ * Why this exists: S288 governance breach — an `implementer` sub-agent autonomously
14
+ * committed + pushed + `gh pr merge`'d an unauthorized FK-drop to main. Prose
15
+ * commit-policy in dispatch prompts is unenforced (agents hold Bash + gh). This hook
16
+ * is the enforcement layer (cf. workflow-guard model; S288-handoff §TD-169).
17
+ *
18
+ * Scope: push / merge ONLY — NOT commit. A local commit by a sub-agent is recoverable
19
+ * and is sometimes legitimate (orchestrator Commit Policy option b). Push/merge to a
20
+ * remote is the unrecoverable breach vector, so that is what we deny.
21
+ *
22
+ * RFC-040 TD-204 §⑤-A (S366) — Classe-A asset-safety classification:
23
+ * this gate is classified Classe-A (same family as workflow-guard.ts's
24
+ * `.orchestrator`-registration and workflow-active checks — asset-safety
25
+ * gates that must remain intact everywhere, never silently no-op). UNLIKE
26
+ * workflow-guard.ts, this gate's decision (evaluateGitGuard) is a pure
27
+ * function of (command, agentId, agentType) ONLY — it never inspects any
28
+ * file_path or cwd. A sub-agent attempting `git push`/`git merge`/`gh pr
29
+ * merge` is denied identically no matter which project's working tree the
30
+ * Bash command runs against. This makes it **globally cwd-safe already**:
31
+ * no TD-204 ⑤-A remediation (project-root resolution / `.unmanaged`
32
+ * sentinel / unregistered-path branching) is needed here — there is no
33
+ * path-dependent branch to make cwd-scoped-safe in the first place. See
34
+ * tests/unit/hooks/agent-git-guard-path-invariance.test.ts for the
35
+ * property-style proof.
36
+ *
37
+ * Decision:
38
+ * - agent_id absent (main orchestrator) → silent pass-through (allow)
39
+ * - agent_id present + push/merge/gh-pr-merge → DENY
40
+ * - agent_id present + commit/read-only/other → silent pass-through (allow)
41
+ * - SKIP_AGENT_GIT_GUARD=true → allow (escape hatch, logged)
42
+ * - parse error / empty stdin → fail-open (allow)
43
+ */
44
+
45
+ import { log, readStdin, getField, outputPreToolUse } from './lib/api-client.js';
46
+
47
+ const HOOK = 'AGENT-GIT-GUARD';
48
+
49
+ // ─────────────────────────────────────────────────────────────
50
+ // Dependency injection interface (enables testing without IO)
51
+ // ─────────────────────────────────────────────────────────────
52
+
53
+ export interface HookDeps {
54
+ readStdin: () => Promise<Record<string, unknown>>;
55
+ output: (opts: { decision: 'allow' | 'deny'; reason?: string; context?: string }) => void;
56
+ log: (prefix: string, msg: string) => void;
57
+ getEnv: (key: string) => string | undefined;
58
+ }
59
+
60
+ const defaultDeps: HookDeps = {
61
+ readStdin,
62
+ output: outputPreToolUse,
63
+ log,
64
+ getEnv: (key) => process.env[key],
65
+ };
66
+
67
+ // ─────────────────────────────────────────────────────────────
68
+ // Pure helpers (exported for testing)
69
+ // ─────────────────────────────────────────────────────────────
70
+
71
+ // `(\s|$)` after the verb avoids matching plumbing like `git merge-base`.
72
+ const PUSH = /\bgit\s+push(\s|$)/;
73
+ const MERGE = /\bgit\s+merge(\s|$)/;
74
+ const GH_PR_MERGE = /\bgh\s+pr\s+merge(\s|$)/;
75
+
76
+ /**
77
+ * True when the bash command performs a push or merge (the escape-to-remote
78
+ * operations owned exclusively by the main orchestrator). Excludes `git merge-base`
79
+ * (read-only plumbing), `git commit`, and read-only git/gh commands.
80
+ */
81
+ export function commandIsPushOrMerge(command: string): boolean {
82
+ return PUSH.test(command) || MERGE.test(command) || GH_PR_MERGE.test(command);
83
+ }
84
+
85
+ export interface GuardResult {
86
+ decision: 'allow' | 'deny';
87
+ reason?: string;
88
+ }
89
+
90
+ /**
91
+ * Pure decision: deny only when a sub-agent (agentId present) attempts a
92
+ * push/merge. Empty agentId == main orchestrator == always allowed.
93
+ *
94
+ * Path-independent by construction (RFC-040 TD-204 §⑤-A, Classe-A): the
95
+ * signature takes no file_path/cwd input, so the decision is provably the
96
+ * same for every project's working tree — globally cwd-safe without any
97
+ * project-root resolution.
98
+ */
99
+ export function evaluateGitGuard(
100
+ command: string,
101
+ agentId: string,
102
+ agentType?: string
103
+ ): GuardResult {
104
+ if (!agentId) return { decision: 'allow' }; // main orchestrator owns git
105
+ if (!commandIsPushOrMerge(command)) return { decision: 'allow' }; // commit/read-only fine
106
+
107
+ const who = agentType && agentType.length > 0 ? `Sub-agent '${agentType}'` : 'Sub-agent';
108
+ return {
109
+ decision: 'deny',
110
+ reason:
111
+ `[AGENT-GIT-GUARD] ${who} is not permitted to run git push / git merge / gh pr merge. ` +
112
+ `Per RFC-022 + TD-169, push and merge are owned EXCLUSIVELY by the main orchestrator ` +
113
+ `(the main conversation). Make your changes locally and return them in your report — ` +
114
+ `the orchestrator reviews, then pushes/merges. (Prevents the S288 unauthorized merge-to-main breach.)`,
115
+ };
116
+ }
117
+
118
+ // ─────────────────────────────────────────────────────────────
119
+ // Core logic (exported for testing)
120
+ // ─────────────────────────────────────────────────────────────
121
+
122
+ export async function mainWithDeps(deps: HookDeps): Promise<void> {
123
+ const { readStdin, output, log, getEnv } = deps;
124
+
125
+ const stdin = await readStdin();
126
+
127
+ const command =
128
+ (getField(stdin, 'tool_input.command') as string | undefined) ||
129
+ (getField(stdin, 'command') as string | undefined) ||
130
+ '';
131
+
132
+ const agentId = getField(stdin, 'agent_id');
133
+ const agentType = getField(stdin, 'agent_type');
134
+
135
+ // Escape hatch (parity with workflow-guard SKIP_*). Process-env only — a
136
+ // sub-agent's transient shell env does not persist into the hook process.
137
+ if (getEnv('SKIP_AGENT_GIT_GUARD') === 'true') {
138
+ log(HOOK, `BYPASS (SKIP_AGENT_GIT_GUARD): ${command.slice(0, 60)}`);
139
+ return; // silent pass-through
140
+ }
141
+
142
+ const result = evaluateGitGuard(command, agentId, agentType);
143
+
144
+ if (result.decision === 'deny') {
145
+ log(HOOK, `DENY (agent=${agentType || 'unknown'}): ${command.slice(0, 80)}`);
146
+ output({ decision: 'deny', reason: result.reason });
147
+ return;
148
+ }
149
+
150
+ // Allow path is a silent pass-through so we never clobber the context that the
151
+ // sibling Bash hook (verification-before-completion) injects.
152
+ log(
153
+ HOOK,
154
+ `ALLOW (agent=${agentId ? agentType || 'sub-agent' : 'main'}): ${command.slice(0, 60)}`
155
+ );
156
+ }
157
+
158
+ // ─────────────────────────────────────────────────────────────
159
+ // Entry point (production use)
160
+ // ─────────────────────────────────────────────────────────────
161
+
162
+ async function main(): Promise<void> {
163
+ await mainWithDeps(defaultDeps);
164
+ }
165
+
166
+ main().catch(() => process.exit(0));
@@ -0,0 +1,78 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "startup|resume",
6
+ "hooks": [
7
+ { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start.mjs\"", "timeout": 10000 },
8
+ { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/sprint-registry.mjs\"", "timeout": 5000 }
9
+ ]
10
+ }
11
+ ],
12
+ "UserPromptSubmit": [
13
+ {
14
+ "matcher": "",
15
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/user-prompt.mjs\"", "timeout": 10000 }]
16
+ }
17
+ ],
18
+ "PreToolUse": [
19
+ {
20
+ "matcher": "mcp__(plugin_orchestrator_)?orchestrator-tools__advancePhase",
21
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gate-guardian.mjs\"", "timeout": 15000 }]
22
+ },
23
+ {
24
+ "matcher": "Write|Edit",
25
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/workflow-guard.mjs\"", "timeout": 10000 }]
26
+ },
27
+ {
28
+ "matcher": "Bash",
29
+ "hooks": [
30
+ { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/verification-before-completion.mjs\"", "timeout": 5000 },
31
+ { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/agent-git-guard.mjs\"", "timeout": 5000 }
32
+ ]
33
+ },
34
+ {
35
+ "matcher": "Agent",
36
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/pre-agent-dispatch.mjs\"", "timeout": 5000 }]
37
+ },
38
+ {
39
+ "matcher": "mcp__plugin_playwright_playwright__browser_take_screenshot|mcp__plugin_playwright_playwright__browser_pdf_save",
40
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/playwright-output-guard.mjs\"", "timeout": 5000 }]
41
+ }
42
+ ],
43
+ "SubagentStart": [
44
+ {
45
+ "matcher": "(orchestrator:)?(implementer|specifier|planner|task-generator|reviewer|researcher)",
46
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/subagent-start.mjs\"", "timeout": 10000 }]
47
+ }
48
+ ],
49
+ "SubagentStop": [
50
+ {
51
+ "matcher": "(orchestrator:)?(implementer|specifier|planner|task-generator|reviewer|researcher)",
52
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/subagent-stop.mjs\"", "timeout": 30000 }]
53
+ }
54
+ ],
55
+ "Stop": [
56
+ {
57
+ "matcher": "",
58
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/dangling-guard.mjs\"", "timeout": 15000 }]
59
+ }
60
+ ],
61
+ "PostToolUse": [
62
+ {
63
+ "matcher": "",
64
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/mailbox-listener.mjs\"", "timeout": 5000 }]
65
+ },
66
+ {
67
+ "matcher": "mcp__(plugin_orchestrator_)?orchestrator-tools__advancePhase",
68
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/post-implement.mjs\"", "timeout": 15000 }]
69
+ }
70
+ ],
71
+ "PostCompact": [
72
+ {
73
+ "matcher": "",
74
+ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/post-compact.mjs\"", "timeout": 5000 }]
75
+ }
76
+ ]
77
+ }
78
+ }
@@ -0,0 +1,136 @@
1
+ import { createRequire as __createRequireShim } from 'node:module'; const require = __createRequireShim(import.meta.url);
2
+
3
+ // hooks/playwright-output-guard.ts
4
+ import { dirname as dirname3, isAbsolute, normalize, resolve } from "node:path";
5
+
6
+ // hooks/lib/api-client.ts
7
+ import { readFileSync, writeFileSync, mkdirSync, statSync, unlinkSync, readdirSync } from "node:fs";
8
+ import { join as join2, dirname as dirname2 } from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+
11
+ // ../project-root-resolver/dist/index.js
12
+ import { existsSync } from "node:fs";
13
+ import { dirname, join } from "node:path";
14
+ function resolveProjectRoot(cwd, sentinel = ".orchestrator") {
15
+ let currentDir = cwd;
16
+ for (; ; ) {
17
+ if (existsSync(join(currentDir, sentinel))) {
18
+ return currentDir;
19
+ }
20
+ const parentDir = dirname(currentDir);
21
+ if (parentDir === currentDir) {
22
+ return null;
23
+ }
24
+ currentDir = parentDir;
25
+ }
26
+ }
27
+
28
+ // hooks/lib/api-client.ts
29
+ var __filename = fileURLToPath(import.meta.url);
30
+ var __dirname = dirname2(__filename);
31
+ var PROJECT_ROOT = join2(__dirname, "..", "..", "..");
32
+ var STATE_DIR = join2(PROJECT_ROOT, ".orchestrator", ".state");
33
+ var JWT_CACHE = join2(STATE_DIR, "jwt-token");
34
+ var DEBUG_LOG = join2(STATE_DIR, "hook-debug.log");
35
+ mkdirSync(STATE_DIR, { recursive: true });
36
+ var API_URL = process.env.ORCHESTRATOR_API_URL || "http://localhost:3001";
37
+ var AUTH_EMAIL = process.env.ORCHESTRATOR_ADMIN_EMAIL || process.env.ORCHESTRATOR_AUTH_EMAIL || "system@orchestrator.local";
38
+ var AUTH_PASSWORD = process.env.ORCHESTRATOR_ADMIN_PASSWORD || process.env.ORCHESTRATOR_AUTH_PASSWORD || "system123";
39
+ var PROJECT_ID = process.env.ORCHESTRATOR_PROJECT_ID || "";
40
+ function resolveHookProjectRoot(cwd) {
41
+ return resolveProjectRoot(cwd);
42
+ }
43
+ function log(prefix, msg) {
44
+ const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d+Z$/, "Z");
45
+ try {
46
+ const line = `[${ts}] ${prefix}: ${msg}
47
+ `;
48
+ writeFileSync(DEBUG_LOG, line, { flag: "a" });
49
+ } catch {
50
+ }
51
+ }
52
+ var LAST_COMPLETED_FILE = join2(STATE_DIR, "last-completed-workflow.json");
53
+ var LAST_COMPLETED_TTL_MS = 60 * 60 * 1e3;
54
+ var INVOCATIONS_DIR = join2(STATE_DIR, "invocations");
55
+ var INVOCATION_STATE_TTL_MS = 4 * 60 * 60 * 1e3;
56
+ var DISPATCH_INTENT_DIR = join2(STATE_DIR, "dispatch-intent");
57
+ async function readStdin() {
58
+ const chunks = [];
59
+ for await (const chunk of process.stdin) {
60
+ chunks.push(chunk);
61
+ }
62
+ const raw = Buffer.concat(chunks).toString("utf-8").trim();
63
+ if (!raw) return {};
64
+ try {
65
+ return JSON.parse(raw);
66
+ } catch {
67
+ return {};
68
+ }
69
+ }
70
+ function getField(obj, path) {
71
+ const parts = path.split(".");
72
+ let current = obj;
73
+ for (const part of parts) {
74
+ if (current == null || typeof current !== "object") return "";
75
+ current = current[part];
76
+ }
77
+ return current != null ? String(current) : "";
78
+ }
79
+ function outputPreToolUse(opts) {
80
+ const output = {
81
+ hookSpecificOutput: {
82
+ hookEventName: "PreToolUse",
83
+ permissionDecision: opts.decision,
84
+ ...opts.reason && { permissionDecisionReason: opts.reason },
85
+ ...opts.context && { additionalContext: opts.context }
86
+ }
87
+ };
88
+ console.log(JSON.stringify(output));
89
+ }
90
+
91
+ // hooks/playwright-output-guard.ts
92
+ var HOOK = "PLAYWRIGHT-OUTPUT-GUARD";
93
+ var PROJECT_ROOT2 = process.env.CLAUDE_PROJECT_DIR ?? resolveHookProjectRoot(process.cwd()) ?? process.cwd();
94
+ var GUIDANCE = 'Playwright Output Guard: screenshots n\xE3o podem cair na raiz do repo (auto-checkpoint os varre \u2014 recorr\xEAncia S266-S268). Use `filename: ".playwright-mcp/<nome>.png"` (descart\xE1vel, gitignored), `filename: ".cobaia-evidence/<sess\xE3o>/<nome>.png"` (evid\xEAncia a versionar), ou omita `filename` (default j\xE1 vai para .playwright-mcp/).';
95
+ function evaluateFilename(filename) {
96
+ if (!filename) return { decision: "allow" };
97
+ const resolved = isAbsolute(filename) ? normalize(filename) : resolve(PROJECT_ROOT2, filename);
98
+ const dir = dirname3(resolved);
99
+ if (dir === PROJECT_ROOT2) {
100
+ return { decision: "deny", reason: GUIDANCE };
101
+ }
102
+ if (!resolved.startsWith(PROJECT_ROOT2 + "/") && !isAbsolute(filename)) {
103
+ return { decision: "deny", reason: GUIDANCE };
104
+ }
105
+ return { decision: "allow" };
106
+ }
107
+ var defaultDeps = {
108
+ readStdin,
109
+ output: outputPreToolUse,
110
+ log
111
+ };
112
+ async function mainWithDeps(deps) {
113
+ const stdin = await deps.readStdin();
114
+ const filename = getField(stdin, "tool_input.filename");
115
+ const result = evaluateFilename(filename || void 0);
116
+ deps.log(HOOK, `filename=${filename || "(none)"} decision=${result.decision}`);
117
+ if (result.decision === "deny") {
118
+ deps.output({ decision: "deny", reason: result.reason });
119
+ return;
120
+ }
121
+ deps.output({
122
+ decision: "allow",
123
+ ...filename ? {} : {
124
+ context: "[PLAYWRIGHT-OUTPUT-GUARD] sem filename: output em .playwright-mcp/ (gitignored)."
125
+ }
126
+ });
127
+ }
128
+ async function main() {
129
+ await mainWithDeps(defaultDeps);
130
+ }
131
+ main().catch(() => process.exit(0));
132
+ export {
133
+ PROJECT_ROOT2 as PROJECT_ROOT,
134
+ evaluateFilename,
135
+ mainWithDeps
136
+ };