arkaos 4.32.0 → 4.33.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 (82) hide show
  1. package/README.md +1 -1
  2. package/THE-ARKAOS-GUIDE.md +1 -1
  3. package/VERSION +1 -1
  4. package/arka/SKILL.md +1 -1
  5. package/arka/skills/forge/references/workflows.md +10 -0
  6. package/config/claude-agents/architect.md +1 -1
  7. package/config/claude-agents/backend-dev.md +1 -1
  8. package/config/claude-agents/devops-eng.md +1 -1
  9. package/config/claude-agents/frontend-dev.md +1 -1
  10. package/config/claude-agents/ops-lead.md +1 -1
  11. package/config/claude-agents/pm-director.md +1 -1
  12. package/config/claude-agents/strategy-director.md +1 -1
  13. package/config/skills-curated.yaml +2 -2
  14. package/config/skills-provenance.yaml +7 -0
  15. package/departments/dev/agents/architect.yaml +1 -0
  16. package/departments/dev/agents/backend-dev.yaml +1 -0
  17. package/departments/dev/agents/devops-eng.yaml +1 -0
  18. package/departments/dev/agents/frontend-dev.yaml +1 -0
  19. package/departments/dev/agents/tech-lead.yaml +1 -0
  20. package/departments/dev/skills/diagram/SKILL.md +175 -0
  21. package/departments/dev/skills/diagram/examples/archify-repo-grid.architecture.json +57 -0
  22. package/departments/dev/skills/diagram/vendor/LICENSE +22 -0
  23. package/departments/dev/skills/diagram/vendor/SKILL.md +367 -0
  24. package/departments/dev/skills/diagram/vendor/assets/template.html +11470 -0
  25. package/departments/dev/skills/diagram/vendor/bin/archify.mjs +600 -0
  26. package/departments/dev/skills/diagram/vendor/bin/open-artifact.mjs +67 -0
  27. package/departments/dev/skills/diagram/vendor/examples/agent-run.lifecycle.json +71 -0
  28. package/departments/dev/skills/diagram/vendor/examples/agent-tool-call.workflow.json +111 -0
  29. package/departments/dev/skills/diagram/vendor/examples/async-job-roundtrip.sequence.json +62 -0
  30. package/departments/dev/skills/diagram/vendor/examples/cache-miss-request.sequence.json +82 -0
  31. package/departments/dev/skills/diagram/vendor/examples/deployment-release.lifecycle.json +50 -0
  32. package/departments/dev/skills/diagram/vendor/examples/event-stream.dataflow.json +58 -0
  33. package/departments/dev/skills/diagram/vendor/examples/incident-response.workflow.json +65 -0
  34. package/departments/dev/skills/diagram/vendor/examples/product-analytics.dataflow.json +77 -0
  35. package/departments/dev/skills/diagram/vendor/examples/production-deployment.architecture.json +70 -0
  36. package/departments/dev/skills/diagram/vendor/examples/release-delivery.workflow.json +63 -0
  37. package/departments/dev/skills/diagram/vendor/examples/web-app.architecture.json +47 -0
  38. package/departments/dev/skills/diagram/vendor/package-lock.json +80 -0
  39. package/departments/dev/skills/diagram/vendor/package.json +28 -0
  40. package/departments/dev/skills/diagram/vendor/recipes/scenarios.mjs +350 -0
  41. package/departments/dev/skills/diagram/vendor/renderers/architecture/grid.mjs +62 -0
  42. package/departments/dev/skills/diagram/vendor/renderers/architecture/render-architecture.mjs +490 -0
  43. package/departments/dev/skills/diagram/vendor/renderers/dataflow/README.md +93 -0
  44. package/departments/dev/skills/diagram/vendor/renderers/dataflow/render-dataflow.mjs +396 -0
  45. package/departments/dev/skills/diagram/vendor/renderers/lifecycle/README.md +103 -0
  46. package/departments/dev/skills/diagram/vendor/renderers/lifecycle/render-lifecycle.mjs +482 -0
  47. package/departments/dev/skills/diagram/vendor/renderers/sequence/README.md +96 -0
  48. package/departments/dev/skills/diagram/vendor/renderers/sequence/render-sequence.mjs +357 -0
  49. package/departments/dev/skills/diagram/vendor/renderers/shared/cli.mjs +176 -0
  50. package/departments/dev/skills/diagram/vendor/renderers/shared/generated-validators.mjs +13 -0
  51. package/departments/dev/skills/diagram/vendor/renderers/shared/geometry.mjs +992 -0
  52. package/departments/dev/skills/diagram/vendor/renderers/shared/layout-report.mjs +40 -0
  53. package/departments/dev/skills/diagram/vendor/renderers/shared/utils.mjs +156 -0
  54. package/departments/dev/skills/diagram/vendor/renderers/shared/validator.mjs +40 -0
  55. package/departments/dev/skills/diagram/vendor/renderers/workflow/README.md +114 -0
  56. package/departments/dev/skills/diagram/vendor/renderers/workflow/render-workflow.mjs +598 -0
  57. package/departments/dev/skills/diagram/vendor/schemas/README.md +93 -0
  58. package/departments/dev/skills/diagram/vendor/schemas/architecture.schema.json +125 -0
  59. package/departments/dev/skills/diagram/vendor/schemas/common.schema.json +62 -0
  60. package/departments/dev/skills/diagram/vendor/schemas/dataflow.schema.json +240 -0
  61. package/departments/dev/skills/diagram/vendor/schemas/lifecycle.schema.json +260 -0
  62. package/departments/dev/skills/diagram/vendor/schemas/sequence.schema.json +205 -0
  63. package/departments/dev/skills/diagram/vendor/schemas/workflow.schema.json +351 -0
  64. package/departments/dev/skills/diagram/vendor/scripts/check-render-output.mjs +774 -0
  65. package/departments/dev/skills/diagram/vendor/scripts/generate-validators.mjs +66 -0
  66. package/departments/dev/skills/diagram/vendor/scripts/render-examples.mjs +26 -0
  67. package/departments/dev/skills/spec/SKILL.md +19 -0
  68. package/departments/ops/agents/ops-lead.yaml +1 -0
  69. package/departments/pm/agents/pm-director.yaml +1 -0
  70. package/departments/strategy/agents/strategy-director.yaml +1 -0
  71. package/harness/codex/AGENTS.md +1 -1
  72. package/harness/copilot/copilot-instructions.md +1 -1
  73. package/harness/cursor/rules/arkaos.mdc +2 -2
  74. package/harness/gemini/GEMINI.md +1 -1
  75. package/harness/opencode/AGENTS.md +1 -1
  76. package/harness/zed/.rules +1 -1
  77. package/knowledge/agents-registry-v2.json +9 -1
  78. package/knowledge/skills-manifest.json +14 -1
  79. package/package.json +3 -2
  80. package/pyproject.toml +1 -1
  81. package/scripts/skill_validator.py +10 -2
  82. package/scripts/tools/docs_stats.py +8 -2
