# Inquiry routing / 询盘分流 — synthetic review-only DRAFT

**Not a published tutorial or production integration. / 非已发布教程，非生产集成。**

Manual Trigger → Synthetic Fixtures (Code) → Review Only – Never Send (Code).
Routing means an output `reviewQueue` label, **not** delivery to a person or system. Every policy output has `requiresHumanReview: true` and `sendAllowed: false`. There are no HTTP, email, CRM, model, credential, scheduling or external-write nodes. The workflow is inactive and ends at review data.

分流仅输出人工审核队列标签，不通知任何人员或系统。所有策略结果必须人审且禁止发送。仅手动触发及确定性 Code 节点，无网络、邮件、CRM、模型、凭据、定时或外部写入节点；工作流保持未激活。

## Files / 文件

- `policy.mjs`: reusable pure policy plus bounded n8n item adapter / 可复用纯策略与批次适配。
- `fixtures.json`: 12 entirely invented cases; example-domain addresses and one `.invalid` rejection case, no customer data / 12 个全合成样本，无客户数据。
- `expected-output.json`: independently specified final item-array oracle, including `pairedItem`; not regenerated by the builder / 独立定义的最终输出，不随构建器自动重算。
- `workflow.json`: self-contained n8n import-format draft, Manual Trigger v1 / Code v2 / 自包含待导入草稿。
- `build-workflow.mjs`: embeds the exact policy and fixtures; writes only this directory's `workflow.json` / 仅更新本目录工作流。
- `policy.test.mjs`: native Node tests, including embedded-Code parity / 原生测试含内嵌代码一致性验证。
- `runtime-output.json`, `runtime-evidence.json`: extracted real n8n CLI output and a bounded version/hash/result record / 真实 CLI 输出及版本、校验和与验证边界。
- `skills/inquiry-review/SKILL.md`, `mcp/`, `agents-sdk/`: same-task Skill, MCP tool shape, and complete Agents SDK source. Live client/Runner not executed / 同任务 Skill、MCP 工具形状与完整 SDK 源码；客户端与 live Runner 未执行。
- `runtime-check.md`: disposable CLI reproduction contract and observed compatibility limits / 隔离 CLI 复核步骤与已观察到的兼容边界。

## Offline check / 离线验证

From the repository root, use an existing Node 22 executable (no install or n8n required):
在仓库根目录使用已有 Node 22；无需安装依赖或启动 n8n：

```sh
node --version # Use your existing Node 22 / 使用已有 Node 22
node --test examples/inquiry-routing/policy.test.mjs
# Only after intentionally changing policy/fixtures / 仅在有意修改策略或样本后：
node examples/inquiry-routing/build-workflow.mjs --write
node --test examples/inquiry-routing/policy.test.mjs
```

The original 21 policy tests passed on Node v22.23.2. A separate stored-evidence check now detects drift between the workflow, oracle and recorded runtime output. Tests parse JSON, compare the generated graph, enforce allowed nodes, and execute embedded JavaScript with a minimal `$input.all()` stub in Node `vm`. The VM and regex tripwire are **not security sandboxes/audits**. Running this command does not install or rerun n8n; the actual CLI execution below is separate evidence.

原有 21 项策略测试在 Node v22.23.2 通过；新增留存证据检查用于发现工作流、独立预期与历史运行输出之间的漂移。原生测试不是 n8n 运行，也不是安全审计。更改工作流后不能重算校验和冒充复测：须真实重跑，或明确撤下已不适用的运行证明。

## Input and routing contract / 输入与分支

`routeInquiry(value)` accepts JSON data, not raw JSON text or executable JS objects (getters/proxies/custom instances are outside contract). Each workflow input item is exactly `{ json: { inquiry: value } }`; n8n item metadata such as `pairedItem` may remain outside `json`. Strings are never evaluated or parsed as code/JSON. Required inquiry keys:

| Field / 字段 | Rule / 规则 |
| --- | --- |
| `id` | `DEMO-` plus 3 digits / 加 3 位数字 |
| `email` | lowercase ASCII local part (1–40), only `example.com/org/net`; not deliverability/provenance proof / 仅示例域名，不证明真实性或可投递性 |
| `language` | exact `en` or `zh`; no silent language fallback / 不静默回退 |
| `message` | nonblank, ≤2000 raw UTF-16 code units / 非空，原始 UTF-16 单元上限 2000 |
| `quantity` | integer 1–100000, no string coercion / 整数，不转换数字字符串 |

Raw string caps before trimming: id 8, email 80, language 2, message 2000. At most 50 items; empty/malformed/oversized batches produce one review-error item in the adapter, not silent truncation. Limits act on already parsed data, **not transport bytes or memory allocation**. No recursive scan of unexpected values. Duplicate IDs are not deduplicated; pair by item index. Only use the shipped synthetic fixtures; these format checks cannot establish synthetic provenance or remove personal data from incoming messages.

长度检查在去空白前执行；最多 50 项，适配器对空/无效/过大批次返回一个审核错误，不静默截断。边界针对已解析数据，**并非传输字节或内存防护**。不递归扫描额外值；重复 ID 不去重，按索引对应。仅使用附带合成样本；格式限制无法证明数据来源或清除消息中的个人数据。

Precedence / 优先级：

