@senpi/runtime 3.0.9-dev.feat-strategy-compos.20260716013009 → 3.0.9-dev.feat-strategy-compos.20260717153418

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 (64) hide show
  1. package/dist/cli/composer-commands.d.ts.map +1 -1
  2. package/dist/cli/composer-commands.js +111 -2
  3. package/dist/cli/composer-commands.js.map +1 -1
  4. package/dist/cli/validate-runtime-config.mjs +66 -0
  5. package/dist/composer/authoring/__init__.py +13 -1
  6. package/dist/composer/authoring/answers.py +119 -4
  7. package/dist/composer/authoring/archetypes/__init__.py +24 -6
  8. package/dist/composer/authoring/archetypes/_common.py +193 -1
  9. package/dist/composer/authoring/archetypes/breakout.py +152 -0
  10. package/dist/composer/authoring/archetypes/classifier.py +16 -0
  11. package/dist/composer/authoring/archetypes/relative_value.py +354 -0
  12. package/dist/composer/authoring/archetypes/skeleton.py +23 -1
  13. package/dist/composer/authoring/archetypes/thesis_fund.py +17 -0
  14. package/dist/composer/authoring/archetypes/trend_momentum.py +47 -3
  15. package/dist/composer/authoring/generate.py +12 -5
  16. package/dist/composer/authoring/presets.py +3 -0
  17. package/dist/composer/authoring/runtime_emit.py +57 -1
  18. package/dist/composer/cli.py +166 -11
  19. package/dist/composer/compiler/__init__.py +25 -4
  20. package/dist/composer/compiler/compile.py +432 -25
  21. package/dist/composer/examples/conviction_scorer.graph.yaml +1 -1
  22. package/dist/composer/examples/pair_relative_strength.graph.yaml +263 -0
  23. package/dist/composer/examples/pre_listing_classifier.graph.yaml +1 -1
  24. package/dist/composer/generated/catalog.md +64 -2
  25. package/dist/composer/generated/describe.md +514 -0
  26. package/dist/composer/generated/graph.schema.json +797 -4
  27. package/dist/composer/primitives/__init__.py +81 -0
  28. package/dist/composer/primitives/adapter.py +243 -0
  29. package/dist/composer/primitives/emitters.py +55 -0
  30. package/dist/composer/primitives/indicators.py +124 -1
  31. package/dist/composer/primitives/sources.py +666 -15
  32. package/dist/composer/primitives/stateful.py +217 -15
  33. package/dist/composer/registry/__init__.py +2 -0
  34. package/dist/composer/registry/generate.py +260 -9
  35. package/dist/composer/registry/mcp-tools-snapshot.json +193 -0
  36. package/dist/composer/registry/mcp_closure.py +311 -0
  37. package/dist/composer/registry/models.py +116 -2
  38. package/dist/composer/registry/nodes.py +706 -10
  39. package/dist/composer/scaffold_path.py +118 -0
  40. package/dist/composer/templates/scan.py.j2 +7 -3
  41. package/dist/composer/validator/errors.py +40 -0
  42. package/dist/composer/validator/graph_checks.py +97 -2
  43. package/dist/composer/vendoring.py +103 -0
  44. package/dist/composer/verbs/__init__.py +17 -1
  45. package/dist/composer/verbs/_box.py +308 -0
  46. package/dist/composer/verbs/check.py +92 -7
  47. package/dist/composer/verbs/close.py +494 -0
  48. package/dist/composer/verbs/deploy.py +91 -9
  49. package/dist/composer/verbs/docs.py +60 -4
  50. package/dist/composer/verbs/fund.py +498 -0
  51. package/dist/composer/verbs/install.py +586 -0
  52. package/dist/composer/verbs/runtime_validate.py +314 -4
  53. package/dist/composer/verbs/smoke.py +44 -25
  54. package/dist/composer/verbs/status.py +205 -27
  55. package/dist/runtime/load-runtime-config.d.ts +17 -0
  56. package/dist/runtime/load-runtime-config.d.ts.map +1 -1
  57. package/dist/runtime/load-runtime-config.js +2 -2
  58. package/dist/runtime/load-runtime-config.js.map +1 -1
  59. package/dist/skills-manager/manifest.d.ts.map +1 -1
  60. package/dist/skills-manager/manifest.js +0 -2
  61. package/dist/skills-manager/manifest.js.map +1 -1
  62. package/dist/skills-manager/skills-manifest.json +0 -2
  63. package/package.json +2 -2
  64. package/dist/composer/AUTHORING.md +0 -233
