@exellix/graph-composer 2.0.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 (103) hide show
  1. package/.env.example +66 -0
  2. package/LICENSE +21 -0
  3. package/README.md +329 -0
  4. package/dist/aiTaskProfile.d.ts +66 -0
  5. package/dist/aiTaskProfile.d.ts.map +1 -0
  6. package/dist/aiTaskProfile.js +179 -0
  7. package/dist/canonicalGraphDocument.d.ts +8 -0
  8. package/dist/canonicalGraphDocument.d.ts.map +1 -0
  9. package/dist/canonicalGraphDocument.js +344 -0
  10. package/dist/canonicalGraphWarnings.d.ts +6 -0
  11. package/dist/canonicalGraphWarnings.d.ts.map +1 -0
  12. package/dist/canonicalGraphWarnings.js +140 -0
  13. package/dist/catalogMatchAssist.d.ts +20 -0
  14. package/dist/catalogMatchAssist.d.ts.map +1 -0
  15. package/dist/catalogMatchAssist.js +203 -0
  16. package/dist/cataloxCatalogBridge.d.ts +103 -0
  17. package/dist/cataloxCatalogBridge.d.ts.map +1 -0
  18. package/dist/cataloxCatalogBridge.js +222 -0
  19. package/dist/cli.d.ts +3 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +43 -0
  22. package/dist/composeInstructions.d.ts +11 -0
  23. package/dist/composeInstructions.d.ts.map +1 -0
  24. package/dist/composeInstructions.js +39 -0
  25. package/dist/defaultUtilitySkills.d.ts +4 -0
  26. package/dist/defaultUtilitySkills.d.ts.map +1 -0
  27. package/dist/defaultUtilitySkills.js +5 -0
  28. package/dist/exampleGeneration.d.ts +15 -0
  29. package/dist/exampleGeneration.d.ts.map +1 -0
  30. package/dist/exampleGeneration.js +72 -0
  31. package/dist/exampleInputs.d.ts +12 -0
  32. package/dist/exampleInputs.d.ts.map +1 -0
  33. package/dist/exampleInputs.js +181 -0
  34. package/dist/graphComposerActions.d.ts +22 -0
  35. package/dist/graphComposerActions.d.ts.map +1 -0
  36. package/dist/graphComposerActions.js +168 -0
  37. package/dist/graphComposerAgent.d.ts +26 -0
  38. package/dist/graphComposerAgent.d.ts.map +1 -0
  39. package/dist/graphComposerAgent.js +175 -0
  40. package/dist/graphComposerOutputValidation.d.ts +23 -0
  41. package/dist/graphComposerOutputValidation.d.ts.map +1 -0
  42. package/dist/graphComposerOutputValidation.js +709 -0
  43. package/dist/graphConceptPatchMerge.d.ts +10 -0
  44. package/dist/graphConceptPatchMerge.d.ts.map +1 -0
  45. package/dist/graphConceptPatchMerge.js +40 -0
  46. package/dist/graphEngineBridge.d.ts +7 -0
  47. package/dist/graphEngineBridge.d.ts.map +1 -0
  48. package/dist/graphEngineBridge.js +5 -0
  49. package/dist/index.d.ts +24 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +19 -0
  52. package/dist/openRouterConnectTimeout.d.ts +3 -0
  53. package/dist/openRouterConnectTimeout.d.ts.map +1 -0
  54. package/dist/openRouterConnectTimeout.js +48 -0
  55. package/dist/packDir.d.ts +7 -0
  56. package/dist/packDir.d.ts.map +1 -0
  57. package/dist/packDir.js +23 -0
  58. package/dist/parseGraphConceptStory.d.ts +21 -0
  59. package/dist/parseGraphConceptStory.d.ts.map +1 -0
  60. package/dist/parseGraphConceptStory.js +105 -0
  61. package/dist/redactForLog.d.ts +2 -0
  62. package/dist/redactForLog.d.ts.map +1 -0
  63. package/dist/redactForLog.js +37 -0
  64. package/dist/runGraphComposer.d.ts +54 -0
  65. package/dist/runGraphComposer.d.ts.map +1 -0
  66. package/dist/runGraphComposer.js +444 -0
  67. package/dist/scopingCatalogHostTypes.d.ts +28 -0
  68. package/dist/scopingCatalogHostTypes.d.ts.map +1 -0
  69. package/dist/scopingCatalogHostTypes.js +6 -0
  70. package/dist/scopingNeedMatchAssist.d.ts +14 -0
  71. package/dist/scopingNeedMatchAssist.d.ts.map +1 -0
  72. package/dist/scopingNeedMatchAssist.js +58 -0
  73. package/dist/taskNodeTaskVariable.d.ts +44 -0
  74. package/dist/taskNodeTaskVariable.d.ts.map +1 -0
  75. package/dist/taskNodeTaskVariable.js +347 -0
  76. package/dist/types.d.ts +174 -0
  77. package/dist/types.d.ts.map +1 -0
  78. package/dist/types.js +1 -0
  79. package/examples/network-vuln-subnet-triage.v2.json +389 -0
  80. package/functions/graph-composer/meta.json +607 -0
  81. package/functions/graph-composer/prompts/README.md +46 -0
  82. package/functions/graph-composer/prompts/action-create.md +51 -0
  83. package/functions/graph-composer/prompts/action-explain.md +26 -0
  84. package/functions/graph-composer/prompts/action-modify.md +32 -0
  85. package/functions/graph-composer/prompts/action-review-concept.md +97 -0
  86. package/functions/graph-composer/prompts/action-suggest-catalog-creations.md +31 -0
  87. package/functions/graph-composer/prompts/action-suggest-catalog-resolution.md +42 -0
  88. package/functions/graph-composer/prompts/action-suggest-concept-objective.md +38 -0
  89. package/functions/graph-composer/prompts/action-suggest-scoping-map-creation.md +31 -0
  90. package/functions/graph-composer/prompts/action-suggest-scoping-need-match.md +25 -0
  91. package/functions/graph-composer/prompts/default-utility-skills.json +22 -0
  92. package/functions/graph-composer/prompts/judge-rules.md +30 -0
  93. package/functions/graph-composer/prompts/orchestrator-system.md +21 -0
  94. package/functions/graph-composer/prompts/shared/graph-format.md +124 -0
  95. package/functions/graph-composer/prompts/shared/request-context.md +12 -0
  96. package/functions/graph-composer/prompts/shared/skill-selection.md +6 -0
  97. package/functions/graph-composer/prompts/shared/structural-validation.md +19 -0
  98. package/functions/graph-composer/prompts/skill-catalog-ai-header.md +3 -0
  99. package/functions/graph-composer/prompts/skill-catalog-utility-header.md +3 -0
  100. package/functions/graph-composer/prompts/skill-mode-extensible.md +7 -0
  101. package/functions/graph-composer/prompts/skill-mode-locked.md +7 -0
  102. package/functions/graph-composer/test-cases.json +52 -0
  103. package/package.json +86 -0