1. `invalid_input`: malformed record, unexpected keys, wrong type/range/format, unsupported language, oversized fields → input reviewer; no draft / 输入错误，无草稿。
2. `policy_review`: instruction/secret or unverified-claim heuristic hit; missing-field reasons retained → policy reviewer; no draft / 策略提示优先于缺信息，保留缺项原因，无草稿。
3. `needs_information`: absent/null/blank required fields → input reviewer; no draft / 缺信息，人工补全后重跑，无草稿。
4. `draft_for_review`: fixed bilingual internal acknowledgement → sales reviewer; quantity only, no price/stock/lead-time/certification assertions / 固定内部草稿，仅数量，不承诺价格、库存、交期或认证。

Regexes are triage heuristics with false positives/negatives, **never prompt-injection protection, factual verification, compliance decisions or approval to send**. Ordinary drafts also require review. Output omits the original email/message and unexpected values; upstream fixture/execution data still exists. Default save settings are best-effort configuration, not a confidentiality/retention guarantee. Human review must verify routing, quantity/context and any facts against authorized sources; this artifact has no approval or sending transition.

正则只提示人工分流，存在误报/漏报，**不保证防注入、事实、合规或发送许可**。正常草稿也须人审。输出不回显邮件/消息或额外值，但上游执行数据仍存在；保存设置不是保密或留存保证。人工须核对分流、数量、上下文及授权来源，本示例无批准或发送通道。

## Recorded runtime verification / 已记录的真实运行

On **2026-09-05 UTC**, an authorized disposable **n8n 2.37.10 / Node v24.20.0 / macOS arm64** installation imported an unmodified copy of `workflow.json` via **`import:workflow --separate`**. Export confirmed the original nodes, connections and settings, no credentials, `active: false` and `activeVersionId: null`. `execute --id=… --rawOutput` finished successfully through the internal **JavaScript task runner**. All **12 complete output items, including `pairedItem`, exactly matched the independent oracle**: 2 drafts, 1 needs-information, 3 policy-review and 6 invalid-input. All require review and prohibit sending. See the two runtime JSON records and [reproduction notes](runtime-check.md).

**Compatibility limits:** ordinary single-file CLI import failed because this ID-free template had no workflow ID; `--separate` generated one. Do not add a reusable fixed ID that might overwrite an existing workflow. The editor root returned HTTP 404 in this npm setup, so **GUI import and GUI execution remain unverified**. A missing Python-runner environment warning does not affect this JavaScript-only result and is not Python support. n8n also warned that non-container operation is deprecated: use official deployment guidance for production, not this disposable setup.

**证据等级：** 原生测试 + 指定版本的真实 CLI 导入、导出和 JS 任务运行器执行；12 项及配对完全一致。GUI 仍未验证；没有真实客户、模型、人工批准、发送、生产交付或业务效果测试。工作流保留的 `verification: "synthetic-offline-only"` 是合成练习范围标签，不是能自行认证运行环境的证明。网站 Node 22 与临时 n8n Node 24 相互独立。

### Operator editor path / 操作者界面路径（文档步骤，未实测）

In a separately approved disposable editor, official docs describe **Import from File**. Select `workflow.json`, inspect exactly three nodes and both all-items JavaScript Code nodes, keep it unpublished, execute the synthetic fixture once, then compare the final 12 objects. `pairedItem` is item metadata and may not appear in the editor JSON view. Record your actual version, import warnings and full output; stop on mismatch. Do not attach destinations or use real inquiries. The result remains a review draft, not an implemented human-approval service.

另获授权后可在一次性编辑器按官方步骤从文件导入；确认三节点、无凭据、未发布，再运行并对照输出。这里没有声称此界面路径已通过；版本不兼容或输出不一致必须停止，不能据此发布生产流程。

## Official sources / 官方资料

Read-only HTTPS GETs during implementation returned HTTP 200 after redirects:
本次仅只读获取官方文档，重定向后均 HTTP 200：

- [Export/import](https://docs.n8n.io/workflows/export-import/) → [current page](https://docs.n8n.io/build/manage-workflows/export-and-import): JSON and editor Import from File; warns exported credential names/headers can leak / JSON 文件导入及凭据泄露提醒。
- [Code node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/): JavaScript, all-items mode and item-linking responsibilities / JavaScript、全批次模式及数据关联。
- [Data structure](https://docs.n8n.io/data/data-structure/) → [current page](https://docs.n8n.io/build/work-with-data/understand-n8ns-data-structure): array of items with `json` objects / `json` 项目数组结构。

Initial raw GitHub documentation URLs returned 404; the official site pages above were fetched instead. Docs describe conventions, not certification of this hand-authored artifact. The optional scratch policy was inspected as unvalidated reference, not accepted implementation.

初次 GitHub 原始文档链接返回 404，已改读以上官方站点。文档支持格式约定，不认证本手写构件。临时策略草稿仅作未验证参考。

## Integration suggestion / 集成建议

Keep this artifact review-only until editorial/release acceptance. The real CLI check resolves that bounded runtime gap, not tutorial publication or whole-phase completion. Any production input, approval mechanism or sending integration requires a separate design/privacy/security review, not merely flipping `sendAllowed`.

真实 CLI 运行证明已经补齐，但不代表教程已发布或第二阶段全部完成。生产输入、人审机制及发送集成须另行设计并做隐私/安全审查，不能只改发送开关。
