@dezycro-ai/agent-plugin 2.1.2 → 2.3.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 (53) hide show
  1. package/README.md +14 -98
  2. package/dist/cli/dezycro.js +54 -0
  3. package/dist/cli/install.js +7 -0
  4. package/dist/dezycro-config.d.ts +52 -0
  5. package/dist/dezycro-config.js +167 -0
  6. package/dist/gateway/compact-cli.js +8 -0
  7. package/dist/gateway/proxy.js +35 -0
  8. package/dist/hooks/lib/router.js +14 -830
  9. package/dist/schemas/anthropic.d.ts +119 -0
  10. package/dist/schemas/anthropic.js +43 -0
  11. package/dist/schemas/dezycro.d.ts +19 -0
  12. package/dist/schemas/dezycro.js +22 -0
  13. package/dist/schemas/gateway.d.ts +40 -0
  14. package/dist/schemas/gateway.js +30 -0
  15. package/dist/schemas/gating.d.ts +32 -0
  16. package/dist/schemas/gating.js +15 -0
  17. package/dist/schemas/index.d.ts +14 -0
  18. package/dist/schemas/index.js +29 -0
  19. package/package.json +21 -13
  20. package/skills/verify/SKILL.md +17 -15
  21. package/LICENSE +0 -18
  22. package/bin/resolve-auth.js +0 -112
  23. package/dist/hooks/lib/authoring.d.ts +0 -118
  24. package/dist/hooks/lib/authoring.js +0 -277
  25. package/dist/hooks/lib/command-bus.d.ts +0 -66
  26. package/dist/hooks/lib/command-bus.js +0 -357
  27. package/dist/hooks/lib/config.d.ts +0 -28
  28. package/dist/hooks/lib/config.js +0 -175
  29. package/dist/hooks/lib/controller-match.d.ts +0 -16
  30. package/dist/hooks/lib/controller-match.js +0 -96
  31. package/dist/hooks/lib/coverage.d.ts +0 -17
  32. package/dist/hooks/lib/coverage.js +0 -66
  33. package/dist/hooks/lib/hashing.d.ts +0 -8
  34. package/dist/hooks/lib/hashing.js +0 -49
  35. package/dist/hooks/lib/logging.d.ts +0 -13
  36. package/dist/hooks/lib/logging.js +0 -72
  37. package/dist/hooks/lib/publish-spec.d.ts +0 -17
  38. package/dist/hooks/lib/publish-spec.js +0 -64
  39. package/dist/hooks/lib/quality-gate.d.ts +0 -67
  40. package/dist/hooks/lib/quality-gate.js +0 -187
  41. package/dist/hooks/lib/router.d.ts +0 -32
  42. package/dist/hooks/lib/state.d.ts +0 -34
  43. package/dist/hooks/lib/state.js +0 -245
  44. package/dist/hooks/lib/undo.d.ts +0 -11
  45. package/dist/hooks/lib/undo.js +0 -71
  46. package/dist/hooks/lib/verify.d.ts +0 -28
  47. package/dist/hooks/lib/verify.js +0 -94
  48. package/dist/hooks/lib/workbook.d.ts +0 -21
  49. package/dist/hooks/lib/workbook.js +0 -77
  50. package/dist/hooks/types.d.ts +0 -293
  51. package/dist/hooks/types.js +0 -14
  52. package/install.js +0 -84
  53. package/setup.js +0 -53