@@ -0,0 +1,350 @@
1
+ const RAW_RECIPES = [
2
+ {
3
+ id: 'system-overview', type: 'architecture', proof: 'web-app',
4
+ presentation: { preset: 'classic', motion: 'static', views: 'optional' },
5
+ signals: [['system overview', 12], ['architecture', 10], ['components', 6], ['services', 4], ['repository', 5], ['trust boundary', 8], ['架构', 10], ['系统总览', 12], ['组件', 6], ['服务', 4], ['仓库', 5], ['信任边界', 8]],
6
+ en: {
7
+ title: 'System overview', question: 'What exists, who owns it, and how is it connected?',
8
+ summary: 'A bounded map of core components, external dependencies, primary paths, and trust boundaries.',
9
+ useWhen: 'Onboarding, design reviews, repository orientation, or explaining a service landscape.',
10
+ avoidWhen: 'The audience needs exact call order, state transitions, or row-level data lineage.',
11
+ include: ['8–12 core components', 'one primary path', 'external dependencies', 'trust boundaries'],
12
+ prompt: 'Analyze this repository, then use Archify to create a high-level architecture diagram. Show 8–12 core runtime components, one primary request or data path, external dependencies, ownership or trust boundaries, and put supporting detail in cards instead of adding more edges.',
13
+ },
14
+ zh: {
15
+ title: '系统总览', question: '系统里有什么、归谁负责、彼此如何连接?',
16
+ summary: '用一张有边界的图展示核心组件、外部依赖、主路径和信任边界。',
17
+ useWhen: '适合新人上手、方案评审、仓库梳理和服务全景说明。',
18
+ avoidWhen: '如果重点是精确调用顺序、状态流转或字段级血缘,请换其他配方。',
19
+ include: ['8–12 个核心组件', '一条主路径', '外部依赖', '归属或信任边界'],
20
+ prompt: '分析这个仓库,然后用 Archify 生成高层系统架构图。展示 8–12 个核心运行时组件、一条主要请求或数据路径、外部依赖、归属或信任边界;支持性细节放进卡片,不要继续堆连线。',
21
+ },
22
+ },
23
+ {
24
+ id: 'deployment-ownership', type: 'architecture', proof: 'deployment-ownership',
25
+ presentation: { preset: 'blueprint', motion: 'trace', views: 'recommended' },
26
+ signals: [['deployment topology', 14], ['region', 7], ['vpc', 9], ['cluster', 6], ['availability zone', 8], ['ownership', 7], ['cloud deployment', 12], ['部署拓扑', 14], ['区域', 6], ['集群', 6], ['可用区', 8], ['资源归属', 9], ['跨区', 8]],
27
+ en: {
28
+ title: 'Deployment ownership', question: 'Where does each workload run, and what crosses a boundary?',
29
+ summary: 'A deployment-focused map of regions, networks, clusters, workloads, stores, and cross-boundary mechanisms.',
30
+ useWhen: 'Cloud reviews, production readiness, multi-region planning, or infrastructure ownership handoffs.',
31
+ avoidWhen: 'Deployment facts are unknown or the real question is application behavior rather than placement.',
32
+ include: ['regions and networks', 'workload ownership', 'stateful services', 'named boundary crossings'],
33
+ prompt: 'Use Archify to draw the production deployment topology. Group resources by region, network, cluster, and owner; show workloads and stateful services; label every cross-boundary mechanism. Do not invent deployment facts—mark unknown areas explicitly.',
34
+ },
35
+ zh: {
36
+ title: '部署与归属', question: '每个工作负载运行在哪里,哪些连接跨越了边界?',
37
+ summary: '围绕 Region、网络、集群、工作负载、存储和跨边界机制组织部署图。',
38
+ useWhen: '适合云上评审、生产就绪、多区域规划和基础设施交接。',
39
+ avoidWhen: '部署事实不清楚,或真正问题是应用行为而不是资源位置时不要使用。',
40
+ include: ['区域与网络', '工作负载归属', '有状态服务', '明确的跨边界机制'],
41
+ prompt: '用 Archify 绘制生产部署拓扑。按区域、网络、集群和负责人分组,展示工作负载与有状态服务,并标注每一种跨边界机制。不要编造部署事实,不确定的区域要明确标出。',
42
+ },
43
+ },
44
+ {
45
+ id: 'agent-tool-call', type: 'workflow', proof: 'agent-tool-call',
46
+ presentation: { preset: 'signal-flow', motion: 'trace', views: 'recommended' },
47
+ signals: [['agent tool call', 16], ['tool call', 12], ['approval gate', 10], ['human in the loop', 9], ['mcp', 7], ['planner', 6], ['agent loop', 10], ['智能体工具调用', 16], ['工具调用', 12], ['审批门', 10], ['人在回路', 9], ['规划器', 6], ['智能体循环', 10]],
48
+ en: {
49
+ title: 'Agent tool-call loop', question: 'How does an agent plan, get permission, act, recover, and report?',
50
+ summary: 'A lane-based agent loop with policy gates, tool execution, exception recovery, evidence, and final response.',
51
+ useWhen: 'Explaining agent runtimes, MCP/tool orchestration, approvals, retries, or observability.',
52
+ avoidWhen: 'The goal is only to show static agent components or exact API message timing.',
53
+ include: ['request and planning', 'policy or approval gate', 'tool execution', 'exception and evidence paths'],
54
+ prompt: 'Use Archify workflow mode to explain this agent tool-call loop. Separate user surface, agent runtime, policy boundary, exception handling, tool execution, and observability into lanes. Make the successful path primary and show approval, retry, blocked, and evidence paths explicitly.',
55
+ },
56
+ zh: {
57
+ title: '智能体工具调用', question: '智能体如何规划、获批、执行、恢复并汇报?',
58
+ summary: '用泳道表达策略门、工具执行、异常恢复、证据和最终回复。',
59
+ useWhen: '适合解释 Agent Runtime、MCP/工具编排、审批、重试和可观测性。',
60
+ avoidWhen: '如果只想看静态组件,或重点是精确 API 消息时序,请换其他配方。',
61
+ include: ['请求与规划', '策略或审批门', '工具执行', '异常与证据路径'],
62
+ prompt: '用 Archify 工作流模式解释这段智能体工具调用。把用户界面、Agent Runtime、策略边界、异常处理、工具执行和可观测性分成泳道;突出成功主路径,并明确展示审批、重试、阻塞和证据路径。',
63
+ },
64
+ },
65
+ {
66
+ id: 'delivery-workflow', type: 'workflow', proof: 'delivery-workflow',
67
+ presentation: { preset: 'classic', motion: 'trace', views: 'optional' },
68
+ signals: [['ci/cd', 14], ['release workflow', 14], ['deployment pipeline', 11], ['pull request', 7], ['staging', 7], ['rollback', 8], ['发布流程', 14], ['流水线', 9], ['上线', 7], ['预发', 7], ['回滚', 8], ['审批发布', 10]],
69
+ en: {
70
+ title: 'Delivery workflow', question: 'How does a change move safely from commit to production?',
71
+ summary: 'A delivery flow with build, checks, environments, approvals, smoke tests, rollback, and ownership lanes.',
72
+ useWhen: 'CI/CD design, release reviews, deployment governance, or onboarding developers to delivery.',
73
+ avoidWhen: 'The question is where infrastructure runs or what states a deployment object can occupy.',
74
+ include: ['trigger and build', 'blocking checks', 'approval and environments', 'rollback and verification'],
75
+ prompt: 'Use Archify workflow mode to draw this delivery process from commit to production. Separate developer, CI, approval, environment, and exception lanes; mark blocking checks, smoke tests, ownership, and the rollback path. Keep one unmistakable happy path.',
76
+ },
77
+ zh: {
78
+ title: '研发交付流程', question: '一次变更如何安全地从提交走到生产?',
79
+ summary: '展示构建、检查、环境、审批、冒烟、回滚和负责人泳道。',
80
+ useWhen: '适合 CI/CD 设计、发布评审、部署治理和研发新人上手。',
81
+ avoidWhen: '如果重点是基础设施位置或部署对象的状态集合,请换架构图或生命周期图。',
82
+ include: ['触发与构建', '阻断检查', '审批与环境', '回滚与验证'],
83
+ prompt: '用 Archify 工作流模式绘制从代码提交到生产发布的流程。拆分开发者、CI、审批、环境和异常泳道;标出阻断检查、冒烟测试、负责人和回滚路径,并保留一条一眼可见的成功主路径。',
84
+ },
85
+ },
86
+ {
87
+ id: 'incident-runbook', type: 'workflow', proof: 'incident-runbook',
88
+ presentation: { preset: 'signal-flow', motion: 'trace', views: 'recommended' },
89
+ signals: [['incident response', 15], ['runbook', 12], ['outage', 9], ['triage', 8], ['mitigation', 8], ['escalation', 7], ['事故处置', 15], ['故障', 9], ['应急预案', 12], ['排障', 9], ['缓解', 7], ['升级响应', 8]],
90
+ en: {
91
+ title: 'Incident runbook', question: 'How do responders detect, triage, mitigate, verify, and escalate?',
92
+ summary: 'An operational workflow that separates signals, responders, mitigation, communications, and recovery proof.',
93
+ useWhen: 'Incident playbooks, on-call handoffs, reliability reviews, and tabletop exercises.',
94
+ avoidWhen: 'The audience needs live metrics or a post-incident component topology instead of response actions.',
95
+ include: ['detection signal', 'triage owner', 'mitigation and rollback', 'verification and communication'],
96
+ prompt: 'Use Archify workflow mode to turn this incident runbook into responder lanes. Show detection, triage, mitigation, escalation, communication, rollback, and recovery verification. Separate decision gates from actions and make missing ownership visible.',
97
+ },
98
+ zh: {
99
+ title: '事故处置 Runbook', question: '响应者如何发现、分诊、缓解、验证并升级?',
100
+ summary: '把信号、响应者、缓解动作、沟通和恢复证据拆成可执行流程。',
101
+ useWhen: '适合故障预案、On-call 交接、稳定性评审和桌面演练。',
102
+ avoidWhen: '如果受众需要实时指标仪表盘或事故后的组件拓扑,而不是响应动作,请换其他视图。',
103
+ include: ['发现信号', '分诊负责人', '缓解与回滚', '恢复验证与沟通'],
104
+ prompt: '用 Archify 工作流模式把事故处置预案画成响应者泳道。展示发现、分诊、缓解、升级、沟通、回滚和恢复验证;把决策门与操作分开,并让缺失的负责人清晰可见。',
105
+ },
106
+ },
107
+ {
108
+ id: 'api-request', type: 'sequence', proof: 'cache-miss',
109
+ presentation: { preset: 'classic', motion: 'trace', views: 'optional' },
110
+ signals: [['api request', 14], ['request response', 12], ['call chain', 11], ['cache miss', 13], ['jwt', 8], ['who calls whom', 12], ['api 请求', 14], ['请求响应', 12], ['调用链', 11], ['缓存未命中', 13], ['谁调用谁', 12], ['鉴权链路', 9]],
111
+ en: {
112
+ title: 'API request chain', question: 'Who calls whom, in what order, and what returns?',
113
+ summary: 'A time-ordered request path with authentication, cache fallback, persistence, return traffic, and async trace.',
114
+ useWhen: 'API documentation, debugging request latency, auth reviews, or explaining cache fallback.',
115
+ avoidWhen: 'Order is unimportant and the audience only needs the stable service topology.',
116
+ include: ['callers and callees', 'request and return messages', 'fallback or error path', 'async side effects'],
117
+ prompt: 'Use Archify sequence mode to show this request from caller to final response. Include authentication, cache hit or miss, persistence fallback, return messages, and asynchronous trace or event emission. Keep message labels short and order unambiguous.',
118
+ },
119
+ zh: {
120
+ title: 'API 请求链', question: '谁调用谁、顺序如何、最终返回什么?',
121
+ summary: '按时间展示鉴权、缓存回退、持久化、返回流量和异步追踪。',
122
+ useWhen: '适合 API 文档、请求耗时排查、鉴权评审和缓存回退说明。',
123
+ avoidWhen: '如果顺序不重要,受众只需要稳定的服务拓扑,请用架构图。',
124
+ include: ['调用方与被调用方', '请求与返回消息', '回退或错误路径', '异步副作用'],
125
+ prompt: '用 Archify 时序模式展示从调用方到最终响应的完整请求。包含鉴权、缓存命中或未命中、持久化回退、返回消息,以及异步 Trace 或事件上报;消息标签保持简短,顺序必须明确。',
126
+ },
127
+ },
128
+ {
129
+ id: 'async-roundtrip', type: 'sequence', proof: 'async-roundtrip',
130
+ presentation: { preset: 'signal-flow', motion: 'trace', views: 'recommended' },
131
+ signals: [['async roundtrip', 14], ['webhook', 10], ['callback', 10], ['acknowledgement', 8], ['timeout', 7], ['retry message', 8], ['异步回调', 14], ['回调', 10], ['确认消息', 8], ['超时', 7], ['消息重试', 9], ['webhook', 10]],
132
+ en: {
133
+ title: 'Async roundtrip', question: 'What happens after the initial request returns?',
134
+ summary: 'A sequence view of enqueue, acknowledgement, background work, callbacks, retries, timeout, and final consistency.',
135
+ useWhen: 'Webhooks, jobs, queues, payment callbacks, eventual consistency, or async API contracts.',
136
+ avoidWhen: 'The primary question is topic topology and consumer ownership rather than time order.',
137
+ include: ['initial acknowledgement', 'queue or scheduler', 'background work', 'callback, retry, and timeout'],
138
+ prompt: 'Use Archify sequence mode to explain this asynchronous roundtrip. Show the initial acknowledgement, enqueue or scheduling step, background processing, callback or polling, retry and timeout behavior, and the point where the caller can observe final consistency.',
139
+ },
140
+ zh: {
141
+ title: '异步往返链路', question: '初始请求返回之后,后台还会发生什么?',
142
+ summary: '按时间展示入队、确认、后台处理、回调、重试、超时和最终一致。',
143
+ useWhen: '适合 Webhook、后台任务、队列、支付回调、最终一致和异步 API 契约。',
144
+ avoidWhen: '如果重点是 Topic 拓扑和消费者归属,而不是时间顺序,请用事件数据流配方。',
145
+ include: ['初始确认', '队列或调度器', '后台处理', '回调、重试与超时'],
146
+ prompt: '用 Archify 时序模式解释这段异步往返链路。展示初始确认、入队或调度、后台处理、回调或轮询、重试与超时,以及调用方何时能观察到最终一致结果。',
147
+ },
148
+ },
149
+ {
150
+ id: 'data-lineage', type: 'dataflow', proof: 'product-analytics',
151
+ presentation: { preset: 'classic', motion: 'trace', views: 'recommended' },
152
+ signals: [['data lineage', 15], ['etl', 12], ['warehouse', 9], ['pii', 11], ['governance', 9], ['analytics pipeline', 12], ['数据血缘', 15], ['数据管道', 11], ['数仓', 9], ['治理', 9], ['隐私数据', 10], ['用户同意', 9]],
153
+ en: {
154
+ title: 'Data lineage', question: 'Where does data come from, how does it change, and who consumes it?',
155
+ summary: 'A governed path from sources through consent, transforms, sensitive stores, warehouse, and consumers.',
156
+ useWhen: 'Analytics architecture, ETL/ELT review, PII assessment, warehouse design, or model feature lineage.',
157
+ avoidWhen: 'The audience needs request timing or operational task ownership rather than data assets.',
158
+ include: ['sources and assets', 'transform stages', 'classification or consent', 'stores and consumers'],
159
+ prompt: 'Use Archify dataflow mode to map this data lineage. Name every data asset and transform, show consent or classification boundaries, distinguish streaming from batch paths, and identify stores plus downstream consumers. Do not use unlabeled flows.',
160
+ },
161
+ zh: {
162
+ title: '数据血缘', question: '数据从哪里来、如何变化、最终被谁消费?',
163
+ summary: '从来源经过同意、转换、敏感存储、数仓直到消费者的治理路径。',
164
+ useWhen: '适合分析架构、ETL/ELT 评审、PII 评估、数仓设计和特征血缘。',
165
+ avoidWhen: '如果受众需要请求时序或操作负责人,而不是数据资产,请换其他配方。',
166
+ include: ['数据来源与资产', '转换阶段', '分类或同意边界', '存储与消费者'],
167
+ prompt: '用 Archify 数据流模式梳理这段数据血缘。为每个数据资产和转换命名,展示用户同意或数据分类边界,区分流式与批处理路径,并标明存储和下游消费者;所有数据流都必须有标签。',
168
+ },
169
+ },
170
+ {
171
+ id: 'event-stream', type: 'dataflow', proof: 'event-stream',
172
+ presentation: { preset: 'signal-flow', motion: 'trace', views: 'recommended' },
173
+ signals: [['event stream', 15], ['kafka topology', 14], ['topic', 8], ['consumer group', 11], ['dead letter', 10], ['dlq', 10], ['事件流', 15], ['kafka 拓扑', 14], ['主题', 7], ['消费者组', 11], ['死信', 10], ['事件地铁图', 12]],
174
+ en: {
175
+ title: 'Event-stream topology', question: 'Which events move through which topics, processors, groups, and failure paths?',
176
+ summary: 'A stream map of producers, topics, ordered processors, consumer groups, state, replay, and DLQ.',
177
+ useWhen: 'Kafka/event-platform design, stream processing reviews, ownership, replay, and failure handling.',
178
+ avoidWhen: 'Topic names, consumer groups, and delivery semantics are not known—use a generic workflow instead.',
179
+ include: ['producers and event names', 'topics and ordering', 'processors and consumer groups', 'state, replay, and DLQ'],
180
+ prompt: 'Use Archify dataflow mode to draw this event-stream topology. Name producers, events, topics, ordered processors, consumer groups, state stores, replay paths, and the DLQ. Show ownership and delivery semantics only when supported by evidence.',
181
+ },
182
+ zh: {
183
+ title: '事件流拓扑', question: '哪些事件经过哪些 Topic、处理器、消费者组和失败路径?',
184
+ summary: '展示生产者、Topic、有序处理器、消费者组、状态、重放和 DLQ。',
185
+ useWhen: '适合 Kafka/事件平台设计、流处理评审、归属、重放和失败处理。',
186
+ avoidWhen: '如果 Topic、消费者组和投递语义都不清楚,请先用通用工作流,不要编造事件拓扑。',
187
+ include: ['生产者与事件名', 'Topic 与顺序', '处理器与消费者组', '状态、重放与 DLQ'],
188
+ prompt: '用 Archify 数据流模式绘制这段事件流拓扑。命名生产者、事件、Topic、有序处理器、消费者组、状态存储、重放路径和 DLQ;只有在证据充分时才标注归属和投递语义。',
189
+ },
190
+ },
191
+ {
192
+ id: 'object-lifecycle', type: 'lifecycle', proof: 'agent-run',
193
+ presentation: { preset: 'classic', motion: 'trace', views: 'optional' },
194
+ signals: [['state machine', 15], ['object lifecycle', 14], ['status transition', 11], ['terminal state', 9], ['retry state', 8], ['状态机', 15], ['生命周期', 13], ['状态流转', 11], ['终态', 9], ['等待态', 8], ['重试状态', 8]],
195
+ en: {
196
+ title: 'Object lifecycle', question: 'Which states exist, what events move between them, and how does it end?',
197
+ summary: 'A state model with active work, waits, retries, cancellation, failure, and explicit terminal outcomes.',
198
+ useWhen: 'Tasks, orders, tickets, subscriptions, jobs, agent runs, or any durable object with status.',
199
+ avoidWhen: 'The object has no durable state and the real question is participant interaction over time.',
200
+ include: ['start and active states', 'event-labelled transitions', 'wait and retry states', 'all terminal outcomes'],
201
+ prompt: 'Use Archify lifecycle mode to model this object. Separate main progress, waiting or interruption states, and terminal outcomes. Label transitions with events, include retry, cancellation, timeout, success, and failure where real, and never hide an ending.',
202
+ },
203
+ zh: {
204
+ title: '对象生命周期', question: '有哪些状态、什么事件触发流转、最终如何结束?',
205
+ summary: '展示执行、等待、重试、取消、失败以及明确终态的状态模型。',
206
+ useWhen: '适合任务、订单、工单、订阅、作业、Agent Run 等带持久状态的对象。',
207
+ avoidWhen: '对象没有持久状态,真正问题是参与者随时间的交互时,请使用时序图。',
208
+ include: ['开始与执行态', '带事件的转换', '等待与重试态', '所有终态'],
209
+ prompt: '用 Archify 生命周期模式建模这个对象。分开主进度、等待或中断状态和终态;用事件标注转换,并在真实存在时展示重试、取消、超时、成功和失败,不能隐藏任何结束方式。',
210
+ },
211
+ },
212
+ {
213
+ id: 'deployment-lifecycle', type: 'lifecycle', proof: 'deployment-lifecycle',
214
+ presentation: { preset: 'signal-flow', motion: 'trace', views: 'recommended' },
215
+ signals: [['deployment lifecycle', 15], ['release state', 10], ['promotion state', 9], ['approval status', 8], ['rollback state', 10], ['部署生命周期', 15], ['发布状态', 10], ['晋级', 7], ['审批状态', 8], ['回滚状态', 10]],
216
+ en: {
217
+ title: 'Deployment lifecycle', question: 'What state is a release in, and what can happen next?',
218
+ summary: 'A deployment state model covering queued, building, verifying, approval, promotion, rollback, and terminal outcomes.',
219
+ useWhen: 'Release controllers, GitOps reconciliation, environment promotion, or deployment status APIs.',
220
+ avoidWhen: 'The question is the human/CI sequence of delivery actions rather than the deployment object state.',
221
+ include: ['queued and running states', 'verification and approval', 'promotion and rollback', 'success, failure, cancellation'],
222
+ prompt: 'Use Archify lifecycle mode to model the deployment object. Show queued, building, verifying, waiting for approval, promoting, rolling back, and every terminal outcome. Label the events and guards that permit each transition.',
223
+ },
224
+ zh: {
225
+ title: '部署生命周期', question: '一次发布当前处于什么状态,下一步可能发生什么?',
226
+ summary: '覆盖排队、构建、验证、审批、晋级、回滚和终态的部署状态模型。',
227
+ useWhen: '适合发布控制器、GitOps 对账、环境晋级和部署状态 API。',
228
+ avoidWhen: '如果重点是人员与 CI 的交付动作顺序,而不是部署对象状态,请用交付工作流。',
229
+ include: ['排队与执行态', '验证与审批', '晋级与回滚', '成功、失败与取消'],
230
+ prompt: '用 Archify 生命周期模式建模部署对象。展示排队、构建、验证、等待审批、晋级、回滚以及所有终态,并标注允许每次状态转换的事件和守卫条件。',
231
+ },
232
+ },
233
+ ];
234
+
235
+ export const SCENARIO_RECIPES = Object.freeze(RAW_RECIPES.map((recipe) => Object.freeze({
236
+ ...recipe,
237
+ presentation: Object.freeze({ ...recipe.presentation }),
238
+ signals: Object.freeze(recipe.signals.map((signal) => Object.freeze(signal.slice()))),
239
+ en: Object.freeze({ ...recipe.en, include: Object.freeze(recipe.en.include.slice()) }),
240
+ zh: Object.freeze({ ...recipe.zh, include: Object.freeze(recipe.zh.include.slice()) }),
241
+ })));
242
+
243
+ export function detectGuideLanguage(value = '') {
244
+ return /[\u3400-\u9fff]/u.test(value) ? 'zh' : 'en';
245
+ }
246
+
247
+ function normalized(value) {
248
+ return String(value || '').normalize('NFKC').toLowerCase().replace(/[\s_]+/g, ' ').trim();
249
+ }
250
+
251
+ function localized(recipe, lang) {
252
+ const copy = recipe[lang === 'zh' ? 'zh' : 'en'];
253
+ return {
254
+ id: recipe.id,
255
+ type: recipe.type,
256
+ proof: recipe.proof,
257
+ presentation: { ...recipe.presentation },
258
+ ...copy,
259
+ include: copy.include.slice(),
260
+ };
261
+ }
262
+
263
+ export function listScenarioRecipes(lang = 'en') {
264
+ return SCENARIO_RECIPES.map((recipe) => localized(recipe, lang));
265
+ }
266
+
267
+ function scoreRecipe(recipe, query) {
268
+ const text = normalized(query);
269
+ if (!text) return { recipe, score: 0, matched: [] };
270
+ if (text === recipe.id || text === recipe.id.replace(/-/g, ' ')) {
271
+ return { recipe, score: 100, matched: [recipe.id] };
272
+ }
273
+ let score = 0;
274
+ const matched = [];
275
+ for (const [signal, weight] of recipe.signals) {
276
+ if (text.includes(normalized(signal))) {
277
+ score += weight;
278
+ matched.push(signal);
279
+ }
280
+ }
281
+ return { recipe, score, matched };
282
+ }
283
+
284
+ export function recommendScenario(query, options = {}) {
285
+ const lang = options.lang === 'zh' || options.lang === 'en' ? options.lang : detectGuideLanguage(query);
286
+ const ranked = SCENARIO_RECIPES.map((recipe) => scoreRecipe(recipe, query))
287
+ .sort((left, right) => right.score - left.score || SCENARIO_RECIPES.indexOf(left.recipe) - SCENARIO_RECIPES.indexOf(right.recipe));
288
+ const winner = ranked[0].score > 0 ? ranked[0] : { recipe: SCENARIO_RECIPES[0], score: 0, matched: [] };
289
+ const confidence = winner.score >= 14 ? 'high' : winner.score >= 7 ? 'medium' : 'low';
290
+ return {
291
+ ok: true,
292
+ mode: 'recommendation',
293
+ lang,
294
+ query: String(query || ''),
295
+ confidence,
296
+ matchedSignals: winner.matched.slice(),
297
+ recommendation: localized(winner.recipe, lang),
298
+ alternatives: ranked.filter((entry) => entry.recipe.id !== winner.recipe.id && entry.score > 0)
299
+ .slice(0, 2)
300
+ .map((entry) => ({ ...localized(entry.recipe, lang), score: entry.score })),
301
+ };
302
+ }
303
+
304
+ export function formatScenarioList(lang = 'en') {
305
+ const isZh = lang === 'zh';
306
+ const heading = isZh ? 'Archify 场景配方(11)' : 'Archify scenario recipes (11)';
307
+ const intro = isZh
308
+ ? '先选择你要回答的问题,再选择图表类型。可运行:archify guide "你的场景"'
309
+ : 'Choose the question before the diagram type. Run: archify guide "your scenario"';
310
+ return [heading, '', intro, '', ...listScenarioRecipes(lang).flatMap((recipe) => [
311
+ `${recipe.id} [${recipe.type}] ${recipe.title}`,
312
+ ` ${recipe.question}`,
313
+ ])].join('\n');
314
+ }
315
+
316
+ export function formatScenarioRecommendation(result) {
317
+ const isZh = result.lang === 'zh';
318
+ const recipe = result.recommendation;
319
+ const labels = isZh ? {
320
+ heading: '推荐', question: '要回答的问题', use: '适合', avoid: '不要这样用', include: '必须包含', presentation: '表现建议', prompt: '可直接复制的提示词', alternatives: '其他可能', confidence: '置信度',
321
+ } : {
322
+ heading: 'Recommendation', question: 'Question answered', use: 'Use when', avoid: 'Avoid when', include: 'Must include', presentation: 'Presentation', prompt: 'Copy-ready prompt', alternatives: 'Other possible fits', confidence: 'Confidence',
323
+ };
324
+ const lines = [
325
+ `${labels.heading}: ${recipe.title} [${recipe.type}]`,
326
+ `${labels.confidence}: ${result.confidence}`,
327
+ `${labels.question}: ${recipe.question}`,
328
+ '',
329
+ `${labels.use}: ${recipe.useWhen}`,
330
+ `${labels.avoid}: ${recipe.avoidWhen}`,
331
+ `${labels.include}: ${recipe.include.join(isZh ? '、' : '; ')}`,
332
+ `${labels.presentation}: ${recipe.presentation.preset} · ${recipe.presentation.motion} · views ${recipe.presentation.views}`,
333
+ '',
334
+ `${labels.prompt}:`,
335
+ recipe.prompt,
336
+ ];
337
+ if (result.alternatives.length) {
338
+ lines.push('', `${labels.alternatives}: ${result.alternatives.map((item) => `${item.title} [${item.type}]`).join(' · ')}`);
339
+ }
340
+ return lines.join('\n');
341
+ }
342
+
343
+ export function publicGuideData() {
344
+ return SCENARIO_RECIPES.map((recipe) => ({
345
+ ...localized(recipe, 'en'),
346
+ en: recipe.en,
347
+ zh: recipe.zh,
348
+ signals: recipe.signals.map(([signal, weight]) => [signal, weight]),
349
+ }));
350
+ }
@@ -0,0 +1,62 @@
1
+ /** Grid placement for architecture IR (#8). Not auto-layout — fixed cell math only. */
2
+
3
+ export const DEFAULT_GRID = {
4
+ mode: 'grid',
5
+ origin: [40, 80],
6
+ cols: 4,
7
+ gapX: 30,
8
+ gapY: 40,
9
+ cellW: 130,
10
+ cellH: 64,
11
+ };
12
+
13
+ export function gridLayout(arch) {
14
+ const raw = arch.layout;
15
+ if (!raw || raw.mode !== 'grid') return null;
16
+ return { ...DEFAULT_GRID, ...raw };
17
+ }
18
+
19
+ export function resolveComponentPos(component, grid) {
20
+ if (Array.isArray(component.pos) && component.pos.length === 2) {
21
+ return component.pos;
22
+ }
23
+ if (!grid) return [NaN, NaN];
24
+ if (!Number.isInteger(component.row) || !Number.isInteger(component.col)) {
25
+ return [NaN, NaN];
26
+ }
27
+ const [ox, oy] = grid.origin;
28
+ const stepX = grid.cellW + grid.gapX;
29
+ const stepY = grid.cellH + grid.gapY;
30
+ return [ox + component.col * stepX, oy + component.row * stepY];
31
+ }
32
+
33
+ export function validateGridPlacement(arch, grid, problems) {
34
+ if (!grid) return;
35
+ if (arch.layout !== undefined && arch.layout.mode !== 'grid') {
36
+ problems.push('layout.mode must be "grid" when layout is set (free placement omits layout entirely).');
37
+ return;
38
+ }
39
+ const seen = new Map();
40
+ for (const c of arch.components ?? []) {
41
+ const hasPos = Array.isArray(c.pos) && c.pos.length === 2;
42
+ const hasCell = Number.isInteger(c.row) && Number.isInteger(c.col);
43
+ if (hasPos) continue; // pos wins; row/col are optional hints only
44
+ if (!hasPos && !hasCell) {
45
+ problems.push(`Component "${c.id}" needs pos [x,y] or grid row/col when layout.mode is "grid".`);
46
+ continue;
47
+ }
48
+ if (c.row < 0 || c.col < 0) {
49
+ problems.push(`Component "${c.id}" row/col must be non-negative integers.`);
50
+ continue;
51
+ }
52
+ if (c.col >= grid.cols) {
53
+ problems.push(`Component "${c.id}" col ${c.col} exceeds layout.cols ${grid.cols} (valid: 0..${grid.cols - 1}).`);
54
+ }
55
+ const key = `${c.row},${c.col}`;
56
+ if (seen.has(key)) {
57
+ problems.push(`Components "${seen.get(key)}" and "${c.id}" share grid cell row ${c.row} col ${c.col}.`);
58
+ } else {
59
+ seen.set(key, c.id);
60
+ }
61
+ }
62
+ }