@@ -1 +1 @@
1
- {"version":3,"file":"composer-commands.d.ts","sourceRoot":"","sources":["../../src/cli/composer-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,UAAU,gBAAgB;IACxB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACvD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC5C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC9D,MAAM,CACJ,EAAE,EACE,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAC5B,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GACzD,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GACzE,gBAAgB,CAAC;CACrB;AAYD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AA6FD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAoKjE"}
1
+ {"version":3,"file":"composer-commands.d.ts","sourceRoot":"","sources":["../../src/cli/composer-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,UAAU,gBAAgB;IACxB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACvD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC5C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC9D,MAAM,CACJ,EAAE,EACE,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAC5B,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GACzD,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GACzE,gBAAgB,CAAC;CACrB;AAYD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAmGD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CA8QjE"}
@@ -55,6 +55,12 @@ function detectEnvError(pythonBin, root, result) {
55
55
  if (mod === "composer" || mod.startsWith("composer.")) {
56
56
  return `composer: the 'composer' package was not found under ${root} — on a claw run \`npm run build\` (copy:composer) or set COMPOSER_ROOT to your checkout root.`;
57
57
  }
58
+ if (mod === "scaffold" || mod.startsWith("scaffold.")) {
59
+ // The scaffold harness ships WITH the runtime (copy:external-scanners), never from PyPI.
60
+ // Do NOT route this to the "pip install deps" hint — and warn off `pip install scaffold`
61
+ // (an unrelated PyPI package), the exact dead end the original dev-box run hit.
62
+ return `composer: the 'scaffold' harness package was not found — on a claw run \`npm run build\` (copy:external-scanners stages it into dist/scanners/external) or set COMPOSER_SCAFFOLD_DIR to the dir that CONTAINS scaffold/ (…/src/scanners/external). Do NOT \`pip install scaffold\` — that is an unrelated PyPI package.`;
63
+ }
58
64
  return `composer: Python dependency '${mod}' is missing — install the composer deps: ${requirementsHint(root)}`;
59
65
  }
60
66
  return null;
@@ -117,7 +123,7 @@ function printErrors(errors) {
117
123
  }
118
124
  export function registerComposerCli(senpi) {
119
125
  const composer = senpi.command("composer");
120
- composer.description("Strategy Composer: new / validate / compile / check / deploy / status a strategy graph; catalog / describe nodes");
126
+ composer.description("Strategy Composer: new / validate / compile / check / deploy / fund / install / close / status a strategy graph; catalog / describe nodes");
121
127
  // new / validate / compile stream Python's own (rich) human render through — teaching
122
128
  // errors, gap reports, emitted scan.py — forwarding only the relevant flags. Thin: no
123
129
  // TS-side interpretation; the exit code is Python's (0 ok, 2 gap report, 3 clobber-refused).
@@ -239,20 +245,123 @@ export function registerComposerCli(senpi) {
239
245
  printErrors(check.errors ?? []);
240
246
  }
241
247
  else {
248
+ // Always surface the ABSOLUTE staged dir Python resolved (a relative `-o` against an
249
+ // unexpected cwd was "deploy exited 0 but there are no files where I looked"). UNCHANGED
250
+ // says plainly that nothing was rewritten so an idempotent no-op never reads as a failure.
242
251
  const staged = (json.staged ?? {});
243
- console.log(`${verdict}: ${graph} — staged to ${staged.dir}. (live tick: slice 8)`);
252
+ const dir = staged.dir ?? "(no staged dir reported)";
253
+ if (verdict === "UNCHANGED") {
254
+ console.log(`UNCHANGED: ${graph} — already staged at ${dir}, nothing rewritten (idempotent no-op).`);
255
+ }
256
+ else {
257
+ console.log(`${verdict}: ${graph} — staged to ${dir}.`);
258
+ }
259
+ }
260
+ process.exitCode = status;
261
+ });
262
+ composer
263
+ .command("fund <target>")
264
+ .description("Create + fund the strategy's wallet (MCP strategy_create_custom_strategy): preflights the balance, waits for ACTIVE, safe to re-run while funding settles")
265
+ .option("--budget <usd>", "Explicit USD to fund this strategy's wallet with (>= $100; never derived/split)")
266
+ .option("-o, --out <dir>", "Staging dir (when target is a graph file, not a staged dir)")
267
+ .option("--state-dir <dir>", "Base senpi-state dir (default: $SENPI_STATE_DIR or ~/.openclaw/senpi-state)")
268
+ .option("--json", "Print the raw Python fund verdict JSON")
269
+ .action(async (target, opts) => {
270
+ const args = ["fund", target];
271
+ if (opts.budget !== undefined)
272
+ args.push("--budget", String(opts.budget));
273
+ if (opts.out)
274
+ args.push("--out", opts.out);
275
+ if (opts.stateDir)
276
+ args.push("--state-dir", opts.stateDir);
277
+ // The rim owns the wall-clock: created_at is injected as an ISO string (like install's bound-at).
278
+ args.push("--created-at", new Date().toISOString());
279
+ if (opts.json)
280
+ args.push("--json");
281
+ const { status, stdout, stderr, envError } = runComposer(args);
282
+ if (envError) {
283
+ process.exitCode = 1;
284
+ return;
285
+ }
286
+ if (stdout)
287
+ process.stdout.write(stdout);
288
+ if (stderr)
289
+ process.stderr.write(stderr);
290
+ process.exitCode = status;
291
+ });
292
+ composer
293
+ .command("install <target>")
294
+ .description("Bind a staged unit onto THIS box: copy to a canonical hash dir, bind --wallet (or auto-bind a funded wallet.json), run `openclaw senpi runtime create`")
295
+ .option("--wallet <address>", "The strategy's ACTIVE 0x… wallet to bind (omit to auto-bind a funded wallet.json)")
296
+ .option("-o, --out <dir>", "Staging dir (when target is a graph file, not a staged dir)")
297
+ .option("--state-dir <dir>", "Base senpi-state dir (default: $SENPI_STATE_DIR or ~/.openclaw/senpi-state)")
298
+ .option("--runtime-id <id>", "Override the derived runtime id (default: <strategy>-<hash8>)")
299
+ .option("--json", "Print the raw Python install verdict JSON")
300
+ .action(async (target, opts) => {
301
+ const args = ["install", target];
302
+ if (opts.wallet)
303
+ args.push("--wallet", opts.wallet);
304
+ if (opts.out)
305
+ args.push("--out", opts.out);
306
+ if (opts.stateDir)
307
+ args.push("--state-dir", opts.stateDir);
308
+ if (opts.runtimeId)
309
+ args.push("--runtime-id", opts.runtimeId);
310
+ // Inject the wall-clock here (the rim owns the clock; the Python core stays deterministic).
311
+ args.push("--bound-at", new Date().toISOString());
312
+ if (opts.json)
313
+ args.push("--json");
314
+ const { status, stdout, stderr, envError } = runComposer(args);
315
+ if (envError) {
316
+ process.exitCode = 1;
317
+ return;
244
318
  }
319
+ if (stdout)
320
+ process.stdout.write(stdout);
321
+ if (stderr)
322
+ process.stderr.write(stderr);
323
+ process.exitCode = status;
324
+ });
325
+ composer
326
+ .command("close <target>")
327
+ .description("Safe teardown: stop the runtime, confirm gone, then trigger MCP strategy_close (flattens positions + returns funds). Idempotent — re-run to poll")
328
+ .option("--wallet <address>", "Close the strategy on this 0x… wallet directly")
329
+ .option("--strategy-id <id>", "Close this strategyId directly (legacy/ops-deployed strategies)")
330
+ .option("--state-dir <dir>", "Base senpi-state dir (default: $SENPI_STATE_DIR or ~/.openclaw/senpi-state)")
331
+ .option("--json", "Print the raw Python close verdict JSON")
332
+ .action(async (target, opts) => {
333
+ const args = ["close", target];
334
+ if (opts.wallet)
335
+ args.push("--wallet", opts.wallet);
336
+ if (opts.strategyId)
337
+ args.push("--strategy-id", opts.strategyId);
338
+ if (opts.stateDir)
339
+ args.push("--state-dir", opts.stateDir);
340
+ if (opts.json)
341
+ args.push("--json");
342
+ const { status, stdout, stderr, envError } = runComposer(args);
343
+ if (envError) {
344
+ process.exitCode = 1;
345
+ return;
346
+ }
347
+ if (stdout)
348
+ process.stdout.write(stdout);
349
+ if (stderr)
350
+ process.stderr.write(stderr);
245
351
  process.exitCode = status;
246
352
  });
247
353
  composer
248
354
  .command("status <target>")
249
355
  .description("Derived lifecycle position + the next verb to run (graph file or staging dir)")
250
356
  .option("-o, --out <dir>", "Staging directory to check for a deployed artifact")
357
+ .option("--state-dir <dir>", "Base senpi-state dir — extend status down the on-box install chain")
251
358
  .option("--json", "Print the raw Python status JSON")
252
359
  .action(async (target, opts) => {
253
360
  const args = ["status", target, "--json"];
254
361
  if (opts.out)
255
362
  args.push("--out", opts.out);
363
+ if (opts.stateDir)
364
+ args.push("--state-dir", opts.stateDir);
256
365
  const { status, stdout, json } = runComposer(args);
257
366
  if (opts.json || !json) {
258
367
  process.stdout.write(stdout);
@@ -1 +1 @@
1
- {"version":3,"file":"composer-commands.js","sourceRoot":"","sources":["../../src/cli/composer-commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"composer-commands.js","sourceRoot":"","sources":["../../src/cli/composer-commands.ts"],"names":[],"mappings":"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"}
@@ -46,10 +46,24 @@ async function main() {
46
46
 
47
47
  const imp = (rel) => import(pathToFileURL(pathJoin(distDir, rel)).href);
48
48
  let runtimeConfigSchema, parseDslPluginConfig, mapRuntimeExitToDslConfig, DslConfigValidationError;
49
+ // A3 (install-time parity): checks the runtime runs only when it actually boots — a
50
+ // runtime.yaml can pass the Zod schema + DSL preset parse yet still fail at install. Imported
51
+ // from dist alongside the existing three oracle objects so the same single source of truth
52
+ // (the runtime's own code) judges them. `validateDslPositionTracking` is Runtime.start()'s DSL
53
+ // wiring gate; `assertUnique*Names` + `assertActionPromptPlaceholdersResolvable` are
54
+ // loadRuntimeConfig's post-Zod asserts the rim otherwise skips (it avoids loadRuntimeConfig to
55
+ // keep structured errors). All throw plain Errors — caught below and mapped to distinct codes.
56
+ let validateDslPositionTracking,
57
+ assertActionPromptPlaceholdersResolvable,
58
+ assertUniqueScannerNames,
59
+ assertUniqueActionNames;
49
60
  try {
50
61
  ({ runtimeConfigSchema } = await imp("runtime/runtime-schema.js"));
51
62
  ({ parseDslPluginConfig, DslConfigValidationError } = await imp("dsl/config/index.js"));
52
63
  ({ mapRuntimeExitToDslConfig } = await imp("runtime/map-exit-config.js"));
64
+ ({ validateDslPositionTracking } = await imp("runtime/validate-dsl-position-tracking.js"));
65
+ ({ assertActionPromptPlaceholdersResolvable } = await imp("runtime/validate-action-prompts.js"));
66
+ ({ assertUniqueScannerNames, assertUniqueActionNames } = await imp("runtime/load-runtime-config.js"));
53
67
  } catch (err) {
54
68
  // Signal an ENV-absent condition distinctly so Python can skip (not RED) when dist is unbuilt.
55
69
  process.stdout.write(
@@ -117,6 +131,58 @@ async function main() {
117
131
  }
118
132
  }
119
133
 
134
+ // Third oracle layer (A3): install-time parity. The above proves the config PARSES; these
135
+ // reproduce the checks that only fire when the runtime BOOTS, so GREEN means "will install".
136
+ // Each new failure class carries a distinct machine `code` the Python CMP1xx mapper keys on.
137
+ // Collected together (not first-throw) so the author sees every install blocker at once.
138
+ const installErrors = [];
139
+
140
+ // load-time asserts loadRuntimeConfig runs post-Zod (the rim skips loadRuntimeConfig to keep
141
+ // structured errors, so it must re-run them here). Order matches load-runtime-config.ts.
142
+ try {
143
+ assertUniqueScannerNames(cfg);
144
+ } catch (err) {
145
+ installErrors.push({ path: "scanners", message: err?.message ?? String(err), code: "DUP_SCANNER_NAME" });
146
+ }
147
+ try {
148
+ assertUniqueActionNames(cfg);
149
+ } catch (err) {
150
+ installErrors.push({ path: "actions", message: err?.message ?? String(err), code: "DUP_ACTION_NAME" });
151
+ }
152
+ try {
153
+ assertActionPromptPlaceholdersResolvable(cfg);
154
+ } catch (err) {
155
+ installErrors.push({ path: "actions", message: err?.message ?? String(err), code: "UNRESOLVED_PROMPT_PLACEHOLDER" });
156
+ }
157
+
158
+ // DSL position-tracking wiring — the Runtime.start() gate (runtime.ts:452-457). hasDsl is
159
+ // derived exactly as the call site does: mapRuntimeExitToDslConfig(config.exit).dsl_preset
160
+ // present. The map call already succeeded in the DSL layer above whenever a dsl_preset exists;
161
+ // if it throws for a preset-less exit block, hasDsl is false (the gate is a no-op) — that class
162
+ // of error is surfaced by the schema/DSL layers, not misreported here.
163
+ try {
164
+ let hasDsl = false;
165
+ try {
166
+ const exitConfig = mapRuntimeExitToDslConfig(cfg.exit);
167
+ const dp = exitConfig?.dsl_preset;
168
+ hasDsl = dp != null && typeof dp === "object" && !Array.isArray(dp);
169
+ } catch {
170
+ hasDsl = false;
171
+ }
172
+ validateDslPositionTracking(cfg, hasDsl);
173
+ } catch (err) {
174
+ const message = err?.message ?? String(err);
175
+ // The single function throws one of three messages; the action-wiring ones point at actions.
176
+ const path = /action/i.test(message) ? "actions" : "scanners";
177
+ installErrors.push({ path, message, code: "DSL_POSITION_TRACKING" });
178
+ }
179
+
180
+ if (installErrors.length > 0) {
181
+ process.stdout.write(JSON.stringify({ ok: false, errors: installErrors }) + "\n");
182
+ process.exit(0);
183
+ return;
184
+ }
185
+
120
186
  process.stdout.write(JSON.stringify({ ok: true }) + "\n");
121
187
  process.exit(0);
122
188
  }
@@ -16,7 +16,16 @@ Public API:
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from .answers import Answers, Risk, Universe, load_answers, load_answers_file
19
+ from .answers import (
20
+ Answers,
21
+ ExitSignals,
22
+ Indicator,
23
+ Risk,
24
+ Scoring,
25
+ Universe,
26
+ load_answers,
27
+ load_answers_file,
28
+ )
20
29
  from .archetypes import ARCHETYPES, SKELETON
21
30
  from .gaps import Gap, GapReport, detect_gaps
22
31
  from .generate import NewResult, compose_new, render_graph
@@ -26,7 +35,10 @@ from .strategy_manifest import render_strategy_yaml
26
35
 
27
36
  __all__ = [
28
37
  "Answers",
38
+ "ExitSignals",
39
+ "Indicator",
29
40
  "Risk",
41
+ "Scoring",
30
42
  "Universe",
31
43
  "load_answers",
32
44
  "load_answers_file",
@@ -56,6 +56,29 @@ class Risk(BaseModel):
56
56
  max_consecutive_losses: Optional[int] = None # stop after N losses
57
57
  cooldown_seconds: Optional[int] = None # post-loss cooldown (>= 60)
58
58
  max_entries_per_day: Optional[int] = None # per-day entry cap (>= 1)
59
+ # post-close per-asset re-entry cooldown (guard_rails.per_asset_cooldown_seconds, floor 300);
60
+ # None -> preset default, OR (for a signal-exit pair) the exit_signals.reentry_cooldown_seconds
61
+ # default. An explicit value here ALWAYS wins (RISK_OVERRIDE_KEYS carries it into guard_rails).
62
+ per_asset_cooldown_seconds: Optional[int] = None
63
+
64
+
65
+ class ExitSignals(BaseModel):
66
+ """OPTIONAL thesis-exit knobs — the hysteresis dead band + post-close re-entry cooldown for a
67
+ signal-driven (thesis) exit (exit-composition slice). Absent (the default ``None`` on
68
+ :class:`Answers`) => byte-identical output EVERYWHERE (the hard regression constraint): no exit
69
+ scanner, no CLOSE_POSITION action, no per-asset cooldown guard rail. Present => the composer
70
+ additionally emits the exit scanner + CLOSE action pair and the per-asset cooldown (design §1.2).
71
+
72
+ ``interval_seconds`` is the exit scanner's poll cadence; ``enter_threshold`` / ``exit_threshold``
73
+ are the net-score hysteresis band the compiled predicate uses; ``reentry_cooldown_seconds`` is
74
+ the post-close per-asset re-entry cooldown (schema floor 300)."""
75
+
76
+ model_config = ConfigDict(extra="forbid")
77
+
78
+ interval_seconds: int = 300
79
+ enter_threshold: float = 3.0
80
+ exit_threshold: float = 2.0
81
+ reentry_cooldown_seconds: int = 1800
59
82
 
60
83
 
61
84
  class Universe(BaseModel):
@@ -80,6 +103,53 @@ class Universe(BaseModel):
80
103
  min_day_volume: float = 0.0
81
104
 
82
105
 
106
+ class Scoring(BaseModel):
107
+ """OPTIONAL re-selection of the scorer's hard gates / weighted contributors / floor (F1).
108
+
109
+ The scoring surface lets the answers move the hard-vs-weighted split AMONG the graph's
110
+ feature nodes without hand-editing the emitted graph. Every field is ``None`` = "keep the
111
+ archetype's working default"; a set field OVERRIDES it (D7 "answers override else current
112
+ defaults"). Names are SOURCE NODE IDS — the same keys the scorer merges its ``features`` by
113
+ (e.g. ``breakout_detect`` wired as ``brk`` is referenced as ``"brk"``). A name matching no
114
+ feature node in the graph is a generation error (``archetypes._common.resolve_scoring``),
115
+ never a silent drop. Absent entirely (the default), the emitted graph is byte-identical to
116
+ the pre-F1 output."""
117
+
118
+ model_config = ConfigDict(extra="forbid")
119
+
120
+ required_gates: Optional[tuple[str, ...]] = None # feature ids that must ALL be truthy
121
+ weights: Optional[dict[str, float]] = None # feature id -> weighted-sum weight
122
+ min_score: Optional[float] = None # minimum score to emit
123
+
124
+
125
+ class Indicator(BaseModel):
126
+ """An ADDITIONAL registry indicator node the answers ask the archetype to add and wire (F1).
127
+
128
+ Each entry adds a real registry node (``node``) under ``id``, feeds it the graph's candles,
129
+ and merges its feature output into the scorer's ``features`` — so the id becomes addressable
130
+ from :class:`Scoring` (as a gate or a weight). ``with`` carries the node's params; ``port``
131
+ names which output feeds the scorer (defaults to the node's sole output). A ``node`` the
132
+ registry lacks — or a ``port`` the node does not declare — is a generation error, never a
133
+ silent drop. This is how an answer requests, e.g., ``breakout_detect`` with ``window: 168``
134
+ on an archetype whose fixed indicator set does not already carry it.
135
+
136
+ ``source`` (optional, C1b) CHAINS this indicator's input off another feature node instead
137
+ of the graph's candles: when set, the node's data input wires from ``source``'s output
138
+ (``source`` names an EARLIER ``indicators`` entry's id or a built-in feature node of the
139
+ archetype), with the port types checked against the registry — a mismatch or an unknown
140
+ ``source`` is a generation error. This is what lets a ``threshold_gate`` read a raw
141
+ ``recent_high_bars_ago`` output (``fresh = threshold_gate(op: lte, value: 5, source:
142
+ fresh_raw)``) — a thresholded gate, not the inverted truthiness gate the raw feature had."""
143
+
144
+ model_config = ConfigDict(extra="forbid", populate_by_name=True)
145
+
146
+ id: str
147
+ node: str
148
+ with_: dict[str, Any] = Field(default_factory=dict, alias="with")
149
+ port: Optional[str] = None
150
+ source: Optional[str] = None
151
+
152
+
83
153
  class RequiredCapability(BaseModel):
84
154
  """A registry capability an answer says the strategy needs (D4 feasibility surface).
85
155
 
@@ -107,14 +177,26 @@ class Answers(BaseModel):
107
177
  intervals: tuple[str, ...] = ("4h",)
108
178
  max_positions: int = 1 # cardinality -> ranker choice (single-best vs pool-cap)
109
179
  ttl_seconds: int = 240 # memory -> ttl_dedup_state dedup window
110
- # LIVE: emitted as the runtime.yaml exit: section. Default None = "unset"; `composer new`
111
- # BINDS protected_standard unless overridden (protection-by-default). A graph reaching
112
- # `check` with exit_preset unset AND unmanaged False is the RED CMP120 contradiction.
180
+ # LIVE: emitted as the runtime.yaml exit: section. Default None = "unset" (unset-vs-explicit
181
+ # semantics): `composer new` RESOLVES an unset preset at build time — protected_standard when
182
+ # there is no exit_signals (today's default, byte-identical), protected_wide when exit_signals
183
+ # is present (the DSL demotes to a WIDE safety net so it never front-runs the thesis exit). An
184
+ # EXPLICIT value ALWAYS wins. A graph reaching `check` with exit_preset unset AND unmanaged
185
+ # False is the RED CMP120 contradiction.
113
186
  exit_preset: Optional[str] = None
114
187
  unmanaged: bool = False # explicit opt-out: no exit section (else CMP120 RED at check)
115
188
  risk: Risk = Field(default_factory=Risk)
116
189
  edge: str = "" # the user's EDGE, verbatim; the machine never interprets it
117
190
  requires: tuple[RequiredCapability, ...] = ()
191
+ # F1 — OPTIONAL expressiveness surface. Absent (the defaults below) => byte-identical to
192
+ # the pre-F1 output; present => the archetype re-selects gates/weights (scoring) and adds
193
+ # registry indicator nodes (indicators) mechanically, no hand edit. See the two submodels.
194
+ scoring: Optional[Scoring] = None
195
+ indicators: tuple[Indicator, ...] = ()
196
+ # exit-composition — OPTIONAL thesis-exit surface. Absent (None) => byte-identical to today
197
+ # (no exit scanner / CLOSE action / per-asset cooldown). Present => the composer emits the
198
+ # entry/exit scanner pair. See :class:`ExitSignals` and the PRESET POLICY on exit_preset.
199
+ exit_signals: Optional[ExitSignals] = None
118
200
 
119
201
  @field_validator("exit_preset")
120
202
  @classmethod
@@ -149,7 +231,7 @@ class Answers(BaseModel):
149
231
  def metadata_block(self) -> dict:
150
232
  """The answers as an ordered plain-dict for the emitted graph's metadata (D7:
151
233
  the spec file IS the state; interview answers live in the metadata block)."""
152
- return {
234
+ block: dict = {
153
235
  "archetype": self.archetype,
154
236
  "strategy": self.strategy,
155
237
  "universe": {
@@ -180,6 +262,39 @@ class Answers(BaseModel):
180
262
  {"name": c.name, "kind": c.kind, "need": c.need} for c in self.requires
181
263
  ],
182
264
  }
265
+ # per_asset_cooldown_seconds joins the risk block ONLY when set — the sibling knobs above
266
+ # always emit (None -> null), but this one is exit-composition-era and must stay ABSENT for
267
+ # exit-less answers to keep the metadata byte-identical (round-trips via Answers(**block)).
268
+ if self.risk.per_asset_cooldown_seconds is not None:
269
+ block["risk"]["per_asset_cooldown_seconds"] = self.risk.per_asset_cooldown_seconds
270
+ # F1: emit the optional surface ONLY when set, so answers without it round-trip
271
+ # byte-identically to the pre-F1 metadata block (the HARD regression constraint).
272
+ # Both survive `Answers(**block)` deterministically (the deploy metadata re-derive path).
273
+ if self.scoring is not None:
274
+ scoring: dict = {}
275
+ if self.scoring.required_gates is not None:
276
+ scoring["required_gates"] = list(self.scoring.required_gates)
277
+ if self.scoring.weights is not None:
278
+ scoring["weights"] = dict(self.scoring.weights)
279
+ if self.scoring.min_score is not None:
280
+ scoring["min_score"] = self.scoring.min_score
281
+ block["scoring"] = scoring
282
+ if self.indicators:
283
+ block["indicators"] = [
284
+ {"id": i.id, "node": i.node, "with": dict(i.with_), "port": i.port,
285
+ "source": i.source}
286
+ for i in self.indicators
287
+ ]
288
+ # exit-composition: the thesis-exit knobs, emitted ONLY when set (same F1 discipline) so
289
+ # exit-less answers round-trip byte-identically. Survives Answers(**block) as ExitSignals.
290
+ if self.exit_signals is not None:
291
+ block["exit_signals"] = {
292
+ "interval_seconds": self.exit_signals.interval_seconds,
293
+ "enter_threshold": self.exit_signals.enter_threshold,
294
+ "exit_threshold": self.exit_signals.exit_threshold,
295
+ "reentry_cooldown_seconds": self.exit_signals.reentry_cooldown_seconds,
296
+ }
297
+ return block
183
298
 
184
299
 
185
300
  def _deep_merge(base: dict, over: dict) -> dict:
@@ -2,24 +2,42 @@
2
2
 
3
3
  Each archetype is CODE that builds a graph from the same registry types (see
4
4
  ``composer.authoring.builder``), so a template that names a nonexistent node/port fails at
5
- construction — the CI guarantee that templates cannot drift from the vocabulary. Only the
6
- archetypes the POC graphs need are here (trend_momentum / classifier / thesis_fund); an
7
- unrecognised archetype falls to the minimal ``skeleton`` (D7 step 5), which is NOT in
8
- ``ARCHETYPES`` because "no matching archetype" is its trigger.
5
+ construction — the CI guarantee that templates cannot drift from the vocabulary. The
6
+ archetypes the POC graphs need are here (trend_momentum / breakout / classifier /
7
+ thesis_fund); an unrecognised archetype falls to the minimal ``skeleton`` (D7 step 5), which
8
+ is NOT in ``ARCHETYPES`` because "no matching archetype" is its trigger.
9
9
 
10
10
  Each module exposes ``build(answers) -> GraphBuilder`` and a ``BANNER`` header.
11
11
  """
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
- from . import classifier, skeleton, thesis_fund, trend_momentum
15
+ from . import breakout, classifier, relative_value, skeleton, thesis_fund, trend_momentum
16
16
 
17
17
  ARCHETYPES = {
18
18
  "trend_momentum": trend_momentum,
19
+ "breakout": breakout,
19
20
  "classifier": classifier,
20
21
  "thesis_fund": thesis_fund,
22
+ "relative_value": relative_value,
21
23
  }
22
24
 
23
25
  SKELETON = skeleton
24
26
 
25
- __all__ = ["ARCHETYPES", "SKELETON"]
27
+
28
+ def archetype_names() -> list[str]:
29
+ """The recognised archetype names (a `describe <archetype>` namespace)."""
30
+ return sorted(ARCHETYPES)
31
+
32
+
33
+ def render_describe_archetype(name: str) -> str | None:
34
+ """The describe reference for ONE archetype (its ``DESCRIBE`` block — the single home for
35
+ the archetype's shape), or None if the name is not a recognised archetype. The skeleton
36
+ fallback is deliberately excluded: "no matching archetype" is its trigger, not a name."""
37
+ module = ARCHETYPES.get(name)
38
+ if module is None:
39
+ return None
40
+ return "\n".join(module.DESCRIBE) + "\n"
41
+
42
+
43
+ __all__ = ["ARCHETYPES", "SKELETON", "archetype_names", "render_describe_archetype"]