intentdna 1.5.16 → 1.5.17
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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +72 -92
- package/dist/audit/index.d.ts +12 -3
- package/dist/cli/commands/feedback.d.ts +3 -0
- package/dist/cli/commands/feedback.js +33 -11
- package/dist/cli/commands/run.js +1 -1
- package/dist/cli/commands/sync.js +5 -5
- package/dist/compiler/cascade.d.ts +3 -1
- package/dist/compiler/cascade.js +86 -2
- package/dist/compiler/compile.js +93 -3
- package/dist/compiler/workflow.d.ts +1 -0
- package/dist/compiler/workflow.js +1 -0
- package/dist/evolution/trace-bridge.d.ts +4 -5
- package/dist/evolution/trace-bridge.js +31 -55
- package/dist/hooks/cli.d.ts +18 -1
- package/dist/hooks/cli.js +624 -24
- package/dist/hooks/enforce.js +3 -2
- package/dist/hooks/state.d.ts +20 -1
- package/dist/hooks/state.js +55 -0
- package/dist/runtime/settings-adapter.d.ts +3 -2
- package/dist/runtime/settings-adapter.js +26 -4
- package/dist/runtime/skill-adapter.js +49 -23
- package/dist/schema/types.d.ts +39 -0
- package/dist/schema/validate.js +143 -0
- package/dist/signals/index.d.ts +45 -0
- package/dist/signals/index.js +117 -0
- package/dist/templates/code-review-pipeline.dna.yaml +4 -0
- package/dist/templates/flutter-rewrite.dna.yaml +34 -11
- package/dist/templates/full-pipeline.dna.yaml +4 -0
- package/dist/templates/mobile-dev.dna.yaml +5 -0
- package/hooks/hooks.json +1 -1
- package/package.json +1 -1
- package/spec/control-plane-convergence-handoff-2026-04-24.md +432 -0
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{
|
|
10
10
|
"name": "intentdna",
|
|
11
11
|
"description": "Declarative policy layer for AI agent behavior with plugin-managed hook runtime for Claude Code.",
|
|
12
|
-
"version": "1.5.
|
|
12
|
+
"version": "1.5.17",
|
|
13
13
|
"author": {
|
|
14
14
|
"name": "Samuel"
|
|
15
15
|
},
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
]
|
|
26
26
|
}
|
|
27
27
|
],
|
|
28
|
-
"version": "1.5.
|
|
28
|
+
"version": "1.5.17"
|
|
29
29
|
}
|
package/README.md
CHANGED
|
@@ -1,133 +1,105 @@
|
|
|
1
1
|
# Intent DNA
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Declarative control plane for AI agent behavior.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
npm install -g intentdna
|
|
7
|
-
cd your-project
|
|
8
|
-
dna guard
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
That's it. Your AI agent (Claude Code, Cursor, Cline) now has safety boundaries — no more accidental `rm -rf`, force-push to main, or production deletes.
|
|
5
|
+
Intent DNA turns intent, policy, and accumulated experience into enforceable agent constraints. Instead of relying on prompts alone, it compiles DNA into the native control surfaces of Claude Code and related harnesses. It governs how agents operate across existing tools and systems; it does not replace your business systems or act as a domain-specific automation runtime.
|
|
12
6
|
|
|
13
7
|
---
|
|
14
8
|
|
|
15
|
-
##
|
|
9
|
+
## What It Is
|
|
10
|
+
|
|
11
|
+
Intent DNA is a compiler and runtime toolkit for managing agent behavior across three layers:
|
|
12
|
+
|
|
13
|
+
- **Behavioral guidance** via generated prompt/context files
|
|
14
|
+
- **Deterministic enforcement** via hooks and runtime checks
|
|
15
|
+
- **Feedback loops** via trace, audit, and epigenetic evolution
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
It governs the agents operating on your systems rather than re-implementing the systems themselves.
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
The core model is:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
DNA config → compiler pipeline → Constraint IR → harness-specific outputs
|
|
23
|
+
```
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
For the architectural model and long-term design, see [DESIGN.md](DESIGN.md).
|
|
26
|
+
For the current stage and upcoming work, see [ROADMAP.md](ROADMAP.md).
|
|
27
|
+
For the schema contract, see [spec/schema-spec.md](spec/schema-spec.md).
|
|
28
|
+
|
|
29
|
+
## Design Principles
|
|
30
|
+
|
|
31
|
+
- Govern agents rather than re-implementing business systems.
|
|
32
|
+
- Declare intent and boundaries first, then compile them into native control surfaces.
|
|
33
|
+
- Combine guidance, enforcement, validation, and feedback into one governance loop.
|
|
34
|
+
- Treat runtime state, validators, and signals as first-class governance assets.
|
|
35
|
+
- Keep adapters and signal ingestion pluggable so the control plane outlives any single tool.
|
|
25
36
|
|
|
26
37
|
---
|
|
27
38
|
|
|
28
39
|
## Quick Start
|
|
29
40
|
|
|
30
|
-
### Option 1: Zero-
|
|
41
|
+
### Option 1: Zero-config guardrails
|
|
31
42
|
|
|
32
43
|
```bash
|
|
33
44
|
npm install -g intentdna
|
|
34
45
|
cd your-project
|
|
35
|
-
dna guard
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
**What it does:**
|
|
39
|
-
- Detects your AI coding environment
|
|
40
|
-
- Injects safety rules (no production deletes, no force-push, etc.)
|
|
41
|
-
- Generates enforcement hooks (hard blocks, not suggestions)
|
|
42
|
-
- Creates audit logs at `~/.intentdna/audit/`
|
|
43
|
-
|
|
44
|
-
**Levels:**
|
|
45
|
-
```bash
|
|
46
|
-
dna guard --level standard # Safety baseline (default)
|
|
47
|
-
dna guard --level yolo # Max autonomy + safety net
|
|
48
|
-
dna guard --level strict # Enterprise-grade
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
**Audit:**
|
|
52
|
-
```bash
|
|
53
|
-
dna guard --audit # Show last 7 days of violations
|
|
54
|
-
dna guard --remove # Remove all guardrails
|
|
46
|
+
dna guard
|
|
55
47
|
```
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
### Option 2: Custom DNA (Advanced)
|
|
60
|
-
|
|
61
|
-
Start from a template:
|
|
49
|
+
### Option 2: Template-based DNA
|
|
62
50
|
|
|
63
51
|
```bash
|
|
64
52
|
dna init --template secure-dev
|
|
65
|
-
dna sync
|
|
53
|
+
dna sync
|
|
66
54
|
```
|
|
67
55
|
|
|
68
|
-
|
|
56
|
+
List templates:
|
|
69
57
|
|
|
70
58
|
```bash
|
|
71
|
-
dna
|
|
72
|
-
# Edit .dna.yaml to customize
|
|
73
|
-
dna sync .dna.yaml --inject CLAUDE.md --hooks .claude/hooks
|
|
59
|
+
dna init --template list
|
|
74
60
|
```
|
|
75
61
|
|
|
76
|
-
|
|
62
|
+
Upgrade an existing template-backed config:
|
|
77
63
|
|
|
78
|
-
## 20 Built-in Templates
|
|
79
|
-
|
|
80
|
-
**Workflows (Superpowers-inspired):**
|
|
81
|
-
- `brainstorming-first` — Socratic design before coding
|
|
82
|
-
- `subagent-parallel` — Multi-agent with two-phase review
|
|
83
|
-
- `verification-loop` — Confirm fix before marking done
|
|
84
|
-
- `branch-finishing` — Merge/PR/cleanup decisions
|
|
85
|
-
- `pr-submitter` — Pre-review checklist
|
|
86
|
-
|
|
87
|
-
**Quality & Safety:**
|
|
88
|
-
- `secure-dev` — Security + quality baseline
|
|
89
|
-
- `tdd-strict` — Strict test-driven development
|
|
90
|
-
- `safe-refactoring` — Step-by-step refactoring
|
|
91
|
-
- `systematic-debugging` — Structured debugging
|
|
92
|
-
- `code-review-pipeline` — Review workflow with retry
|
|
93
|
-
|
|
94
|
-
**Domain-Specific:**
|
|
95
|
-
- `frontend-quality` — React/accessibility/performance
|
|
96
|
-
- `api-backend` — API security + database safety
|
|
97
|
-
- `mobile-dev` — Flutter/React Native standards
|
|
98
|
-
- `devops-cicd` — CI/CD agent guardrails
|
|
99
|
-
- `monorepo-governance` — Multi-package isolation
|
|
100
|
-
|
|
101
|
-
**Collaboration:**
|
|
102
|
-
- `multi-perspective-review` — Bull/Bear debate review
|
|
103
|
-
- `documentation-writer` — Technical docs
|
|
104
|
-
- `enterprise-baseline` — Organization security
|
|
105
|
-
- `yolo-with-guardrails` — Full autonomy + limits
|
|
106
|
-
- `full-pipeline` — Complete plan→implement→test→review
|
|
107
|
-
|
|
108
|
-
List all:
|
|
109
64
|
```bash
|
|
110
|
-
dna init --template
|
|
65
|
+
dna init --upgrade <template-name>
|
|
111
66
|
```
|
|
112
67
|
|
|
113
68
|
---
|
|
114
69
|
|
|
115
70
|
## How It Works
|
|
116
71
|
|
|
117
|
-
DNA compiles to your
|
|
72
|
+
Intent DNA compiles to your tool's native control surfaces:
|
|
118
73
|
|
|
119
|
-
```
|
|
120
|
-
|
|
74
|
+
```text
|
|
75
|
+
DNA → Constraint IR → CLAUDE.md / settings / agents / skills / runtime state
|
|
121
76
|
```
|
|
122
77
|
|
|
78
|
+
Typical outputs include:
|
|
79
|
+
|
|
123
80
|
| Output | Purpose |
|
|
124
81
|
|--------|---------|
|
|
125
|
-
| `CLAUDE.md` | Behavioral
|
|
126
|
-
| `.
|
|
82
|
+
| `CLAUDE.md` | Behavioral guidance |
|
|
83
|
+
| `.dna/compiled/ir.json` | Runtime-readable compiled constraints |
|
|
127
84
|
| `.claude/agents/*.md` | Role definitions |
|
|
128
|
-
| `.
|
|
85
|
+
| `.claude/skills/*/SKILL.md` | Workflow entrypoints |
|
|
86
|
+
| `.claude/settings.json` or plugin runtime | Hook wiring |
|
|
129
87
|
|
|
130
|
-
**Key
|
|
88
|
+
**Key idea:** prompts can drift, but runtime constraints and feedback loops make behavior governable.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Supported Workflows
|
|
93
|
+
|
|
94
|
+
Intent DNA currently focuses on:
|
|
95
|
+
|
|
96
|
+
- Claude Code / Claude-style harnesses
|
|
97
|
+
- Role-based agent workflows
|
|
98
|
+
- Template-driven project bootstrap and upgrades
|
|
99
|
+
- Deterministic guardrails and stateful enforcement
|
|
100
|
+
- Dogfood-driven template iteration
|
|
101
|
+
|
|
102
|
+
Adapter and ecosystem direction are tracked in [ROADMAP.md](ROADMAP.md), not duplicated here.
|
|
131
103
|
|
|
132
104
|
---
|
|
133
105
|
|
|
@@ -197,10 +169,8 @@ workflows:
|
|
|
197
169
|
## Supported Environments
|
|
198
170
|
|
|
199
171
|
- ✅ **Claude Code** (CLAUDE.md + hooks + agents + skills + settings)
|
|
200
|
-
-
|
|
201
|
-
- ✅ **Cline** (.clinerules)
|
|
172
|
+
- 🚧 **Prompt-style adapters and markdown outputs** (.cursorrules, .clinerules, GEMINI.md)
|
|
202
173
|
- 🚧 **AgentScope** (coming soon)
|
|
203
|
-
- 🚧 **Gemini CLI** (GEMINI.md)
|
|
204
174
|
|
|
205
175
|
---
|
|
206
176
|
|
|
@@ -223,13 +193,23 @@ dna evolve <dna-id> # Generate epigenetic markers from outcomes
|
|
|
223
193
|
|
|
224
194
|
- **Genes** encode behavioral traits
|
|
225
195
|
- **Codons** are the atomic instructions
|
|
226
|
-
- **Cascade** mimics
|
|
227
|
-
- **Epigenetics** learns from experience without
|
|
196
|
+
- **Cascade** mimics inheritance and override rules
|
|
197
|
+
- **Epigenetics** learns from experience without mutating source intent
|
|
228
198
|
|
|
229
199
|
Read more: [DESIGN.md](DESIGN.md)
|
|
230
200
|
|
|
231
201
|
---
|
|
232
202
|
|
|
203
|
+
## Documentation Map
|
|
204
|
+
|
|
205
|
+
- [DESIGN.md](DESIGN.md) — long-term architecture and design
|
|
206
|
+
- [ROADMAP.md](ROADMAP.md) — current stage, next plan, deferred work
|
|
207
|
+
- [spec/schema-spec.md](spec/schema-spec.md) — schema contract
|
|
208
|
+
- [docs/references/](docs/references/) — distilled research and implementation references
|
|
209
|
+
- [docs/insights/](docs/insights/) — strategic and product-thinking documents
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
233
213
|
## License
|
|
234
214
|
|
|
235
215
|
Apache-2.0
|
|
@@ -248,4 +228,4 @@ Issues and PRs welcome. See [ROADMAP.md](ROADMAP.md) for planned features.
|
|
|
248
228
|
- [Cline KanBan](https://github.com/cline/cline-kanban) — Multi-agent task orchestration
|
|
249
229
|
- [AgentScope](https://github.com/modelscope/agentscope) — Multi-agent framework from Alibaba
|
|
250
230
|
|
|
251
|
-
Intent DNA
|
|
231
|
+
Intent DNA is designed to compile into the native control surfaces those frameworks expose, with current maturity varying by adapter.
|
package/dist/audit/index.d.ts
CHANGED
|
@@ -37,9 +37,17 @@ export interface PolicyViolationEvent extends AuditEvent {
|
|
|
37
37
|
/** Completion check event */
|
|
38
38
|
export interface CompletionCheckEvent extends AuditEvent {
|
|
39
39
|
event_type: "completion_check";
|
|
40
|
-
check_type: "file_exists" | "file_not_empty" | "file_contains" | "command_success";
|
|
40
|
+
check_type: "file_exists" | "file_not_empty" | "file_contains" | "command_success" | "checkpoint_assert";
|
|
41
41
|
target: string;
|
|
42
42
|
result: "pass" | "fail";
|
|
43
|
+
verifier_id?: string;
|
|
44
|
+
verifier_when?: string;
|
|
45
|
+
verifier_severity?: string;
|
|
46
|
+
verifier_kind?: string;
|
|
47
|
+
evidence?: string;
|
|
48
|
+
exit_code?: number;
|
|
49
|
+
artifact?: string;
|
|
50
|
+
message?: string;
|
|
43
51
|
}
|
|
44
52
|
/** Session event */
|
|
45
53
|
export interface SessionEvent extends AuditEvent {
|
|
@@ -56,6 +64,7 @@ export interface ConfigDriftEvent extends AuditEvent {
|
|
|
56
64
|
expected_checksum: string;
|
|
57
65
|
actual_checksum: string;
|
|
58
66
|
}
|
|
67
|
+
export type AnyAuditEvent = AuditEvent | ToolCallEvent | PolicyViolationEvent | CompletionCheckEvent | SessionEvent | ConfigDriftEvent;
|
|
59
68
|
export interface AuditConfig {
|
|
60
69
|
enabled: boolean;
|
|
61
70
|
storage: string;
|
|
@@ -67,7 +76,7 @@ export type AuditTrackOption = "tool_calls" | "policy_violations" | "completion_
|
|
|
67
76
|
* Write an audit event to the log.
|
|
68
77
|
* Events are stored as JSONL (one JSON per line) in daily files.
|
|
69
78
|
*/
|
|
70
|
-
export declare function writeAuditEvent(event:
|
|
79
|
+
export declare function writeAuditEvent(event: AnyAuditEvent, config: AuditConfig): Promise<void>;
|
|
71
80
|
/**
|
|
72
81
|
* Read audit events for a date range.
|
|
73
82
|
*/
|
|
@@ -75,7 +84,7 @@ export declare function readAuditEvents(logDir: string, options?: {
|
|
|
75
84
|
from?: string;
|
|
76
85
|
to?: string;
|
|
77
86
|
event_type?: AuditEventType;
|
|
78
|
-
}): Promise<
|
|
87
|
+
}): Promise<AnyAuditEvent[]>;
|
|
79
88
|
export interface AuditSummary {
|
|
80
89
|
period: {
|
|
81
90
|
from: string;
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* Reads: .dna/state/trace/trace-*.jsonl
|
|
8
8
|
* Outputs: human-readable report (or JSON with --json)
|
|
9
9
|
*/
|
|
10
|
-
import { readTraces } from "../../hooks/state.js";
|
|
11
|
-
import {
|
|
10
|
+
import { readTraces, readVerifierResults } from "../../hooks/state.js";
|
|
11
|
+
import { mergeOutcomes, summarizeConversion } from "../../evolution/trace-bridge.js";
|
|
12
12
|
import { describeMarkerChanges } from "../../evolution/marker-gen.js";
|
|
13
13
|
import { EvolutionStore } from "../../evolution/store.js";
|
|
14
14
|
function aggregate(traces) {
|
|
@@ -50,10 +50,15 @@ function aggregate(traces) {
|
|
|
50
50
|
top_block_reasons: sorted(reasonCounts, 5, "reason"),
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
function generateSuggestions(report) {
|
|
53
|
+
function generateSuggestions(report, verifierResults = 0) {
|
|
54
54
|
const suggestions = [];
|
|
55
55
|
if (report.blocks === 0 && report.warns === 0) {
|
|
56
|
-
|
|
56
|
+
if (verifierResults > 0) {
|
|
57
|
+
suggestions.push("No trace blocks or warnings in this window. Verifier activity is present, so review verifier pass/fail results alongside trace data.");
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
suggestions.push("No blocks or warnings — DNA constraints are not firing. Consider tightening rules or verifying hooks are active.");
|
|
61
|
+
}
|
|
57
62
|
return suggestions;
|
|
58
63
|
}
|
|
59
64
|
const blockRate = report.total_events > 0 ? report.blocks / report.total_events : 0;
|
|
@@ -93,6 +98,12 @@ function formatReport(report) {
|
|
|
93
98
|
lines.push(` Blocked: ${report.blocks}`);
|
|
94
99
|
lines.push(` Warned: ${report.warns}`);
|
|
95
100
|
lines.push("");
|
|
101
|
+
if (report.verifier_results > 0) {
|
|
102
|
+
lines.push(`Verifier results: ${report.verifier_results}`);
|
|
103
|
+
lines.push(` Passed: ${report.verifier_passes}`);
|
|
104
|
+
lines.push(` Failed: ${report.verifier_failures}`);
|
|
105
|
+
lines.push("");
|
|
106
|
+
}
|
|
96
107
|
if (report.top_blocked_tools.length > 0) {
|
|
97
108
|
lines.push("Top blocked tools:");
|
|
98
109
|
for (const t of report.top_blocked_tools) {
|
|
@@ -126,23 +137,34 @@ function formatReport(report) {
|
|
|
126
137
|
export async function runFeedback(opts) {
|
|
127
138
|
const projectDir = process.cwd();
|
|
128
139
|
const traces = await readTraces(projectDir, opts.days);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
const cutoff = new Date();
|
|
141
|
+
cutoff.setDate(cutoff.getDate() - opts.days);
|
|
142
|
+
const verifierResults = (await readVerifierResults(projectDir)).filter((result) => {
|
|
143
|
+
const timestamp = Date.parse(result.timestamp);
|
|
144
|
+
return Number.isNaN(timestamp) || timestamp >= cutoff.getTime();
|
|
145
|
+
});
|
|
146
|
+
if (traces.length === 0 && verifierResults.length === 0) {
|
|
147
|
+
process.stderr.write(`No trace or verifier data found for the last ${opts.days} day(s).\n`);
|
|
148
|
+
process.stderr.write("Signals are generated by dna-hook during Claude Code sessions.\n");
|
|
132
149
|
return 0;
|
|
133
150
|
}
|
|
134
151
|
const stats = aggregate(traces);
|
|
135
|
-
const
|
|
136
|
-
|
|
152
|
+
const verifierStats = {
|
|
153
|
+
verifier_results: verifierResults.length,
|
|
154
|
+
verifier_passes: verifierResults.filter((result) => result.status === "pass").length,
|
|
155
|
+
verifier_failures: verifierResults.filter((result) => result.status === "fail").length,
|
|
156
|
+
};
|
|
157
|
+
const suggestions = generateSuggestions(stats, verifierStats.verifier_results);
|
|
158
|
+
const report = { ...stats, ...verifierStats, period_days: opts.days, suggestions };
|
|
137
159
|
if (opts.json && !opts.evolve) {
|
|
138
160
|
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
139
161
|
}
|
|
140
162
|
else if (!opts.evolve) {
|
|
141
163
|
process.stderr.write(formatReport(report));
|
|
142
164
|
}
|
|
143
|
-
// --evolve: convert
|
|
165
|
+
// --evolve: convert normalized local signals → epigenetic markers
|
|
144
166
|
if (opts.evolve) {
|
|
145
|
-
const outcomes =
|
|
167
|
+
const outcomes = mergeOutcomes(traces, verifierResults);
|
|
146
168
|
if (outcomes.length === 0) {
|
|
147
169
|
process.stderr.write(formatReport(report));
|
|
148
170
|
process.stderr.write("\nNo actionable gene feedback found in traces — nothing to evolve.\n");
|
package/dist/cli/commands/run.js
CHANGED
|
@@ -270,7 +270,7 @@ export async function runRun(opts) {
|
|
|
270
270
|
process.stderr.write(`Error: Workflow '${opts.workflowName}' not found. Available: ${Object.keys(cascaded.workflows).join(", ") || "(none)"}\n`);
|
|
271
271
|
return 1;
|
|
272
272
|
}
|
|
273
|
-
const wfResult = compileWorkflow(wfDef);
|
|
273
|
+
const wfResult = compileWorkflow(wfDef, { workflow_key: opts.workflowName });
|
|
274
274
|
if (!wfResult.ok) {
|
|
275
275
|
process.stderr.write(`Error: Workflow compilation failed:\n`);
|
|
276
276
|
for (const err of wfResult.errors) {
|
|
@@ -21,7 +21,7 @@ import { compileToMarkdown, injectIntoFile, removeFromFile } from "../../runtime
|
|
|
21
21
|
import { compileAllRolesToAgentMD, writeAgentMDFiles, removeAgentMDFiles } from "../../runtime/agent-md.js";
|
|
22
22
|
import { removeWorkflowScripts } from "../../runtime/workflow-runner.js";
|
|
23
23
|
import { compileWorkflowToSkill, writeSkillFiles } from "../../runtime/skill-adapter.js";
|
|
24
|
-
import { compilePluginSettings, detectEnabledEvents, mergeSettingsFile } from "../../runtime/settings-adapter.js";
|
|
24
|
+
import { compilePluginSettings, detectEnabledEvents, mergeSettingsFile, recommendHookTimeouts } from "../../runtime/settings-adapter.js";
|
|
25
25
|
import { createCompiledIR, writeCompiledIR } from "../../runtime/plugin-adapter.js";
|
|
26
26
|
import { cascadeDNA } from "../../compiler/cascade.js";
|
|
27
27
|
import { EvolutionEngine } from "../../evolution/index.js";
|
|
@@ -569,7 +569,7 @@ export async function runSync(opts) {
|
|
|
569
569
|
if (!opts.plugin && opts.settingsPath) {
|
|
570
570
|
const enabledEvents = detectEnabledEvents(ir);
|
|
571
571
|
if (enabledEvents.length > 0) {
|
|
572
|
-
const pluginSettings = compilePluginSettings(enabledEvents);
|
|
572
|
+
const pluginSettings = compilePluginSettings(enabledEvents, 10, recommendHookTimeouts(ir));
|
|
573
573
|
await mergeSettingsFile(pluginSettings, opts.settingsPath);
|
|
574
574
|
process.stderr.write(`Bin mode: registered ${enabledEvents.length} hook event(s) in ${opts.settingsPath}\n`);
|
|
575
575
|
trackedOutputs.push(resolve(opts.settingsPath));
|
|
@@ -627,7 +627,7 @@ export async function runSync(opts) {
|
|
|
627
627
|
process.stderr.write(`Workflow '${name}' not found\n`);
|
|
628
628
|
continue;
|
|
629
629
|
}
|
|
630
|
-
const result = compileWorkflow(wfDef);
|
|
630
|
+
const result = compileWorkflow(wfDef, { workflow_key: name });
|
|
631
631
|
if (!result.ok) {
|
|
632
632
|
process.stderr.write(`Workflow '${name}' compilation failed:\n`);
|
|
633
633
|
for (const err of result.errors) {
|
|
@@ -682,8 +682,8 @@ export async function runSync(opts) {
|
|
|
682
682
|
else {
|
|
683
683
|
const { compileWorkflow } = await import("../../compiler/workflow.js");
|
|
684
684
|
const skillResults = [];
|
|
685
|
-
for (const [, wfDef] of Object.entries(workflows)) {
|
|
686
|
-
const result = compileWorkflow(wfDef);
|
|
685
|
+
for (const [name, wfDef] of Object.entries(workflows)) {
|
|
686
|
+
const result = compileWorkflow(wfDef, { workflow_key: name });
|
|
687
687
|
if (result.ok) {
|
|
688
688
|
skillResults.push(compileWorkflowToSkill(result.plan, roles, ir, variables));
|
|
689
689
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - attract/repel: same target accumulates, different targets independent
|
|
11
11
|
* - amplify/suppress: factors multiply (1.5x × 2.0x = 3.0x)
|
|
12
12
|
*/
|
|
13
|
-
import type { IntentDNA, Gene, ContextRegion, EpigeneticMarker, RoleDef, WorkflowDef } from "../schema/types.js";
|
|
13
|
+
import type { IntentDNA, Gene, ContextRegion, EpigeneticMarker, RoleDef, WorkflowDef, LegibilityAssetMap, VerifierCommandPolicy } from "../schema/types.js";
|
|
14
14
|
export interface CascadedDNA {
|
|
15
15
|
genes: Record<string, Gene>;
|
|
16
16
|
contexts: Record<string, ContextRegion>;
|
|
@@ -20,11 +20,13 @@ export interface CascadedDNA {
|
|
|
20
20
|
source_ids: string[];
|
|
21
21
|
/** Warnings from cascade process (e.g., cross-namespace gene collisions) */
|
|
22
22
|
warnings?: string[];
|
|
23
|
+
legibility_assets?: LegibilityAssetMap;
|
|
23
24
|
context_files?: {
|
|
24
25
|
mandatory?: string[];
|
|
25
26
|
per_role?: Record<string, string[]>;
|
|
26
27
|
per_workflow?: Record<string, string[]>;
|
|
27
28
|
};
|
|
29
|
+
verifier_policy?: VerifierCommandPolicy;
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
32
|
* Cascade multiple DNA layers into a single merged DNA.
|
package/dist/compiler/cascade.js
CHANGED
|
@@ -84,6 +84,80 @@ function prefixWorkflowRoles(wf, ns) {
|
|
|
84
84
|
})),
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
|
+
function prefixRecordKeys(record, ns) {
|
|
88
|
+
if (!record)
|
|
89
|
+
return undefined;
|
|
90
|
+
if (!ns)
|
|
91
|
+
return record;
|
|
92
|
+
return Object.fromEntries(Object.entries(record).map(([key, value]) => [`${ns}_${key}`, value]));
|
|
93
|
+
}
|
|
94
|
+
function prefixLegibilityAssets(map, ns) {
|
|
95
|
+
if (!map)
|
|
96
|
+
return undefined;
|
|
97
|
+
if (!ns)
|
|
98
|
+
return map;
|
|
99
|
+
return {
|
|
100
|
+
mandatory: map.mandatory,
|
|
101
|
+
per_role: prefixRecordKeys(map.per_role, ns),
|
|
102
|
+
per_workflow: prefixRecordKeys(map.per_workflow, ns),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function mergePrefixedRecords(base, incoming) {
|
|
106
|
+
if (!base)
|
|
107
|
+
return incoming;
|
|
108
|
+
if (!incoming)
|
|
109
|
+
return base;
|
|
110
|
+
return { ...base, ...incoming };
|
|
111
|
+
}
|
|
112
|
+
function mergeLegibilityAssets(base, incoming) {
|
|
113
|
+
if (!base)
|
|
114
|
+
return incoming;
|
|
115
|
+
if (!incoming)
|
|
116
|
+
return base;
|
|
117
|
+
return {
|
|
118
|
+
mandatory: incoming.mandatory ?? base.mandatory,
|
|
119
|
+
per_role: mergePrefixedRecords(base.per_role, incoming.per_role),
|
|
120
|
+
per_workflow: mergePrefixedRecords(base.per_workflow, incoming.per_workflow),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function prefixContextFiles(contextFiles, ns) {
|
|
124
|
+
if (!contextFiles)
|
|
125
|
+
return undefined;
|
|
126
|
+
if (!ns)
|
|
127
|
+
return contextFiles;
|
|
128
|
+
return {
|
|
129
|
+
mandatory: contextFiles.mandatory,
|
|
130
|
+
per_role: prefixRecordKeys(contextFiles.per_role, ns),
|
|
131
|
+
per_workflow: prefixRecordKeys(contextFiles.per_workflow, ns),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function mergeContextFiles(base, incoming) {
|
|
135
|
+
if (!base)
|
|
136
|
+
return incoming;
|
|
137
|
+
if (!incoming)
|
|
138
|
+
return base;
|
|
139
|
+
return {
|
|
140
|
+
mandatory: incoming.mandatory ?? base.mandatory,
|
|
141
|
+
per_role: mergePrefixedRecords(base.per_role, incoming.per_role),
|
|
142
|
+
per_workflow: mergePrefixedRecords(base.per_workflow, incoming.per_workflow),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function mergeVerifierPolicy(base, incoming) {
|
|
146
|
+
if (!base)
|
|
147
|
+
return incoming;
|
|
148
|
+
if (!incoming)
|
|
149
|
+
return base;
|
|
150
|
+
const mergeList = (a, b) => {
|
|
151
|
+
if (!a && !b)
|
|
152
|
+
return undefined;
|
|
153
|
+
return [...new Set([...(a ?? []), ...(b ?? [])])];
|
|
154
|
+
};
|
|
155
|
+
return {
|
|
156
|
+
allow_commands: mergeList(base.allow_commands, incoming.allow_commands),
|
|
157
|
+
allow_command_prefixes: mergeList(base.allow_command_prefixes, incoming.allow_command_prefixes),
|
|
158
|
+
allow_builtin_asserts: mergeList(base.allow_builtin_asserts, incoming.allow_builtin_asserts),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
87
161
|
/**
|
|
88
162
|
* Cascade multiple DNA layers into a single merged DNA.
|
|
89
163
|
* Input must be sorted by priority (lowest first).
|
|
@@ -156,11 +230,19 @@ export function cascadeDNA(layers) {
|
|
|
156
230
|
allMarkers.push(...dna.epigenetic.markers);
|
|
157
231
|
}
|
|
158
232
|
}
|
|
159
|
-
// context_files: highest-priority DNA wins (last in sorted layers)
|
|
233
|
+
// legibility_assets/context_files: highest-priority DNA wins (last in sorted layers)
|
|
234
|
+
let legibilityAssets;
|
|
160
235
|
let contextFiles;
|
|
236
|
+
let verifierPolicy;
|
|
161
237
|
for (const dna of sorted) {
|
|
238
|
+
if (dna.legibility_assets) {
|
|
239
|
+
legibilityAssets = mergeLegibilityAssets(legibilityAssets, prefixLegibilityAssets(dna.legibility_assets, dna.namespace));
|
|
240
|
+
}
|
|
162
241
|
if (dna.context_files) {
|
|
163
|
-
contextFiles = dna.context_files;
|
|
242
|
+
contextFiles = mergeContextFiles(contextFiles, prefixContextFiles(dna.context_files, dna.namespace));
|
|
243
|
+
}
|
|
244
|
+
if (dna.verifier_policy) {
|
|
245
|
+
verifierPolicy = mergeVerifierPolicy(verifierPolicy, dna.verifier_policy);
|
|
164
246
|
}
|
|
165
247
|
}
|
|
166
248
|
return {
|
|
@@ -171,6 +253,8 @@ export function cascadeDNA(layers) {
|
|
|
171
253
|
epigenetic_markers: allMarkers,
|
|
172
254
|
source_ids: sourceIds,
|
|
173
255
|
warnings: warnings.length > 0 ? warnings : undefined,
|
|
256
|
+
legibility_assets: legibilityAssets,
|
|
174
257
|
context_files: contextFiles,
|
|
258
|
+
verifier_policy: verifierPolicy,
|
|
175
259
|
};
|
|
176
260
|
}
|