@@ -0,0 +1,119 @@
1
+ /**
2
+ * schemas/anthropic.ts — Anthropic Messages API wire shapes + protocol constants.
3
+ *
4
+ * Minimal and permissive: we model only the fields the gateway actually reads,
5
+ * each with a generic `[k: string]: unknown` tail so unknown fields survive a
6
+ * round-trip untouched.
7
+ *
8
+ * The protocol's string literals (event types, block types, delta types, stop
9
+ * reasons) are named constants below — code compares against `StreamEventType.*`
10
+ * etc. rather than bare strings, and the event/block interfaces pin their
11
+ * discriminant to the same constant so the two can't drift. The streaming events
12
+ * are a discriminated union on `type`, so `switch (event.type)` narrows the
13
+ * payload with no casts.
14
+ */
15
+ export declare const StreamEventType: {
16
+ readonly MessageStart: "message_start";
17
+ readonly ContentBlockStart: "content_block_start";
18
+ readonly ContentBlockDelta: "content_block_delta";
19
+ readonly ContentBlockStop: "content_block_stop";
20
+ readonly MessageDelta: "message_delta";
21
+ readonly MessageStop: "message_stop";
22
+ };
23
+ export declare const MessageRole: {
24
+ readonly User: "user";
25
+ readonly Assistant: "assistant";
26
+ readonly System: "system";
27
+ };
28
+ export declare const ContentBlockType: {
29
+ readonly Text: "text";
30
+ readonly ToolUse: "tool_use";
31
+ };
32
+ export declare const DeltaType: {
33
+ readonly Text: "text_delta";
34
+ readonly InputJson: "input_json_delta";
35
+ };
36
+ export declare const StopReason: {
37
+ readonly ToolUse: "tool_use";
38
+ readonly EndTurn: "end_turn";
39
+ };
40
+ export interface AnthropicTextBlock {
41
+ type: typeof ContentBlockType.Text;
42
+ text: string;
43
+ cache_control?: unknown;
44
+ }
45
+ export interface AnthropicToolUseBlock {
46
+ type: typeof ContentBlockType.ToolUse;
47
+ id?: string;
48
+ name?: string;
49
+ input?: Record<string, unknown>;
50
+ }
51
+ /** A content block we don't specifically model — forwarded as-is. */
52
+ export interface AnthropicUnknownBlock {
53
+ type: string;
54
+ [k: string]: unknown;
55
+ }
56
+ export type AnthropicContentBlock = AnthropicTextBlock | AnthropicToolUseBlock | AnthropicUnknownBlock;
57
+ export interface AnthropicMessage {
58
+ role: string;
59
+ content: string | AnthropicContentBlock[];
60
+ }
61
+ export interface AnthropicSystemBlock {
62
+ type: string;
63
+ text?: string;
64
+ cache_control?: unknown;
65
+ [k: string]: unknown;
66
+ }
67
+ export interface AnthropicBody {
68
+ model?: string;
69
+ stream?: boolean;
70
+ system?: string | AnthropicSystemBlock[];
71
+ tools?: unknown[];
72
+ messages?: AnthropicMessage[];
73
+ input?: unknown;
74
+ stop_reason?: string | null;
75
+ content?: AnthropicContentBlock[];
76
+ [k: string]: unknown;
77
+ }
78
+ export interface TextDelta {
79
+ type: typeof DeltaType.Text;
80
+ text: string;
81
+ }
82
+ export interface InputJsonDelta {
83
+ type: typeof DeltaType.InputJson;
84
+ partial_json: string;
85
+ }
86
+ export type BlockDelta = TextDelta | InputJsonDelta | {
87
+ type: string;
88
+ [k: string]: unknown;
89
+ };
90
+ export interface MessageStartEvent {
91
+ type: typeof StreamEventType.MessageStart;
92
+ message?: unknown;
93
+ }
94
+ export interface ContentBlockStartEvent {
95
+ type: typeof StreamEventType.ContentBlockStart;
96
+ index: number;
97
+ content_block: AnthropicContentBlock;
98
+ }
99
+ export interface ContentBlockDeltaEvent {
100
+ type: typeof StreamEventType.ContentBlockDelta;
101
+ index: number;
102
+ delta: BlockDelta;
103
+ }
104
+ export interface ContentBlockStopEvent {
105
+ type: typeof StreamEventType.ContentBlockStop;
106
+ index: number;
107
+ }
108
+ export interface MessageDeltaEvent {
109
+ type: typeof StreamEventType.MessageDelta;
110
+ delta: {
111
+ stop_reason?: string | null;
112
+ [k: string]: unknown;
113
+ };
114
+ [k: string]: unknown;
115
+ }
116
+ export interface MessageStopEvent {
117
+ type: typeof StreamEventType.MessageStop;
118
+ }
119
+ export type StreamEvent = MessageStartEvent | ContentBlockStartEvent | ContentBlockDeltaEvent | ContentBlockStopEvent | MessageDeltaEvent | MessageStopEvent;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * schemas/anthropic.ts — Anthropic Messages API wire shapes + protocol constants.
4
+ *
5
+ * Minimal and permissive: we model only the fields the gateway actually reads,
6
+ * each with a generic `[k: string]: unknown` tail so unknown fields survive a
7
+ * round-trip untouched.
8
+ *
9
+ * The protocol's string literals (event types, block types, delta types, stop
10
+ * reasons) are named constants below — code compares against `StreamEventType.*`
11
+ * etc. rather than bare strings, and the event/block interfaces pin their
12
+ * discriminant to the same constant so the two can't drift. The streaming events
13
+ * are a discriminated union on `type`, so `switch (event.type)` narrows the
14
+ * payload with no casts.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.StopReason = exports.DeltaType = exports.ContentBlockType = exports.MessageRole = exports.StreamEventType = void 0;
18
+ /* ── protocol constants (the wire's magic strings, named) ──────────────────── */
19
+ exports.StreamEventType = {
20
+ MessageStart: 'message_start',
21
+ ContentBlockStart: 'content_block_start',
22
+ ContentBlockDelta: 'content_block_delta',
23
+ ContentBlockStop: 'content_block_stop',
24
+ MessageDelta: 'message_delta',
25
+ MessageStop: 'message_stop',
26
+ };
27
+ exports.MessageRole = {
28
+ User: 'user',
29
+ Assistant: 'assistant',
30
+ System: 'system',
31
+ };
32
+ exports.ContentBlockType = {
33
+ Text: 'text',
34
+ ToolUse: 'tool_use',
35
+ };
36
+ exports.DeltaType = {
37
+ Text: 'text_delta',
38
+ InputJson: 'input_json_delta',
39
+ };
40
+ exports.StopReason = {
41
+ ToolUse: 'tool_use',
42
+ EndTurn: 'end_turn',
43
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * schemas/dezycro.ts — Dezycro domain constants the gateway reasons about.
3
+ *
4
+ * These name the concrete tool/field/status values the default gating policy
5
+ * matches against, so the policy reads as data, not magic strings.
6
+ */
7
+ /** Dezycro MCP tool name fragments matched by gating rules. */
8
+ export declare const ToolName: {
9
+ readonly UpdateTask: "update_task";
10
+ };
11
+ /** Tool input field names referenced by gating rules. */
12
+ export declare const ToolInputField: {
13
+ readonly Status: "status";
14
+ };
15
+ /** Workbook task statuses (the terminal ones the gate guards). */
16
+ export declare const TaskStatus: {
17
+ readonly Done: "DONE";
18
+ readonly Pushed: "PUSHED";
19
+ };
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ /**
3
+ * schemas/dezycro.ts — Dezycro domain constants the gateway reasons about.
4
+ *
5
+ * These name the concrete tool/field/status values the default gating policy
6
+ * matches against, so the policy reads as data, not magic strings.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.TaskStatus = exports.ToolInputField = exports.ToolName = void 0;
10
+ /** Dezycro MCP tool name fragments matched by gating rules. */
11
+ exports.ToolName = {
12
+ UpdateTask: 'update_task',
13
+ };
14
+ /** Tool input field names referenced by gating rules. */
15
+ exports.ToolInputField = {
16
+ Status: 'status',
17
+ };
18
+ /** Workbook task statuses (the terminal ones the gate guards). */
19
+ exports.TaskStatus = {
20
+ Done: 'DONE',
21
+ Pushed: 'PUSHED',
22
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * schemas/gateway.ts — gateway runtime types.
3
+ *
4
+ * The gateway is a local interception proxy between a coding agent and its model
5
+ * provider: it delivers skills/slash-commands and enforcement regardless of
6
+ * native support, via request injection (cache-safe) and response tool gating.
7
+ */
8
+ /** Model providers the gateway can adapt (value + type share the name). */
9
+ export declare const Provider: {
10
+ readonly Anthropic: "anthropic";
11
+ readonly OpenAI: "openai";
12
+ };
13
+ export type Provider = (typeof Provider)[keyof typeof Provider];
14
+ /** Agents the launcher knows how to point at the gateway. */
15
+ export declare const Agent: {
16
+ readonly Claude: "claude";
17
+ readonly Codex: "codex";
18
+ };
19
+ /** Local control-plane paths (never forwarded upstream). Shared by proxy + launcher. */
20
+ export declare const ControlPath: {
21
+ readonly Health: "/__dz/health";
22
+ readonly Stop: "/__dz/stop";
23
+ };
24
+ /** Response content-types the gate special-cases. */
25
+ export declare const ContentType: {
26
+ readonly EventStream: "text/event-stream";
27
+ readonly Json: "application/json";
28
+ };
29
+ /** trigger (e.g. "/dezycro:verify") -> instruction text injected on match. */
30
+ export interface SkillRegistry {
31
+ [trigger: string]: string;
32
+ }
33
+ export interface GatewayConfig {
34
+ port: number;
35
+ inject: boolean;
36
+ gate: boolean;
37
+ capture: boolean;
38
+ /** path to the launch repo's .dezycro/companion-state.json for state-aware gating. */
39
+ stateFile?: string | null;
40
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ /**
3
+ * schemas/gateway.ts — gateway runtime types.
4
+ *
5
+ * The gateway is a local interception proxy between a coding agent and its model
6
+ * provider: it delivers skills/slash-commands and enforcement regardless of
7
+ * native support, via request injection (cache-safe) and response tool gating.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ContentType = exports.ControlPath = exports.Agent = exports.Provider = void 0;
11
+ /** Model providers the gateway can adapt (value + type share the name). */
12
+ exports.Provider = {
13
+ Anthropic: 'anthropic',
14
+ OpenAI: 'openai',
15
+ };
16
+ /** Agents the launcher knows how to point at the gateway. */
17
+ exports.Agent = {
18
+ Claude: 'claude',
19
+ Codex: 'codex',
20
+ };
21
+ /** Local control-plane paths (never forwarded upstream). Shared by proxy + launcher. */
22
+ exports.ControlPath = {
23
+ Health: '/__dz/health',
24
+ Stop: '/__dz/stop',
25
+ };
26
+ /** Response content-types the gate special-cases. */
27
+ exports.ContentType = {
28
+ EventStream: 'text/event-stream',
29
+ Json: 'application/json',
30
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * schemas/gating.ts — the tool-call gating policy model.
3
+ *
4
+ * A policy is a list of rules. A rule matches a tool_use by name (substring) and
5
+ * optionally by an input field value, then requires a set of workflow-state
6
+ * predicates to ALL hold; if any fails, the call is blocked with a reason.
7
+ */
8
+ import type { CompanionState } from '../hooks/types';
9
+ /** Named, live-state predicates a rule can require (see STATE_PREDICATES). */
10
+ export declare const PredicateName: {
11
+ readonly SpecPublished: "specPublished";
12
+ readonly VerifiedRecently: "verifiedRecently";
13
+ };
14
+ export type StatePredicateName = (typeof PredicateName)[keyof typeof PredicateName];
15
+ export type StatePredicate = (s: CompanionState | null | undefined) => boolean;
16
+ export interface GateRule {
17
+ /** Match a tool_use whose name contains this substring. */
18
+ nameIncludes: string;
19
+ /** Optionally also require an input field to be one of these values. */
20
+ inputField?: string;
21
+ inputValues?: Array<string | number>;
22
+ /** State predicates that must ALL hold to ALLOW; otherwise block. */
23
+ requireAll?: StatePredicateName[];
24
+ reason?: string;
25
+ }
26
+ export interface GatePolicy {
27
+ rules: GateRule[];
28
+ }
29
+ export interface GateDecision {
30
+ block: boolean;
31
+ reason: string | null;
32
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ /**
3
+ * schemas/gating.ts — the tool-call gating policy model.
4
+ *
5
+ * A policy is a list of rules. A rule matches a tool_use by name (substring) and
6
+ * optionally by an input field value, then requires a set of workflow-state
7
+ * predicates to ALL hold; if any fails, the call is blocked with a reason.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.PredicateName = void 0;
11
+ /** Named, live-state predicates a rule can require (see STATE_PREDICATES). */
12
+ exports.PredicateName = {
13
+ SpecPublished: 'specPublished',
14
+ VerifiedRecently: 'verifiedRecently',
15
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * schemas/ — formalized models for the gateway, in one place.
3
+ *
4
+ * anthropic.ts — provider wire shapes (request body, content blocks, SSE events)
5
+ * gating.ts — tool-call gating policy/rules/decisions
6
+ * gateway.ts — gateway runtime config + provider/skill types
7
+ *
8
+ * Import from '../schemas' (this barrel) rather than the individual files.
9
+ */
10
+ export * from './anthropic';
11
+ export * from './dezycro';
12
+ export * from './gating';
13
+ export * from './gateway';
14
+ export type { CompanionState } from '../hooks/types';
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /**
3
+ * schemas/ — formalized models for the gateway, in one place.
4
+ *
5
+ * anthropic.ts — provider wire shapes (request body, content blocks, SSE events)
6
+ * gating.ts — tool-call gating policy/rules/decisions
7
+ * gateway.ts — gateway runtime config + provider/skill types
8
+ *
9
+ * Import from '../schemas' (this barrel) rather than the individual files.
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
23
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ __exportStar(require("./anthropic"), exports);
27
+ __exportStar(require("./dezycro"), exports);
28
+ __exportStar(require("./gating"), exports);
29
+ __exportStar(require("./gateway"), exports);
package/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "@dezycro-ai/agent-plugin",
3
- "version": "2.1.2",
3
+ "version": "2.3.0",
4
4
  "description": "Official Dezycro plugin for AI coding agents (Claude Code today, more to come) — reverse-engineer your codebase into features, PRDs, TRDs, and live verification.",
5
5
  "bin": {
6
- "dezycro-setup": "./setup.js",
7
- "dezycro-resolve-auth": "./bin/resolve-auth.js"
6
+ "dezycro": "./dist/cli/dezycro.js"
8
7
  },
9
8
  "keywords": [
10
9
  "dezycro",
@@ -29,22 +28,31 @@
29
28
  "hooks/**/*",
30
29
  "prompts/**/*",
31
30
  "skills/**/*",
32
- "bin/**/*",
33
- "install.js",
34
- "setup.js",
35
31
  "README.md",
36
- "PERSONAS.md",
37
- "LICENSE"
32
+ "PERSONAS.md"
38
33
  ],
39
34
  "scripts": {
40
35
  "build": "tsc",
41
- "prepare": "[ -d src ] && tsc || true",
42
- "prepublishOnly": "npm run build",
43
- "postinstall": "node install.js",
44
- "setup": "node setup.js"
36
+ "bundle": "node scripts/bundle.mjs",
37
+ "lint": "eslint src/gateway src/schemas src/cli",
38
+ "lint:fix": "eslint src/gateway src/schemas src/cli --fix",
39
+ "format": "prettier --write \"src/{gateway,schemas,cli}/**/*.ts\"",
40
+ "format:check": "prettier --check \"src/{gateway,schemas,cli}/**/*.ts\"",
41
+ "prepare": "[ -d src ] && tsc && node scripts/bundle.mjs || true",
42
+ "prepublishOnly": "npm run build && npm run bundle",
43
+ "postinstall": "[ -f dist/cli/install.js ] && node dist/cli/install.js || true",
44
+ "setup": "node dist/cli/dezycro.js setup",
45
+ "test": "npm run lint && npm run build && node --test test/*.test.js"
45
46
  },
46
47
  "devDependencies": {
47
48
  "@types/node": "^25.9.1",
48
- "typescript": "^5.6.0"
49
+ "esbuild": "^0.28.0",
50
+ "eslint": "^10.4.1",
51
+ "prettier": "^3.8.3",
52
+ "typescript": "^5.6.0",
53
+ "typescript-eslint": "^8.60.1"
54
+ },
55
+ "dependencies": {
56
+ "tslog": "^4.10.2"
49
57
  }
50
58
  }
@@ -90,21 +90,23 @@ If no `setup` command, skip this step. If there's a `healthCheck` but no `setup`
90
90
 
91
91
  2. Call `pull_verifier(featureId, platform)` via MCP (using the `pull_verifier` tool with `featureId` and `platform` parameters).
92
92
 
93
- 3. If the tool returns an error indicating no binary exists:
94
- - Check generation status by calling `generation_status(workspaceId, featureId)` via MCP.
95
- - If generation is **in progress** (status is not IDLE/COMPLETE/FAILED):
96
- - Tell the user: "JEP generation in progress — waiting for binary..."
97
- - Poll `generation_status` every 15 seconds, up to 20 times (5 minutes).
98
- - Show a brief status update every poll: "Still generating... (<status>)"
99
- - Once status is COMPLETE, retry `pull_verifier`.
100
- - If status is FAILED or timeout reached, tell the user:
101
- > JEP generation failed or timed out. Check the generation logs or run `/dezycro:publish-spec` to retry.
102
- - Then stop.
103
- - If generation is **IDLE** (never started):
104
- - Tell the user:
105
- > No verifier binary available. The feature needs an API spec first.
106
- > Run `/dezycro:publish-spec` to upload your spec and trigger JEP generation.
107
- - Then stop.
93
+ 3. If the tool returns an error indicating no binary exists, the verifier is still generating or compiling. Don't busy-poll — block on the *pushed* event with the bundled generic CLI, filtered to the verifier event type. It server-side long-polls `/inbox/wait`, prints the first matching event as JSON the moment it lands, and exits 0 (event) / 5 (timeout) / 2 (error). It reads the token/workspace/active-feature from `.dezycro/` itself:
94
+
95
+ ```bash
96
+ dezycro await-event --event-types VERIFIER_STATUS_UPDATE --feature "$FEATURE" --timeout 600
97
+ echo "exit=$?"
98
+ ```
99
+
100
+ Act on the exit code, then (on 0) on the event's `payload`:
101
+
102
+ - **exit 5 (TIMEOUT)**: no event within the budget. Do one final direct `pull_verifier`; if it still returns no binary, tell the user verification did not run and to check the generation pipeline. Do NOT claim verification ran.
103
+ - **exit 2 (ERROR / not configured)**: couldn't reach the endpoint, or no feature is bound. Show the line; fall back to a single `pull_verifier` retry before giving up.
104
+ - **exit 0**: an event was printed as JSON. Read its `payload` and act:
105
+ - **`payload.status` = `READY`**: the binary is ready. Re-run `pull_verifier(featureId, platform)` and continue to Step 4.4.
106
+ - **`payload.status` = `EMPTY`, or `payload.stage` = `JEP_GENERATION`**: generation produced no executable checks (the journeys aren't checkable API outcomes). STOP. Quote `payload.message`/`payload.reasonCode`, tell the user to fix the spec, and re-run `/dezycro:publish-spec`. Do NOT claim verification ran.
107
+ - **`payload.status` = `FAILED`** (typically `payload.stage` = `COMPILE`): the verifier build failed. STOP. Quote the message and offer to retry via the `retry_verifier_build` MCP tool, then re-run this wait. Do NOT claim verification ran.
108
+
109
+ (If the agent is doing other work instead of waiting here, it doesn't need this command — the Dezycro companion injects the same event as a background nudge when it lands; read its `payload` the same way.)
108
110
 
109
111
  4. From the response, extract `downloadUrl`, `contentHash`, and any CLI usage hints.
110
112
 
package/LICENSE DELETED
@@ -1,18 +0,0 @@
1
- Copyright (c) 2026 Dezycro Inc. All rights reserved.
2
-
3
- This software and its source code are proprietary and confidential to
4
- Dezycro Inc. No part of this software may be reproduced, distributed,
5
- modified, sublicensed, or used to create derivative works, in whole or
6
- in part, without the prior written permission of Dezycro Inc.
7
-
8
- The software is provided to authorized users solely for use with the
9
- Dezycro platform under the terms of a separate agreement. Unauthorized
10
- copying, distribution, reverse engineering, decompilation, or
11
- disassembly is strictly prohibited.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
16
- IN NO EVENT SHALL DEZYCRO INC. BE LIABLE FOR ANY CLAIM, DAMAGES, OR
17
- OTHER LIABILITY ARISING FROM, OUT OF, OR IN CONNECTION WITH THE
18
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,112 +0,0 @@
1
- #!/usr/bin/env node
2
- // Resolve .dezycro/auth.local.json into a shell-safe env fragment suitable for
3
- // `env $(dezycro-resolve-auth) <verifier-binary> ...`.
4
- //
5
- // Schema is documented in claude-plugin/PERSONAS.md:
6
- // personas.<name>.envVar → env var name to set (e.g. AUTH_ADMIN1)
7
- // personas.<name>.config → JSON payload (the value of the env var)
8
- // secrets.<NAME> → secret pool used by ${NAME} substitution
9
- // values may be:
10
- // inline literal
11
- // "!file:<path>" — read file contents (~ expanded)
12
- // "!env:<NAME>" — read from process env
13
- // "!cmd:<command>" — run via /bin/sh -c, use trimmed stdout
14
- //
15
- // Missing file → exit 0 with empty output (not an error: CI/dev may export
16
- // the AUTH_* vars directly). Per-persona failures emit a stderr warning and
17
- // skip that persona so unrelated tests can still run.
18
- //
19
- // Usage:
20
- // dezycro-resolve-auth [<path>] # defaults to .dezycro/auth.local.json
21
- // eval "$(dezycro-resolve-auth)"; ./verifier run ...
22
- //
23
- // Output is newline-separated `export KEY='value'` statements, where single
24
- // quotes inside the value are POSIX-escaped. MUST be consumed via `eval`
25
- // (or `source /dev/stdin <<< "$(...)"`), NOT via `env $(…)` — the latter
26
- // skips shell quote-stripping and hands the binary a value that still starts
27
- // with a literal `'`, producing `invalid character '\'' looking for …` parse
28
- // errors from the Go JSON decoder.
29
-
30
- const fs = require("fs");
31
- const os = require("os");
32
- const { execSync } = require("child_process");
33
-
34
- function shQuote(s) {
35
- return "'" + String(s).replace(/'/g, "'\\''") + "'";
36
- }
37
-
38
- function resolveSecret(raw) {
39
- if (typeof raw !== "string") return raw;
40
- if (raw.startsWith("!file:")) {
41
- const p = raw.slice(6).replace(/^~(?=\/|$)/, os.homedir());
42
- return fs.readFileSync(p, "utf8").replace(/\s+$/, "");
43
- }
44
- if (raw.startsWith("!env:")) {
45
- const name = raw.slice(5);
46
- if (!(name in process.env)) throw new Error(`env var not set: ${name}`);
47
- return process.env[name];
48
- }
49
- if (raw.startsWith("!cmd:")) {
50
- const cmd = raw.slice(5);
51
- const out = execSync(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
52
- const trimmed = out.replace(/\s+$/, "");
53
- if (!trimmed) throw new Error(`empty stdout from: ${cmd}`);
54
- return trimmed;
55
- }
56
- return raw;
57
- }
58
-
59
- function substitute(obj, secrets) {
60
- if (typeof obj === "string") {
61
- return obj.replace(/\$\{([A-Z0-9_]+)\}/g, (_, name) => {
62
- if (!(name in secrets)) throw new Error(`\${${name}} not in secrets`);
63
- return secrets[name];
64
- });
65
- }
66
- if (Array.isArray(obj)) return obj.map((x) => substitute(x, secrets));
67
- if (obj && typeof obj === "object") {
68
- const out = {};
69
- for (const [k, v] of Object.entries(obj)) out[k] = substitute(v, secrets);
70
- return out;
71
- }
72
- return obj;
73
- }
74
-
75
- function main() {
76
- const authPath = process.argv[2] || ".dezycro/auth.local.json";
77
- if (!fs.existsSync(authPath)) {
78
- process.stderr.write(`[dezycro-resolve-auth] no auth file at ${authPath}; emitting nothing\n`);
79
- return;
80
- }
81
- let doc;
82
- try {
83
- doc = JSON.parse(fs.readFileSync(authPath, "utf8"));
84
- } catch (e) {
85
- process.stderr.write(`[dezycro-resolve-auth] parse error in ${authPath}: ${e.message}\n`);
86
- process.exit(1);
87
- }
88
-
89
- const secrets = {};
90
- for (const [k, v] of Object.entries(doc.secrets || {})) {
91
- try {
92
- secrets[k] = resolveSecret(v);
93
- } catch (e) {
94
- process.stderr.write(`[dezycro-resolve-auth] warning: secret ${k}: ${e.message}\n`);
95
- }
96
- }
97
-
98
- const lines = [];
99
- for (const [name, p] of Object.entries(doc.personas || {})) {
100
- if (!p || !p.envVar) continue;
101
- try {
102
- const cfg = substitute(p.config || {}, secrets);
103
- lines.push(`export ${p.envVar}=${shQuote(JSON.stringify(cfg))}`);
104
- } catch (e) {
105
- process.stderr.write(`[dezycro-resolve-auth] warning: persona '${name}' skipped: ${e.message}\n`);
106
- }
107
- }
108
-
109
- if (lines.length) process.stdout.write(lines.join("\n") + "\n");
110
- }
111
-
112
- main();