package/.env.example ADDED
@@ -0,0 +1,66 @@
1
+ # Copy to .env for local development (never commit .env).
2
+
3
+ # Required — OpenRouter API key (used by @x12i/funcx for runGraphComposer).
4
+ OPENROUTER_API_KEY=
5
+
6
+ # Optional — override default models (OpenRouter slugs, e.g. openai/gpt-4o).
7
+ # See @x12i/funcx README for presets.
8
+ # LLM_MODEL_STRONG=
9
+ # LLM_MODEL_NORMAL=
10
+
11
+ # Optional — @x12i/logxer: package log level (verbose|debug|info|warn|error|off).
12
+ # GRAPH_COMPOSER_LOGS_LEVEL=info
13
+ #
14
+ # Optional — Mongo log sink (see @x12i/logxer). Loaded via @x12i/env before Logxer is constructed.
15
+ # MONGO_URI=
16
+ # Mongo persistence defaults to warn; set info (or lower) to persist info-level package logs:
17
+ # logxer_mongo_db_logs_level=info
18
+
19
+ # --- Catalox + Firebase Admin (loadCatalogCandidatesFromCatalox / verify:catalog-live) ---
20
+ # Mental model: every Catalox call needs CataloxContext.appId matching bindings for that catalog.
21
+ # See docs/catalox-multi-app-context.md
22
+ #
23
+ # GCP project (required for verify:catalog-live):
24
+ # FIREBASE_PROJECT_ID=
25
+ # (or GOOGLE_CLOUD_PROJECT / GCLOUD_PROJECT)
26
+ #
27
+ # Credentials — pick one (peer-style):
28
+ # FIREBASE_SERVICE_ACCOUNT_PATH=/path/to/service-account.json
29
+ # GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
30
+ # GOOGLE_SERVICE_ACCOUNT_BASE64= # or FIREBASE_SERVICE_ACCOUNT_BASE64= (JSON base64)
31
+ #
32
+ # Optional Catalox context app id (caller / BFF). With @x12i/catalox >= 3.4.6, appId can be omitted for catalog-id-first + superAdmin verify runs:
33
+ # CATALOX_APP_ID=
34
+ # Optional Catalox context fields:
35
+ # CATALOX_STORE_ID=
36
+ # CATALOX_USER_ID=
37
+ # verify:catalog-live defaults CataloxContext.superAdmin=true (no pins needed). Opt out:
38
+ # CATALOX_VERIFY_SUPER_ADMIN=0
39
+ # (or CATALOX_GOD_MODE=0). To force superAdmin in other tooling, CATALOX_GOD_MODE=1 still works.
40
+ #
41
+ # Multi-app: owning appId per catalog family (verify script + loadCatalogCandidatesFromCatalox contextByBridgeKey):
42
+ # GC_VERIFY_CATALOX_APP_AI_SKILLS=ai-skills
43
+ # GC_VERIFY_CATALOX_APP_AI_TASKS=ai-tasks
44
+ # GC_VERIFY_CATALOX_APP_INPUT_SYNTHESIS=ai-tasks # optional; overrides appId for inputSynthesisModes only
45
+ # GC_VERIFY_CATALOX_APP_NARRIX=narrix
46
+ # GC_VERIFY_CATALOX_APP_XMEMORY=xmemory
47
+ # GC_VERIFY_CATALOX_APP_UTILITY=
48
+ #
49
+ # Firestore catalog document ids (defaults in verify script match docs/catalog-metadb-end-state-contract.md):
50
+ # GC_VERIFY_CATALOG_AI_SKILLS=ai-skills
51
+ # GC_VERIFY_CATALOG_PRE=ai-task-strategies-pre
52
+ # GC_VERIFY_CATALOG_POST=ai-task-strategies-post
53
+ # GC_VERIFY_CATALOG_INPUT_SYNTHESIS_MODES= # set only if this Firestore catalog exists (no default in verify script)
54
+ # GC_VERIFY_CATALOG_UTILITY_SKILLS=
55
+ # GC_VERIFY_CATALOG_SCOPING_MAPS=
56
+ # GC_VERIFY_CATALOG_XMEMORY_SCOPING=xmemory.scopingQuestions
57
+ # GC_VERIFY_CATALOG_XMEMORY_ENTITIES=xmemory.entity-collections
58
+ # GC_VERIFY_CATALOG_NARRIX_TEMPLATES=
59
+ # GC_VERIFY_CATALOG_NARRATIVES=narratives
60
+ # Optional: comma-separated merged skillKey strings that must exist after the bridge:
61
+ # GC_VERIFY_EXPECT_MERGED_SKILL_KEYS=professional-answer,structured-job-context-v1
62
+ #
63
+ # Catalox optional record-history (see @x12i/catalox README / environment docs):
64
+ # CATALOX_RECORD_HISTORY_BUCKET=
65
+ # CATALOX_RECORD_HISTORY_PREFIX=
66
+ # CATALOX_RECORD_HISTORY_FAIL_CLOSED=
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Woreces
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,329 @@
1
+ # @x12i/graph-composer
2
+
3
+ | | Location |
4
+ |---|----------|
5
+ | **GitHub (source)** | [`woroces/graph-composer`](https://github.com/woroces/graph-composer) — clone: `git@github.com:woroces/graph-composer.git` |
6
+ | **npm (package)** | [`@x12i/graph-composer`](https://www.npmjs.com/package/@x12i/graph-composer) |
7
+
8
+ The Git repo lives under the **woroces** org with repo name **graph-composer**. That is separate from the npm scope **@x12i**.
9
+
10
+ LLM-backed **graph composer** for the **worox-graph** DAG format using [@x12i/funcx](https://www.npmjs.com/package/@x12i/funcx) and OpenRouter.
11
+
12
+ **Graph structure:** **create**, **modify**, **explain**. **Product metadata:** **suggestConceptObjective** (`metadata.graphConcept`). **Concept QA:** **reviewConcept** (verdict + findings, no graph rewrite). **Managed catalogs (Catalox-backed rows → planning JSON only — host applies CRUD):** **suggestCatalogResolution**, **suggestCatalogCreations**. **Scoping-only:** **suggestScopingNeedMatch** (natural-language need vs `catalogCandidates.scopingMaps`), **suggestScopingMapCreation** (`scopingMapProposal` + `catalogRequestProposals`).
13
+
14
+ ## Architecture (two ways to run)
15
+
16
+ 1. **Direct workers (`runGraphComposer`)** — You set `intent.action`. Each action uses a **dedicated** system prompt (shared worox-graph fragments + one `action-*.md` file) plus the same skill catalogs and skill-mode gate as before. All graph-scoped actions are registered in [`src/graphComposerActions.ts`](./src/graphComposerActions.ts); adding an action means extending that registry and adding prompt files (see [`functions/graph-composer/prompts/README.md`](./functions/graph-composer/prompts/README.md)).
17
+
18
+ 2. **Orchestrator (`runGraphComposerAgent`)** — You pass a natural-language **`goal`**. The orchestrator uses **`runJsonCompletion`** (structured JSON steps) to choose **registered tools**, then runs each selection via the **same** `runGraphWorker` path as direct mode. This costs **more tokens and latency** (multiple LLM rounds) than a single direct call.
19
+
20
+ Registered tool ids (mirror `GRAPH_COMPOSER_ACTION_REGISTRY`): `graph_create`, `graph_modify`, `graph_explain`, `graph_suggest_concept_objective`, `graph_suggest_catalog_resolution`, `graph_suggest_catalog_creations`, `graph_suggest_scoping_need_match`, `graph_suggest_scoping_map_creation`, `graph_review_concept`.
21
+
22
+ Pass **`catalogCandidates`** on `GraphComposerAgentInput` when the goal involves catalog or scoping tools (host loads rows from **Catalox** via `loadCatalogCandidatesFromCatalox`, or supplies fixtures).
23
+
24
+ Upstream feature request for first-class tool loops / worker profiles in aifunctions-js: [docs/aifunctions-agent-toolbox-feature-request.md](./docs/aifunctions-agent-toolbox-feature-request.md).
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ npm install @x12i/graph-composer
30
+ ```
31
+
32
+ Requires **Node.js 20+** (Catalox embedder and this package align on `>=20`).
33
+
34
+ ## Environment
35
+
36
+ | Variable | Required | Description |
37
+ |----------|----------|-------------|
38
+ | `OPENROUTER_API_KEY` | **Yes** (for API runs) | OpenRouter API key. |
39
+ | `LLM_MODEL_STRONG` | No | Model slug when using `mode: "strong"` (default preset from @x12i/funcx). |
40
+ | `LLM_MODEL_NORMAL` | No | Model slug for `normal` mode. |
41
+ | `GRAPH_COMPOSER_LOGS_LEVEL` | No | Log level for [@x12i/logxer](https://www.npmjs.com/package/@x12i/logxer) (`info`, `warn`, …). |
42
+
43
+ Copy [`.env.example`](./.env.example) to `.env` for local development. **Do not commit secrets.**
44
+
45
+ ## Quick start (direct worker)
46
+
47
+ ```ts
48
+ import { runGraphComposer } from "@x12i/graph-composer";
49
+
50
+ const result = await runGraphComposer(
51
+ {
52
+ intent: {
53
+ action: "create",
54
+ description: "Read a record, classify it, persist the result.",
55
+ },
56
+ skillMode: "locked",
57
+ aiSkills: [
58
+ {
59
+ skillKey: "professional-answer",
60
+ description: "Structured analysis with LLM",
61
+ isLocal: false,
62
+ },
63
+ ],
64
+ utilitySkills: [
65
+ {
66
+ skillKey: "scoped-data-reader",
67
+ description: "Read scoped data",
68
+ isLocal: true,
69
+ },
70
+ {
71
+ skillKey: "scoped-answer-writer",
72
+ description: "Persist results",
73
+ isLocal: true,
74
+ },
75
+ ],
76
+ constraints: { requireFinalizer: true },
77
+ },
78
+ {
79
+ askTimeoutMs: 120_000,
80
+ connectTimeoutMs: 60_000,
81
+ maxTokens: 8192,
82
+ }
83
+ );
84
+ ```
85
+
86
+ ### Orchestrator (toolbox)
87
+
88
+ ```ts
89
+ import { runGraphComposerAgent } from "@x12i/graph-composer";
90
+
91
+ const out = await runGraphComposerAgent(
92
+ {
93
+ goal:
94
+ "Explain the attached graph for operators: summary, execution order, data flow.",
95
+ existingGraph: myGraphJson,
96
+ skillMode: "locked",
97
+ aiSkills: [...],
98
+ utilitySkills: [...],
99
+ },
100
+ {
101
+ askTimeoutMs: 120_000,
102
+ connectTimeoutMs: 60_000,
103
+ maxTokens: 8192,
104
+ maxOrchestratorSteps: 8,
105
+ }
106
+ );
107
+ // out.orchestration.summary — orchestrator narrative
108
+ // out.orchestration.steps — which tools ran
109
+ // out.result — last worker JSON (e.g. explain payload)
110
+ ```
111
+
112
+ `runGraphComposerAgent` uses the same OpenRouter client resolution as workers; pass **`options.model`** if you need an explicit model for orchestrator JSON steps (see aifunctions-js `runJsonCompletion`).
113
+
114
+ ### Explain an existing graph
115
+
116
+ Pass `existingGraph` (worox-graph JSON) and `intent.action: "explain"`.
117
+
118
+ ### Suggest primary intent (`suggestConceptObjective`)
119
+
120
+ **Generic API (any graph):** set `intent.action: "suggestConceptObjective"`, **`existingGraph`** (required), optional **`analysisContext`**, and the usual skill / constraint fields. This is **not** tied to a specific domain or subnet.
121
+
122
+ **Bundled sample graph (legacy fixture):** `inputSuggestConceptObjectiveNetworkVulnSubnet()` and the JSON under `examples/` are **non-normative** test/demo payloads — not catalog ids, not a product-specific API surface. Prefer your own graphs and Catalox-backed `catalogCandidates` in production.
123
+
124
+ Optional **`intent.onlyIfEmpty`**: array of patch field names (`primaryIntentType`, `primaryIntentStatement`, `businessObjective`, `primaryOutcome`). The runtime **drops** any listed key from the model’s `graphConceptPatch` when `existingGraph.metadata.graphConcept.<key>` is already a non-empty string, and appends a short note to `rationale` when something was skipped.
125
+
126
+ **Stable result shape** (top-level, in addition to `action`):
127
+
128
+ ```json
129
+ {
130
+ "action": "suggestConceptObjective",
131
+ "graphConceptPatch": {
132
+ "primaryIntentType": "objective",
133
+ "primaryIntentStatement": "One or two product-facing sentences describing what this graph achieves for the user.",
134
+ "businessObjective": "",
135
+ "primaryOutcome": ""
136
+ },
137
+ "rationale": "Optional short note for UI or logs."
138
+ }
139
+ ```
140
+
141
+ `primaryIntentType` is one of: `question`, `decision`, `action`, `objective` (same vocabulary as playground `INTENT_TYPE_OPTIONS`). Apply the patch in the consumer with a shallow merge into `metadata.graphConcept`, e.g. `{ ...existing, ...graphConceptPatch }`.
142
+
143
+ Types: `GraphConceptPatch`, `GraphConceptPatchKey`, `PrimaryIntentType`. Helper: `applyGraphConceptPatchOnlyIfEmpty()` (same merge rule the runtime uses after the LLM returns).
144
+
145
+ **Example using the bundled fixture helper:**
146
+
147
+ ```ts
148
+ import { runGraphComposer, inputSuggestConceptObjectiveNetworkVulnSubnet } from "@x12i/graph-composer";
149
+
150
+ const result = await runGraphComposer(inputSuggestConceptObjectiveNetworkVulnSubnet(), {
151
+ askTimeoutMs: 120_000,
152
+ connectTimeoutMs: 60_000,
153
+ maxTokens: 4096,
154
+ });
155
+ ```
156
+
157
+ ### Review concept (`reviewConcept`)
158
+
159
+ **Requires** `existingGraph`. Returns **`verdict`** (`coherent`, `summary`) and **`findings`** (category, severity, summary, optional **`taskIndex`**, **`proposal`**, `nodeIds`, `suggestedChange`). When **`metadata.graphConcept.coreTasks`** is non-empty, the model should return **`graphConceptPatch`** or **`suggestedConceptPatch`** (same partial shape; prefer one) with **`coreTasks`** index-aligned to that array and partial **`requirements`** (`skill`, `catalogBinding`, `narrix`, `memoryIO`, optional **`webScoping`**, etc.) inferred from the graph and catalogs. When a single value cannot be chosen, the model may return **`requirementOptions`** (ranked **`candidates`** per `taskIndex` + dot-path **`field`**, plus **`needsNewArtifact`**). Optional extended string fields on the patch (e.g. `expectedInput`, `outputDescription`) and optional **`catalogProposals`** for catalog gaps. No `graph`, `changelog`, or `explanation`. Use for design review before heavy edits.
160
+
161
+ **Tracing:** For `reviewConcept` only, `runGraphWorker` logs a **redacted** JSON snapshot of the serialized worker request and the **raw LLM worker response** (@x12i/funcx function-pack invocation): at **`debug`** by default (set `GRAPH_COMPOSER_LOGS_LEVEL=debug`), or at **`info`** when **`traceReviewConceptIo: true`** is passed in `RunGraphComposerOptions`. Payloads are capped (~500k chars) and keys matching secrets (`apiKey`, `password`, `token`, etc.) are replaced with `[redacted]`.
162
+
163
+ ### Generate example input
164
+
165
+ Use `generateGraphJsonInputExample` when a host has a graph-specific expected input JSON Schema and wants a realistic smoke-test payload. It wraps Funcx `generateJsonExample`, adding graph metadata such as `metadata.graphConcept.expectedInput` and core tasks to the guidance.
166
+
167
+ ```ts
168
+ import { generateGraphJsonInputExample } from "@x12i/graph-composer";
169
+
170
+ const out = await generateGraphJsonInputExample({
171
+ existingGraph: myGraphJson,
172
+ jsonSchema: graphExpectedInputSchema,
173
+ guidance: ["Use fake subnet and CVE values.", "Keep the payload minimal."],
174
+ examples: previousGoodInputs,
175
+ timeoutMs: 120_000,
176
+ });
177
+ ```
178
+
179
+ The package also re-exports Funcx `generateJsonExample`, `generateMdExample`, and `generateContentExample` for non-graph-specific examples.
180
+
181
+ ### Catalog resolution & creation (`suggestCatalogResolution`, `suggestCatalogCreations`)
182
+
183
+ Both **require** `existingGraph`. Pass **`catalogCandidates`** (from **Catalox** via `loadCatalogCandidatesFromCatalox`, or fixtures): `aiSkills`, `utilitySkills`, `scopingMaps`, `narrixTemplates` — see [`docs/worox-graphs-catalogs.md`](./docs/worox-graphs-catalogs.md) and [`docs/catalog-metadb-end-state-contract.md`](./docs/catalog-metadb-end-state-contract.md) (**Catalox bridge + `catalogCandidates` as documented there: `@x12i/graph-composer` ≥ 1.6.0**).
184
+
185
+ - **`suggestCatalogResolution`** — Per-node style recommendations: `skillResolution`, `scopingResolution`, `narrixResolution`, `gaps`. Optional **`matchLists`** pre-pass (skills / scoping / narrix) injects **`catalogMatchHints`** into the worker prompt when `catalogMatchListsAssist !== false` (default) and an OpenRouter **client** is available.
186
+ - **`suggestCatalogCreations`** — `catalogRequestProposals` (+ optional `newSkillDescriptors`). Host applies approved rows via **Catalox** (or your store); this package emits JSON only.
187
+
188
+ ### Scoping need match & scoping map creation
189
+
190
+ - **`suggestScopingNeedMatch`** — **Does not** require `existingGraph` (optional context). **Requires** non-empty **`catalogCandidates.scopingMaps`**. Put the data need in **`intent.description`**. Output: **`hasSuitableMatch`**, **`recommended`** (`scopingMapId` / `questionId` when true, **`null` when false**), **`gaps`**, optional **`alternatives`**. Optional **`matchLists`** injects **`scopingNeedMatchHints`** (same client / `catalogMatchListsAssist` flag).
191
+ - **`suggestScopingMapCreation`** — Plan a new scoping map: **`scopingMapProposal`** + non-empty **`catalogRequestProposals`**. Host persists approved artifacts; see **`WoroxScopingMapCatalogCreatePayload`** exported from **`@x12i/graph-composer`** (authored as `src/scopingCatalogHostTypes.ts` in this repo).
192
+
193
+ ### `RunGraphComposerOptions` (workers)
194
+
195
+ In addition to `client`, `mode`, `model`, `temperature`, `maxTokens`, `askTimeoutMs`, `connectTimeoutMs`:
196
+
197
+ - **`catalogMatchListsAssist`** — When not `false`, enables **`matchLists`** pre-passes for `suggestCatalogResolution`, `suggestCatalogCreations`, and **`suggestScopingNeedMatch`** when a client is resolved (skips if no client).
198
+ - **`traceReviewConceptIo`** — When `true`, emit **`reviewConcept`** request/response trace logs at **`info`** (still redacted). When `false` (default), the same traces use **`debug`** only.
199
+
200
+ ### Worker actions cheat sheet
201
+
202
+ | `intent.action` | `existingGraph` | Notes |
203
+ |-----------------|-----------------|--------|
204
+ | `create` | No | Full graph + changelog |
205
+ | `modify` | **Yes** | Patched graph + changelog |
206
+ | `explain` | **Yes** | `explanation` object only |
207
+ | `suggestConceptObjective` | **Yes** | `graphConceptPatch` |
208
+ | `reviewConcept` | **Yes** | `verdict` + `findings`; optional patch + `requirementOptions` / `catalogProposals` |
209
+ | `suggestCatalogResolution` | **Yes** | Pass `catalogCandidates`; optional `catalogMatchHints` injection |
210
+ | `suggestCatalogCreations` | **Yes** | `catalogRequestProposals` |
211
+ | `suggestScopingNeedMatch` | No* | *Optional; **requires** non-empty `catalogCandidates.scopingMaps` |
212
+ | `suggestScopingMapCreation` | No* | *Optional; `scopingMapProposal` + `catalogRequestProposals` |
213
+
214
+ Authoritative JSON shapes: [`functions/graph-composer/meta.json`](./functions/graph-composer/meta.json).
215
+
216
+ ### CLI (after install)
217
+
218
+ **Core usage:** pass a **`test-cases.json`** id (e.g. `explain-basic`, `create-simple-linear`) — these map to the pack’s machine fixtures.
219
+
220
+ **Demo / smoke only (not the core API surface):**
221
+
222
+ - `network-vuln` — runs **explain** on the bundled subnet triage sample graph.
223
+ - `network-vuln-intent` — runs **`suggestConceptObjective`** on the same sample graph.
224
+
225
+ ```bash
226
+ export OPENROUTER_API_KEY=sk-or-...
227
+ npx @x12i/graph-composer explain-basic
228
+ npx @x12i/graph-composer network-vuln
229
+ ```
230
+
231
+ Or use the binary name:
232
+
233
+ ```bash
234
+ graph-composer explain-basic
235
+ ```
236
+
237
+ ## API highlights
238
+
239
+ | Export | Purpose |
240
+ |--------|---------|
241
+ | `runGraphComposer(input, options?)` | Direct worker for `intent.action`. |
242
+ | `runGraphComposerAgent(input, options?)` | Orchestrator + toolbox (multi-step JSON). |
243
+ | `runGraphWorker` | Same LLM path as `runGraphComposer` (used internally and for advanced composition). |
244
+ | `getGraphComposerLlmClient` | Always returns an OpenRouter `Client` (orchestrator / custom `ask` use). |
245
+ | `resolveGraphComposerClient` | Optional client + timeout wiring (may return `undefined` so aifunctions-js uses its default OpenRouter client for worker LLM calls). |
246
+ | `GRAPH_COMPOSER_ACTION_REGISTRY`, `getActionDefinition`, `getActionDefinitionByToolName`, `requiredPromptPathsFromRegistry`, `loadWorkerBaseMarkdown` | Action registry + prompts. |
247
+ | `composeWorkerInstructions` | Build full system text for one action + catalogs + mode gate. |
248
+ | `applyGraphConceptPatchOnlyIfEmpty` | Apply `intent.onlyIfEmpty` rules to a `graphConceptPatch`. |
249
+ | `composeInstructions`, `formatSkillList` | Lower-level composition from a raw base string + skill lists. |
250
+ | `getPackDir()`, `graphComposerPackRoot()` | Path to bundled `functions/graph-composer` pack. |
251
+ | `readGraphComposerPromptFile(name)` | Read a file under `functions/graph-composer/prompts/`. |
252
+ | `DEFAULT_UTILITY_SKILLS` | Default local skills when `utilitySkills` is omitted. |
253
+ | `buildCatalogMatchHints`, `buildScopingNeedMatchHints` | Optional `matchLists` helpers (normally invoked inside `runGraphWorker`). |
254
+ | `generateGraphJsonInputExample`, `buildGraphInputExampleGuidance` | Generate a realistic JSON input example for a specific graph and expected input schema. |
255
+ | `generateJsonExample`, `generateMdExample`, `generateContentExample` | Re-exported Funcx example-generation helpers. |
256
+ | `validateSuggestCatalogResolutionOutput`, `validateSuggestCatalogCreationsOutput`, `validateSuggestScopingNeedMatchOutput`, `validateSuggestScopingMapCreationOutput`, `validateReviewConceptOutput` | Offline output validators for tests / hosts. |
257
+ | Types: `GraphComposerInput`, `GraphComposerAgentInput`, `GraphComposerIntent`, `CatalogCandidates`, `ScopingMapCandidate`, `NarrixTemplateCandidate`, … | See `dist/index.d.ts`. |
258
+ | `loadCatalogCandidatesFromCatalox`, `createCatalox`, `unifiedCatalogItemToSkillDescriptor`, … | Build `catalogCandidates` from **Catalox** catalogs; see [`docs/catalog-metadb-end-state-contract.md`](./docs/catalog-metadb-end-state-contract.md). |
259
+ | `reportTaskNodeProtocolGaps` | Offline list of **AI task** nodes violating **`taskConfiguration.aiTaskProfile`** (pre/post, **`webScoping.questions`** when enabled, **`inputSynthesis`** fields when synthesis is on). See `docs/task-node-execution-protocol.md`. |
260
+ | `collectCanonicalGraphWarnings` | Warn-first **`@exellix/graph-engine`** canonical checks (top-level keys, metadata placement, memory paths). **Next minor:** `validateCreateModifyOutput` will call `assertCanonicalGraphDocument` (hard-fail) after canonicalize. |
261
+ | `assertCanonicalGraphDocument` | Re-exported from graph-engine — use in host CI when graphs must match runtime 6.x exactly. |
262
+ | `GRAPH_ENGINE_MEMORY_PATH_ROOTS` | Re-exported memory path allowlist from graph-engine — use for validation parity, not a forked copy. |
263
+ | `WoroxScopingMapCatalogCreatePayload`, `WoroxScopedDataDocumentShape` | Host-side CRUD handoff (align field names with your persisted catalog / scoping schema). |
264
+ | `parseGraphConceptStory`, `isGraphConceptStoryDescription`, `GRAPH_CONCEPT_STORY_MARKER`, … | Parse **graph concept story** text for `create` / `modify` / reviews. |
265
+ | `redactSecretsForLog` | Deep-redact sensitive key names for logging (used by `reviewConcept` tracing). |
266
+
267
+ `RunGraphComposerOptions`: `client`, `mode`, `model`, `temperature`, `maxTokens`, `askTimeoutMs`, `connectTimeoutMs`, **`catalogMatchListsAssist`**, **`traceReviewConceptIo`** — see [integration handoff](./docs/integration-handoff.md).
268
+
269
+ ## Bundled content
270
+
271
+ Published tarball includes:
272
+
273
+ - `dist/` — compiled ESM + TypeScript declarations
274
+ - `functions/graph-composer/` — `prompts/` (per-action workers, `shared/`, `orchestrator-system.md`, `judge-rules.md` + JSON block, `default-utility-skills.json`), plus `meta.json`, `test-cases.json`
275
+ - `examples/network-vuln-subnet-triage.v2.json` — sample worox graph
276
+
277
+ It does **not** include internal `docs/`, tests, or `.env`.
278
+
279
+ ## Development (this repo)
280
+
281
+ The repository may keep a duplicate of the sample graph under `docs/examples/` for documentation. The **published** package only ships `examples/`; keep them in sync if you change the sample.
282
+
283
+ ```bash
284
+ cp .env.example .env
285
+ npm install
286
+ npm run build
287
+ npm run verify:local
288
+ npm run typecheck
289
+ npm test # live tests; needs OPENROUTER_API_KEY in .env
290
+ ```
291
+
292
+ Optional: [nx-config2](https://www.npmjs.com/package/nx-config2) for scripts that load `.env`:
293
+
294
+ ```bash
295
+ npx nx-config2 run --env-file .env -- npm test
296
+ ```
297
+
298
+ **Maintainer smoke (suggest only, truncated JSON):** `npm run suggest-smoke` (repo only; uses `scripts/run-suggest-concept-smoke.ts`).
299
+
300
+ **Catalox / Firestore live catalog probe:** `npm run verify:catalog-live` — lists configured **`aiSkills`** merge catalogs (core skills + PRE/POST by default; synthesis catalog **only if** `GC_VERIFY_CATALOG_INPUT_SYNTHESIS_MODES` is set) and runs **`loadCatalogCandidatesFromCatalox`**. Defaults **`CataloxContext.superAdmin=true`**; with **@x12i/catalox ≥ 3.4.6**, **`CATALOX_APP_ID`** is optional (catalog-id-first). Needs **`FIREBASE_PROJECT_ID`** (or other project id env) and **`FIREBASE_SERVICE_ACCOUNT_PATH`** / base64 SA / ADC. See [docs/catalox-multi-app-context.md](./docs/catalox-multi-app-context.md) and [docs/catalog-metadb-end-state-contract.md](./docs/catalog-metadb-end-state-contract.md) § Live verification.
301
+
302
+ ## Documentation in this repo
303
+
304
+ - **Handoff / forward notes:** [docs/integration-handoff.md](./docs/integration-handoff.md)
305
+ - **Catalog shapes & inspection:** [docs/worox-graphs-catalogs.md](./docs/worox-graphs-catalogs.md)
306
+ - **MetaDB / host CRUD handoff:** [docs/catalog-metadb-end-state-contract.md](./docs/catalog-metadb-end-state-contract.md)
307
+ - **Task node (`aiTaskProfile`) + worox-graph alignment:** [docs/task-node-worox-graph-and-graph-composer.md](./docs/task-node-worox-graph-and-graph-composer.md) · [docs/task-node-execution-protocol.md](./docs/task-node-execution-protocol.md)
308
+ - **aifunctions-js agent toolbox FR:** [docs/aifunctions-agent-toolbox-feature-request.md](./docs/aifunctions-agent-toolbox-feature-request.md)
309
+ - **Funcx example generation context:** [docs/funcx-example-generation-feature-request.md](./docs/funcx-example-generation-feature-request.md)
310
+ - **Verify suggestConceptObjective:** [docs/verify-suggest-concept-objective.md](./docs/verify-suggest-concept-objective.md)
311
+ - **aifunctions-js transport report:** [docs/report-aifunctions-js-undici-http.md](./docs/report-aifunctions-js-undici-http.md)
312
+ - **Historical spec:** [docs/specs.md](./docs/specs.md) — not published on npm
313
+
314
+ Published npm tarball still **does not** ship `docs/`; clone the repo or read these on GitHub for integration details.
315
+
316
+ ## Publishing (maintainers)
317
+
318
+ Scoped package `@x12i/graph-composer` uses `publishConfig.access: "public"`. Ensure your npm user is a member of the **x12i** org (or owns the scope) and has a valid token in `~/.npmrc` or project `.npmrc` (never commit tokens).
319
+
320
+ ```bash
321
+ npm run build
322
+ npm publish
323
+ ```
324
+
325
+ Confirm tarball: `npm run pack:check` (must **not** list `docs/`, `.env`, or `test/`).
326
+
327
+ ## License
328
+
329
+ MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,66 @@
1
+ import type { SkillDescriptor } from "./types.js";
2
+ /**
3
+ * Web scoping for this node: explicit flag + question list for the scoper / ai-tasks.
4
+ * See `docs/task-node-execution-protocol.md`.
5
+ */
6
+ export type WebScopingNodeConfig = {
7
+ enabled: boolean;
8
+ /** When `enabled` is true, must be a non-empty list of non-empty strings. */
9
+ questions?: string[];
10
+ };
11
+ export type InputSynthesisDestination = "job" | "task" | "execution";
12
+ /**
13
+ * Input synthesis before MAIN: enabled flag + which **Catalox catalog** holds mode rows
14
+ * and which **row** (mode / strategy) to run.
15
+ */
16
+ export type InputSynthesisNodeConfig = {
17
+ enabled: boolean;
18
+ /**
19
+ * Firestore / Catalox **catalog document id** whose rows are synthesis modes
20
+ * (same string you pass as `catalogIds.inputSynthesisModes` when loading prompts).
21
+ * When `enabled` is true, required (non-empty).
22
+ */
23
+ catalogId?: string;
24
+ /**
25
+ * Row key within `catalogId` (same resolution as PRE/POST: `data.skillKey` /
26
+ * `data.key` / `data.id` / `itemId` after `unifiedCatalogItemToSkillDescriptor`).
27
+ * When `enabled` is true, required (non-empty).
28
+ */
29
+ strategyKey?: string;
30
+ /** Write target for synthesized context (graph-engine ≥ 5.9.0 includes `execution`). */
31
+ destination?: InputSynthesisDestination;
32
+ /** Non-empty when `enabled` is true. */
33
+ outputKey?: string;
34
+ /** Non-empty memory paths when `enabled` is true. */
35
+ sources?: string[];
36
+ /** Optional extra hint for ai-tasks templates (not validated by graph-composer). */
37
+ mode?: string;
38
+ };
39
+ /**
40
+ * Canonical per-node execution contract under `taskConfiguration.aiTaskProfile`.
41
+ * Legacy `metadata.aiTaskProfile` is dual-read until graphs are migrated.
42
+ * See `reportTaskNodeProtocolGaps` and `docs/formats-documentations/`.
43
+ */
44
+ export type AiTaskProfileMetadata = {
45
+ preStrategyKey: string;
46
+ postStrategyKey: string;
47
+ webScoping?: WebScopingNodeConfig;
48
+ inputSynthesis?: InputSynthesisNodeConfig;
49
+ };
50
+ /** Built-in worox-graph local skills — no aiTaskProfile required. */
51
+ export declare const DEFAULT_LOCAL_SKILL_KEYS: readonly string[];
52
+ export type TaskNodeProtocolIssueCode = "missing_preStrategyKey" | "missing_postStrategyKey" | "web_scoping_enabled_without_questions" | "web_scoping_questions_without_enabled" | "synthesis_enabled_without_catalogId" | "synthesis_enabled_without_strategyKey" | "synthesis_enabled_without_outputKey" | "synthesis_enabled_without_sources" | "synthesis_enabled_without_destination" | "synthesis_pipeline_conflict";
53
+ export type TaskNodeProtocolGap = {
54
+ nodeId: string;
55
+ skillKey: string;
56
+ issues: TaskNodeProtocolIssueCode[];
57
+ };
58
+ /**
59
+ * Lists **AI task** nodes that violate the **task node execution protocol**
60
+ * (pre/post strategies, web scoping questions, input synthesis strategy).
61
+ */
62
+ export declare function reportTaskNodeProtocolGaps(graph: object, options?: {
63
+ utilitySkills?: SkillDescriptor[];
64
+ extraLocalSkillKeys?: Iterable<string>;
65
+ }): TaskNodeProtocolGap[];
66
+ //# sourceMappingURL=aiTaskProfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aiTaskProfile.d.ts","sourceRoot":"","sources":["../src/aiTaskProfile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;AAErE;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,cAAc,CAAC,EAAE,wBAAwB,CAAC;CAC3C,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAK5C,CAAC;AAEX,MAAM,MAAM,yBAAyB,GACjC,wBAAwB,GACxB,yBAAyB,GACzB,uCAAuC,GACvC,uCAAuC,GACvC,qCAAqC,GACrC,uCAAuC,GACvC,qCAAqC,GACrC,mCAAmC,GACnC,uCAAuC,GACvC,6BAA6B,CAAC;AAElC,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,yBAAyB,EAAE,CAAC;CACrC,CAAC;AAsHF;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,eAAe,EAAE,CAAC;IAClC,mBAAmB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CACxC,GACA,mBAAmB,EAAE,CAsEvB"}