@nebutra/brand-genesis 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nebutra/brand-genesis",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "BrandContext-first flagship play for creating a complete brand package from one idea",
5
5
  "private": false,
6
6
  "license": "MIT",
@@ -25,23 +25,27 @@
25
25
  "category": "ai",
26
26
  "summary": "Flagship play that distills an idea into BrandContext and orchestrates lower generation capabilities"
27
27
  },
28
- "main": "./src/index.ts",
29
- "types": "./src/index.ts",
28
+ "main": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
30
  "exports": {
31
- ".": "./src/index.ts"
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js",
34
+ "default": "./dist/index.js"
35
+ }
32
36
  },
33
37
  "dependencies": {
34
- "@nebutra/audio-pipeline": "0.1.2",
35
- "@nebutra/capability-kit": "0.2.2",
36
- "@nebutra/content-store": "0.1.2",
37
- "@nebutra/3d-pipeline": "0.1.2",
38
+ "@nebutra/audio-pipeline": "0.1.3",
39
+ "@nebutra/capability-kit": "0.2.4",
40
+ "@nebutra/3d-pipeline": "0.1.3",
41
+ "@nebutra/content-store": "0.1.4",
38
42
  "@nebutra/errors": "0.1.2",
39
- "@nebutra/generation-context": "0.1.2",
40
- "@nebutra/event-log": "0.1.2",
41
- "@nebutra/image-pipeline": "0.1.2",
42
- "@nebutra/play-loader": "0.1.2",
43
- "@nebutra/video-pipeline": "0.1.2",
44
- "@nebutra/voice-realtime": "0.1.2"
43
+ "@nebutra/event-log": "0.1.4",
44
+ "@nebutra/generation-context": "0.1.3",
45
+ "@nebutra/image-pipeline": "0.1.3",
46
+ "@nebutra/video-pipeline": "0.1.3",
47
+ "@nebutra/voice-realtime": "0.1.3",
48
+ "@nebutra/play-loader": "0.1.3"
45
49
  },
46
50
  "devDependencies": {
47
51
  "@types/node": "^25.9.1",
@@ -62,6 +66,12 @@
62
66
  "publishConfig": {
63
67
  "access": "public"
64
68
  },
69
+ "files": [
70
+ "dist",
71
+ "README.md",
72
+ "LICENSE",
73
+ "CHANGELOG.md"
74
+ ],
65
75
  "scripts": {
66
76
  "build": "tsup",
67
77
  "test": "vitest run",
@@ -1,60 +0,0 @@
1
- {"at":"2026-05-18T12:38:53.666Z","type":"checkpoint","step":"brand_distillation","tenantId":"tenant_a","brandId":"loop"}
2
- {"at":"2026-05-18T12:38:53.666Z","type":"checkpoint","step":"visual_direction","tenantId":"tenant_a","brandId":"loop"}
3
- {"at":"2026-05-18T12:38:53.670Z","type":"checkpoint","step":"assets_generated","tenantId":"tenant_a","brandId":"loop"}
4
- {"at":"2026-05-18T12:38:53.671Z","type":"checkpoint","step":"video_rendered","tenantId":"tenant_a","brandId":"loop"}
5
- {"at":"2026-05-18T12:38:53.690Z","type":"checkpoint","step":"final_compose","tenantId":"tenant_a","brandId":"loop"}
6
- {"at":"2026-05-18T12:38:53.695Z","type":"run","tenantId":"tenant_a","brandId":"loop","eventId":"eecd54026c5837103602d4375d64ae313c39f40257a0f2bd8bb2f72567c8b094"}
7
- {"at":"2026-05-18T14:12:28.912Z","type":"checkpoint","step":"brand_distillation","tenantId":"tenant_a","brandId":"loop"}
8
- {"at":"2026-05-18T14:12:28.914Z","type":"checkpoint","step":"visual_direction","tenantId":"tenant_a","brandId":"loop"}
9
- {"at":"2026-05-18T14:12:28.917Z","type":"checkpoint","step":"assets_generated","tenantId":"tenant_a","brandId":"loop"}
10
- {"at":"2026-05-18T14:12:28.918Z","type":"checkpoint","step":"video_rendered","tenantId":"tenant_a","brandId":"loop"}
11
- {"at":"2026-05-18T14:12:28.943Z","type":"checkpoint","step":"final_compose","tenantId":"tenant_a","brandId":"loop"}
12
- {"at":"2026-05-18T14:12:28.948Z","type":"run","tenantId":"tenant_a","brandId":"loop","eventId":"0c303506da2e5db18f2204c168ca4f3d599606ec55e32757f16d7392bc2a33a4"}
13
- {"at":"2026-05-18T14:23:05.084Z","type":"checkpoint","step":"brand_distillation","tenantId":"tenant_a","brandId":"loop"}
14
- {"at":"2026-05-18T14:23:05.084Z","type":"checkpoint","step":"visual_direction","tenantId":"tenant_a","brandId":"loop"}
15
- {"at":"2026-05-18T14:23:05.086Z","type":"checkpoint","step":"assets_generated","tenantId":"tenant_a","brandId":"loop"}
16
- {"at":"2026-05-18T14:23:05.087Z","type":"checkpoint","step":"video_rendered","tenantId":"tenant_a","brandId":"loop"}
17
- {"at":"2026-05-18T14:23:05.100Z","type":"checkpoint","step":"final_compose","tenantId":"tenant_a","brandId":"loop"}
18
- {"at":"2026-05-18T14:23:05.102Z","type":"run","tenantId":"tenant_a","brandId":"loop","eventId":"b02ff55376d65813e26dff17e27b158213c6d687b5e537870d4ca6503834a944"}
19
- {"at":"2026-05-18T14:47:37.492Z","type":"checkpoint","step":"brand_distillation","tenantId":"tenant_a","brandId":"loop"}
20
- {"at":"2026-05-18T14:47:37.492Z","type":"checkpoint","step":"visual_direction","tenantId":"tenant_a","brandId":"loop"}
21
- {"at":"2026-05-18T14:47:37.496Z","type":"checkpoint","step":"assets_generated","tenantId":"tenant_a","brandId":"loop"}
22
- {"at":"2026-05-18T14:47:37.498Z","type":"checkpoint","step":"video_rendered","tenantId":"tenant_a","brandId":"loop"}
23
- {"at":"2026-05-18T14:47:37.516Z","type":"checkpoint","step":"final_compose","tenantId":"tenant_a","brandId":"loop"}
24
- {"at":"2026-05-18T14:47:37.521Z","type":"run","tenantId":"tenant_a","brandId":"loop","eventId":"5e0f584ad1bf0f43d103a93141e5160e7588b347c163258c913425561fb26fc7"}
25
- {"at":"2026-05-18T14:49:15.328Z","type":"checkpoint","step":"brand_distillation","tenantId":"tenant_a","brandId":"loop"}
26
- {"at":"2026-05-18T14:49:15.328Z","type":"checkpoint","step":"visual_direction","tenantId":"tenant_a","brandId":"loop"}
27
- {"at":"2026-05-18T14:49:15.330Z","type":"checkpoint","step":"assets_generated","tenantId":"tenant_a","brandId":"loop"}
28
- {"at":"2026-05-18T14:49:15.331Z","type":"checkpoint","step":"video_rendered","tenantId":"tenant_a","brandId":"loop"}
29
- {"at":"2026-05-18T14:49:15.346Z","type":"checkpoint","step":"final_compose","tenantId":"tenant_a","brandId":"loop"}
30
- {"at":"2026-05-18T14:49:15.350Z","type":"run","tenantId":"tenant_a","brandId":"loop","eventId":"11e20a44738d5998438345f88c63e098ca43421350513e7fd075badc5b70eee1"}
31
- {"at":"2026-05-19T05:21:56.849Z","type":"checkpoint","step":"brand_distillation","tenantId":"tenant_a","brandId":"loop"}
32
- {"at":"2026-05-19T05:21:56.850Z","type":"checkpoint","step":"visual_direction","tenantId":"tenant_a","brandId":"loop"}
33
- {"at":"2026-05-19T05:21:56.853Z","type":"checkpoint","step":"assets_generated","tenantId":"tenant_a","brandId":"loop"}
34
- {"at":"2026-05-19T05:21:56.855Z","type":"checkpoint","step":"video_rendered","tenantId":"tenant_a","brandId":"loop"}
35
- {"at":"2026-05-19T05:21:56.881Z","type":"checkpoint","step":"final_compose","tenantId":"tenant_a","brandId":"loop"}
36
- {"at":"2026-05-19T05:21:56.892Z","type":"run","tenantId":"tenant_a","brandId":"loop","eventId":"be5546c4ac1f3982b7a70688188dd3affcb14150ff9f20b96f9955746485caac"}
37
- {"at":"2026-05-19T05:21:56.915Z","type":"checkpoint","step":"brand_distillation","tenantId":"local","brandId":"loop"}
38
- {"at":"2026-05-19T05:21:56.915Z","type":"checkpoint","step":"visual_direction","tenantId":"local","brandId":"loop"}
39
- {"at":"2026-05-19T05:21:56.923Z","type":"checkpoint","step":"assets_generated","tenantId":"local","brandId":"loop"}
40
- {"at":"2026-05-19T05:21:56.924Z","type":"checkpoint","step":"video_rendered","tenantId":"local","brandId":"loop"}
41
- {"at":"2026-05-19T05:21:56.939Z","type":"checkpoint","step":"final_compose","tenantId":"local","brandId":"loop"}
42
- {"at":"2026-05-19T05:21:56.946Z","type":"run","tenantId":"local","brandId":"loop","eventId":"5ab4b35e72cc221654e48e9f84fe8c4f1fae4f15f95373c151ab5a13dc3faf33"}
43
- {"at":"2026-05-19T05:25:16.844Z","type":"checkpoint","step":"brand_distillation","tenantId":"tenant_a","brandId":"loop"}
44
- {"at":"2026-05-19T05:25:16.844Z","type":"checkpoint","step":"visual_direction","tenantId":"tenant_a","brandId":"loop"}
45
- {"at":"2026-05-19T05:25:16.847Z","type":"checkpoint","step":"assets_generated","tenantId":"tenant_a","brandId":"loop"}
46
- {"at":"2026-05-19T05:25:16.849Z","type":"checkpoint","step":"video_rendered","tenantId":"tenant_a","brandId":"loop"}
47
- {"at":"2026-05-19T05:25:16.864Z","type":"checkpoint","step":"final_compose","tenantId":"tenant_a","brandId":"loop"}
48
- {"at":"2026-05-19T05:25:16.868Z","type":"run","tenantId":"tenant_a","brandId":"loop","eventId":"a32f3727ed879ea5bef1b3db0750b0939c47545c75868a0da92c5d39f1d6075f"}
49
- {"at":"2026-05-30T21:07:19.035Z","type":"checkpoint","step":"brand_distillation","tenantId":"tenant_a","brandId":"loop"}
50
- {"at":"2026-05-30T21:07:19.037Z","type":"checkpoint","step":"visual_direction","tenantId":"tenant_a","brandId":"loop"}
51
- {"at":"2026-05-30T21:07:19.041Z","type":"checkpoint","step":"assets_generated","tenantId":"tenant_a","brandId":"loop"}
52
- {"at":"2026-05-30T21:07:19.043Z","type":"checkpoint","step":"video_rendered","tenantId":"tenant_a","brandId":"loop"}
53
- {"at":"2026-05-30T21:07:19.064Z","type":"checkpoint","step":"final_compose","tenantId":"tenant_a","brandId":"loop"}
54
- {"at":"2026-05-30T21:07:19.068Z","type":"run","tenantId":"tenant_a","brandId":"loop","eventId":"4f65643226b0ccf5671905696b10ef8e97997a498f37fa450467af7a536b0c65"}
55
- {"at":"2026-07-01T01:41:04.332Z","type":"checkpoint","step":"brand_distillation","tenantId":"tenant_a","brandId":"loop"}
56
- {"at":"2026-07-01T01:41:04.333Z","type":"checkpoint","step":"visual_direction","tenantId":"tenant_a","brandId":"loop"}
57
- {"at":"2026-07-01T01:41:04.409Z","type":"checkpoint","step":"assets_generated","tenantId":"tenant_a","brandId":"loop"}
58
- {"at":"2026-07-01T01:41:04.411Z","type":"checkpoint","step":"video_rendered","tenantId":"tenant_a","brandId":"loop"}
59
- {"at":"2026-07-01T01:41:04.524Z","type":"checkpoint","step":"final_compose","tenantId":"tenant_a","brandId":"loop"}
60
- {"at":"2026-07-01T01:41:04.530Z","type":"run","tenantId":"tenant_a","brandId":"loop","eventId":"91654689f18ec937937bcca40db6b49c4c4de67efd0923472e06511151310bb1"}
@@ -1,57 +0,0 @@
1
- {"at":"2026-05-18T12:38:53.657Z","type":"reindex","tenantId":"tenant_a","files":0}
2
- {"at":"2026-05-18T12:38:53.663Z","type":"write","tenantId":"tenant_a","path":"company/BRAND.md"}
3
- {"at":"2026-05-18T12:38:53.665Z","type":"write","tenantId":"tenant_a","path":"company/assets/palette.json"}
4
- {"at":"2026-05-18T12:38:53.690Z","type":"write","tenantId":"tenant_a","path":"company/landing/index.html"}
5
- {"at":"2026-05-18T12:38:53.705Z","type":"reindex","tenantId":"local","files":0}
6
- {"at":"2026-05-18T12:38:53.721Z","type":"reindex","tenantId":"tenant_a","files":0}
7
- {"at":"2026-05-18T14:12:28.902Z","type":"reindex","tenantId":"tenant_a","files":0}
8
- {"at":"2026-05-18T14:12:28.909Z","type":"write","tenantId":"tenant_a","path":"company/BRAND.md"}
9
- {"at":"2026-05-18T14:12:28.912Z","type":"write","tenantId":"tenant_a","path":"company/assets/palette.json"}
10
- {"at":"2026-05-18T14:12:28.942Z","type":"write","tenantId":"tenant_a","path":"company/landing/index.html"}
11
- {"at":"2026-05-18T14:12:28.962Z","type":"reindex","tenantId":"local","files":0}
12
- {"at":"2026-05-18T14:12:28.983Z","type":"reindex","tenantId":"tenant_a","files":0}
13
- {"at":"2026-05-18T14:23:05.080Z","type":"reindex","tenantId":"tenant_a","files":0}
14
- {"at":"2026-05-18T14:23:05.083Z","type":"write","tenantId":"tenant_a","path":"company/BRAND.md"}
15
- {"at":"2026-05-18T14:23:05.084Z","type":"write","tenantId":"tenant_a","path":"company/assets/palette.json"}
16
- {"at":"2026-05-18T14:23:05.100Z","type":"write","tenantId":"tenant_a","path":"company/landing/index.html"}
17
- {"at":"2026-05-18T14:23:05.110Z","type":"reindex","tenantId":"local","files":0}
18
- {"at":"2026-05-18T14:23:05.121Z","type":"reindex","tenantId":"tenant_a","files":0}
19
- {"at":"2026-05-18T14:47:37.479Z","type":"reindex","tenantId":"tenant_a","files":0}
20
- {"at":"2026-05-18T14:47:37.489Z","type":"write","tenantId":"tenant_a","path":"company/BRAND.md"}
21
- {"at":"2026-05-18T14:47:37.491Z","type":"write","tenantId":"tenant_a","path":"company/assets/palette.json"}
22
- {"at":"2026-05-18T14:47:37.516Z","type":"write","tenantId":"tenant_a","path":"company/landing/index.html"}
23
- {"at":"2026-05-18T14:47:37.527Z","type":"reindex","tenantId":"local","files":0}
24
- {"at":"2026-05-18T14:47:37.540Z","type":"reindex","tenantId":"tenant_a","files":0}
25
- {"at":"2026-05-18T14:49:15.320Z","type":"reindex","tenantId":"tenant_a","files":0}
26
- {"at":"2026-05-18T14:49:15.326Z","type":"write","tenantId":"tenant_a","path":"company/BRAND.md"}
27
- {"at":"2026-05-18T14:49:15.327Z","type":"write","tenantId":"tenant_a","path":"company/assets/palette.json"}
28
- {"at":"2026-05-18T14:49:15.346Z","type":"write","tenantId":"tenant_a","path":"company/landing/index.html"}
29
- {"at":"2026-05-18T14:49:15.358Z","type":"reindex","tenantId":"local","files":0}
30
- {"at":"2026-05-18T14:49:15.372Z","type":"reindex","tenantId":"tenant_a","files":0}
31
- {"at":"2026-05-19T05:21:56.839Z","type":"reindex","tenantId":"tenant_a","files":0}
32
- {"at":"2026-05-19T05:21:56.846Z","type":"write","tenantId":"tenant_a","path":"company/BRAND.md"}
33
- {"at":"2026-05-19T05:21:56.849Z","type":"write","tenantId":"tenant_a","path":"company/assets/palette.json"}
34
- {"at":"2026-05-19T05:21:56.880Z","type":"write","tenantId":"tenant_a","path":"company/landing/index.html"}
35
- {"at":"2026-05-19T05:21:56.904Z","type":"reindex","tenantId":"local","files":0}
36
- {"at":"2026-05-19T05:21:56.910Z","type":"write","tenantId":"local","path":"company/BRAND.md"}
37
- {"at":"2026-05-19T05:21:56.914Z","type":"write","tenantId":"local","path":"company/assets/palette.json"}
38
- {"at":"2026-05-19T05:21:56.939Z","type":"write","tenantId":"local","path":"company/landing/index.html"}
39
- {"at":"2026-05-19T05:21:56.977Z","type":"reindex","tenantId":"tenant_a","files":0}
40
- {"at":"2026-05-19T05:25:16.837Z","type":"reindex","tenantId":"tenant_a","files":0}
41
- {"at":"2026-05-19T05:25:16.840Z","type":"write","tenantId":"tenant_a","path":"company/BRAND.md"}
42
- {"at":"2026-05-19T05:25:16.843Z","type":"write","tenantId":"tenant_a","path":"company/assets/palette.json"}
43
- {"at":"2026-05-19T05:25:16.863Z","type":"write","tenantId":"tenant_a","path":"company/landing/index.html"}
44
- {"at":"2026-05-19T05:25:16.877Z","type":"reindex","tenantId":"local","files":0}
45
- {"at":"2026-05-19T05:25:16.890Z","type":"reindex","tenantId":"tenant_a","files":0}
46
- {"at":"2026-05-30T21:07:19.021Z","type":"reindex","tenantId":"tenant_a","files":0}
47
- {"at":"2026-05-30T21:07:19.031Z","type":"write","tenantId":"tenant_a","path":"company/BRAND.md"}
48
- {"at":"2026-05-30T21:07:19.034Z","type":"write","tenantId":"tenant_a","path":"company/assets/palette.json"}
49
- {"at":"2026-05-30T21:07:19.064Z","type":"write","tenantId":"tenant_a","path":"company/landing/index.html"}
50
- {"at":"2026-05-30T21:07:19.077Z","type":"reindex","tenantId":"local","files":0}
51
- {"at":"2026-05-30T21:07:19.094Z","type":"reindex","tenantId":"tenant_a","files":0}
52
- {"at":"2026-07-01T01:41:04.321Z","type":"reindex","tenantId":"tenant_a","files":0}
53
- {"at":"2026-07-01T01:41:04.328Z","type":"write","tenantId":"tenant_a","path":"company/BRAND.md"}
54
- {"at":"2026-07-01T01:41:04.331Z","type":"write","tenantId":"tenant_a","path":"company/assets/palette.json"}
55
- {"at":"2026-07-01T01:41:04.523Z","type":"write","tenantId":"tenant_a","path":"company/landing/index.html"}
56
- {"at":"2026-07-01T01:41:04.568Z","type":"reindex","tenantId":"local","files":0}
57
- {"at":"2026-07-01T01:41:04.641Z","type":"reindex","tenantId":"tenant_a","files":0}
@@ -1,10 +0,0 @@
1
- {"traceId":"brand_genesis_loop_mpb6xfcq","kind":"content_write","affected":["company/BRAND.md","company/assets/palette.json","company/landing/index.html","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-PwSQoJ/.nebutra/generated/image-pipeline/image_logo_loop_ai_debugging_for_indie_devs_ca_mpb6xfc3.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-PwSQoJ/.nebutra/generated/image-pipeline/image_hero_debug_like_it_is_a_conversation_mpb6xfc3.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-PwSQoJ/.nebutra/generated/image-pipeline/image_icon_loop_mpb6xfc3.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-PwSQoJ/.nebutra/generated/video-pipeline/composition_video_storyboard_brand_film_loop_mpb6xfc_mpb6xfco.compose.json"],"parent":null,"snapshot":{"company/BRAND.md":"---\nbrand_id: loop\nname: Loop\ntype: brand_profile\n---\n# Loop\n\nAI debugging for indie devs called Loop\n\n## Tagline\n\nDebug like it is a conversation\n\n## Audience\n\nIndependent developers and small engineering teams shipping software quickly\n\n## Tone\n\ntechnical, direct, warm\n\n## Visual Direction\n\ncyberpunk: electric, terminal-native, high-contrast\n\n## Differentiation\n\nUnderstands the full production context instead of treating each error as an isolated message\n","company/assets/palette.json":"{\n \"brandId\": \"loop\",\n \"colors\": [\n {\n \"name\": \"electric cyan\",\n \"hex\": \"#00D4FF\",\n \"role\": \"primary\"\n },\n {\n \"name\": \"carbon black\",\n \"hex\": \"#111318\",\n \"role\": \"background\"\n },\n {\n \"name\": \"signal amber\",\n \"hex\": \"#F3C14B\",\n \"role\": \"accent\"\n }\n ]\n}","company/landing/index.html":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <title>Loop</title>\n</head>\n<body>\n <main data-brand-id=\"loop\">\n <h1>Loop</h1>\n <p>Debug like it is a conversation</p>\n <p>AI debugging for indie devs called Loop</p>\n </main>\n</body>\n</html>\n"},"id":"eecd54026c5837103602d4375d64ae313c39f40257a0f2bd8bb2f72567c8b094","tenantId":"tenant_a","at":"2026-05-18T12:38:53.694Z","summary":"content_write touched 7 path(s)","objectHashes":["214176d31137be38d254248f03bf7946f73e60c33f10aca626d3c8262eb81796","871042e6396b84e849e13122ce60392a98cd9108875d882103534c1abffe83ef","425de019a39993cdcc61c233a5e54625dbd4d5a99eb79275f4642f1cda210d33"]}
2
- {"traceId":"brand_genesis_loop_mpba9s3z","kind":"content_write","affected":["company/BRAND.md","company/assets/palette.json","company/landing/index.html","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-gw5Yzm/.nebutra/generated/image-pipeline/image_logo_loop_ai_debugging_for_indie_devs_ca_mpba9s36.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-gw5Yzm/.nebutra/generated/image-pipeline/image_hero_debug_like_it_is_a_conversation_mpba9s36.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-gw5Yzm/.nebutra/generated/image-pipeline/image_icon_loop_mpba9s36.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-gw5Yzm/.nebutra/generated/video-pipeline/composition_video_storyboard_brand_film_loop_mpba9s3_mpba9s3w.compose.json"],"parent":null,"snapshot":{"company/BRAND.md":"---\nbrand_id: loop\nname: Loop\ntype: brand_profile\n---\n# Loop\n\nAI debugging for indie devs called Loop\n\n## Tagline\n\nDebug like it is a conversation\n\n## Audience\n\nIndependent developers and small engineering teams shipping software quickly\n\n## Tone\n\ntechnical, direct, warm\n\n## Visual Direction\n\ncyberpunk: electric, terminal-native, high-contrast\n\n## Differentiation\n\nUnderstands the full production context instead of treating each error as an isolated message\n","company/assets/palette.json":"{\n \"brandId\": \"loop\",\n \"colors\": [\n {\n \"name\": \"electric cyan\",\n \"hex\": \"#00D4FF\",\n \"role\": \"primary\"\n },\n {\n \"name\": \"carbon black\",\n \"hex\": \"#111318\",\n \"role\": \"background\"\n },\n {\n \"name\": \"signal amber\",\n \"hex\": \"#F3C14B\",\n \"role\": \"accent\"\n }\n ]\n}","company/landing/index.html":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <title>Loop</title>\n</head>\n<body>\n <main data-brand-id=\"loop\">\n <h1>Loop</h1>\n <p>Debug like it is a conversation</p>\n <p>AI debugging for indie devs called Loop</p>\n </main>\n</body>\n</html>\n"},"id":"0c303506da2e5db18f2204c168ca4f3d599606ec55e32757f16d7392bc2a33a4","tenantId":"tenant_a","at":"2026-05-18T14:12:28.947Z","summary":"content_write touched 7 path(s)","objectHashes":["214176d31137be38d254248f03bf7946f73e60c33f10aca626d3c8262eb81796","871042e6396b84e849e13122ce60392a98cd9108875d882103534c1abffe83ef","425de019a39993cdcc61c233a5e54625dbd4d5a99eb79275f4642f1cda210d33"]}
3
- {"traceId":"brand_genesis_loop_mpbanez0","kind":"content_write","affected":["company/BRAND.md","company/assets/palette.json","company/landing/index.html","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-jaKU9z/.nebutra/generated/image-pipeline/image_logo_loop_ai_debugging_for_indie_devs_ca_mpbaneyl.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-jaKU9z/.nebutra/generated/image-pipeline/image_hero_debug_like_it_is_a_conversation_mpbaneyl.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-jaKU9z/.nebutra/generated/image-pipeline/image_icon_loop_mpbaneyl.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-jaKU9z/.nebutra/generated/video-pipeline/composition_video_storyboard_brand_film_loop_mpbaney_mpbaneyz.compose.json"],"parent":null,"snapshot":{"company/BRAND.md":"---\nbrand_id: loop\nname: Loop\ntype: brand_profile\n---\n# Loop\n\nAI debugging for indie devs called Loop\n\n## Tagline\n\nDebug like it is a conversation\n\n## Audience\n\nIndependent developers and small engineering teams shipping software quickly\n\n## Tone\n\ntechnical, direct, warm\n\n## Visual Direction\n\ncyberpunk: electric, terminal-native, high-contrast\n\n## Differentiation\n\nUnderstands the full production context instead of treating each error as an isolated message\n","company/assets/palette.json":"{\n \"brandId\": \"loop\",\n \"colors\": [\n {\n \"name\": \"electric cyan\",\n \"hex\": \"#00D4FF\",\n \"role\": \"primary\"\n },\n {\n \"name\": \"carbon black\",\n \"hex\": \"#111318\",\n \"role\": \"background\"\n },\n {\n \"name\": \"signal amber\",\n \"hex\": \"#F3C14B\",\n \"role\": \"accent\"\n }\n ]\n}","company/landing/index.html":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <title>Loop</title>\n</head>\n<body>\n <main data-brand-id=\"loop\">\n <h1>Loop</h1>\n <p>Debug like it is a conversation</p>\n <p>AI debugging for indie devs called Loop</p>\n </main>\n</body>\n</html>\n"},"id":"b02ff55376d65813e26dff17e27b158213c6d687b5e537870d4ca6503834a944","tenantId":"tenant_a","at":"2026-05-18T14:23:05.102Z","summary":"content_write touched 7 path(s)","objectHashes":["214176d31137be38d254248f03bf7946f73e60c33f10aca626d3c8262eb81796","871042e6396b84e849e13122ce60392a98cd9108875d882103534c1abffe83ef","425de019a39993cdcc61c233a5e54625dbd4d5a99eb79275f4642f1cda210d33"]}
4
- {"traceId":"brand_genesis_loop_mpbbiz3h","kind":"content_write","affected":["company/BRAND.md","company/assets/palette.json","company/landing/index.html","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-EtzEJo/.nebutra/generated/image-pipeline/image_logo_loop_ai_debugging_for_indie_devs_ca_mpbbiz2t.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-EtzEJo/.nebutra/generated/image-pipeline/image_hero_debug_like_it_is_a_conversation_mpbbiz2t.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-EtzEJo/.nebutra/generated/image-pipeline/image_icon_loop_mpbbiz2t.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-EtzEJo/.nebutra/generated/video-pipeline/composition_video_storyboard_brand_film_loop_mpbbiz2_mpbbiz3e.compose.json"],"parent":null,"snapshot":{"company/BRAND.md":"---\nbrand_id: loop\nname: Loop\ntype: brand_profile\n---\n# Loop\n\nAI debugging for indie devs called Loop\n\n## Tagline\n\nDebug like it is a conversation\n\n## Audience\n\nIndependent developers and small engineering teams shipping software quickly\n\n## Tone\n\ntechnical, direct, warm\n\n## Visual Direction\n\ncyberpunk: electric, terminal-native, high-contrast\n\n## Differentiation\n\nUnderstands the full production context instead of treating each error as an isolated message\n","company/assets/palette.json":"{\n \"brandId\": \"loop\",\n \"colors\": [\n {\n \"name\": \"electric cyan\",\n \"hex\": \"#00D4FF\",\n \"role\": \"primary\"\n },\n {\n \"name\": \"carbon black\",\n \"hex\": \"#111318\",\n \"role\": \"background\"\n },\n {\n \"name\": \"signal amber\",\n \"hex\": \"#F3C14B\",\n \"role\": \"accent\"\n }\n ]\n}","company/landing/index.html":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <title>Loop</title>\n</head>\n<body>\n <main data-brand-id=\"loop\">\n <h1>Loop</h1>\n <p>Debug like it is a conversation</p>\n <p>AI debugging for indie devs called Loop</p>\n </main>\n</body>\n</html>\n"},"id":"5e0f584ad1bf0f43d103a93141e5160e7588b347c163258c913425561fb26fc7","tenantId":"tenant_a","at":"2026-05-18T14:47:37.520Z","summary":"content_write touched 7 path(s)","objectHashes":["214176d31137be38d254248f03bf7946f73e60c33f10aca626d3c8262eb81796","871042e6396b84e849e13122ce60392a98cd9108875d882103534c1abffe83ef","425de019a39993cdcc61c233a5e54625dbd4d5a99eb79275f4642f1cda210d33"]}
5
- {"traceId":"brand_genesis_loop_mpbbl2ky","kind":"content_write","affected":["company/BRAND.md","company/assets/palette.json","company/landing/index.html","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-QfJS5I/.nebutra/generated/image-pipeline/image_logo_loop_ai_debugging_for_indie_devs_ca_mpbbl2kg.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-QfJS5I/.nebutra/generated/image-pipeline/image_hero_debug_like_it_is_a_conversation_mpbbl2kg.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-QfJS5I/.nebutra/generated/image-pipeline/image_icon_loop_mpbbl2kg.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-QfJS5I/.nebutra/generated/video-pipeline/composition_video_storyboard_brand_film_loop_mpbbl2k_mpbbl2kx.compose.json"],"parent":null,"snapshot":{"company/BRAND.md":"---\nbrand_id: loop\nname: Loop\ntype: brand_profile\n---\n# Loop\n\nAI debugging for indie devs called Loop\n\n## Tagline\n\nDebug like it is a conversation\n\n## Audience\n\nIndependent developers and small engineering teams shipping software quickly\n\n## Tone\n\ntechnical, direct, warm\n\n## Visual Direction\n\ncyberpunk: electric, terminal-native, high-contrast\n\n## Differentiation\n\nUnderstands the full production context instead of treating each error as an isolated message\n","company/assets/palette.json":"{\n \"brandId\": \"loop\",\n \"colors\": [\n {\n \"name\": \"electric cyan\",\n \"hex\": \"#00D4FF\",\n \"role\": \"primary\"\n },\n {\n \"name\": \"carbon black\",\n \"hex\": \"#111318\",\n \"role\": \"background\"\n },\n {\n \"name\": \"signal amber\",\n \"hex\": \"#F3C14B\",\n \"role\": \"accent\"\n }\n ]\n}","company/landing/index.html":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <title>Loop</title>\n</head>\n<body>\n <main data-brand-id=\"loop\">\n <h1>Loop</h1>\n <p>Debug like it is a conversation</p>\n <p>AI debugging for indie devs called Loop</p>\n </main>\n</body>\n</html>\n"},"id":"11e20a44738d5998438345f88c63e098ca43421350513e7fd075badc5b70eee1","tenantId":"tenant_a","at":"2026-05-18T14:49:15.349Z","summary":"content_write touched 7 path(s)","objectHashes":["214176d31137be38d254248f03bf7946f73e60c33f10aca626d3c8262eb81796","871042e6396b84e849e13122ce60392a98cd9108875d882103534c1abffe83ef","425de019a39993cdcc61c233a5e54625dbd4d5a99eb79275f4642f1cda210d33"]}
6
- {"traceId":"brand_genesis_loop_mpc6rd01","kind":"content_write","affected":["company/BRAND.md","company/assets/palette.json","company/landing/index.html","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-aXQqoZ/.nebutra/generated/image-pipeline/image_logo_loop_ai_debugging_for_indie_devs_ca_mpc6rcz6.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-aXQqoZ/.nebutra/generated/image-pipeline/image_hero_debug_like_it_is_a_conversation_mpc6rcz7.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-aXQqoZ/.nebutra/generated/image-pipeline/image_icon_loop_mpc6rcz7.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-aXQqoZ/.nebutra/generated/video-pipeline/composition_video_storyboard_brand_film_loop_mpc6rcz_mpc6rczx.compose.json"],"parent":null,"snapshot":{"company/BRAND.md":"---\nbrand_id: loop\nname: Loop\ntype: brand_profile\n---\n# Loop\n\nAI debugging for indie devs called Loop\n\n## Tagline\n\nDebug like it is a conversation\n\n## Audience\n\nIndependent developers and small engineering teams shipping software quickly\n\n## Tone\n\ntechnical, direct, warm\n\n## Visual Direction\n\ncyberpunk: electric, terminal-native, high-contrast\n\n## Differentiation\n\nUnderstands the full production context instead of treating each error as an isolated message\n","company/assets/palette.json":"{\n \"brandId\": \"loop\",\n \"colors\": [\n {\n \"name\": \"electric cyan\",\n \"hex\": \"#00D4FF\",\n \"role\": \"primary\"\n },\n {\n \"name\": \"carbon black\",\n \"hex\": \"#111318\",\n \"role\": \"background\"\n },\n {\n \"name\": \"signal amber\",\n \"hex\": \"#F3C14B\",\n \"role\": \"accent\"\n }\n ]\n}","company/landing/index.html":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <title>Loop</title>\n</head>\n<body>\n <main data-brand-id=\"loop\">\n <h1>Loop</h1>\n <p>Debug like it is a conversation</p>\n <p>AI debugging for indie devs called Loop</p>\n </main>\n</body>\n</html>\n"},"id":"be5546c4ac1f3982b7a70688188dd3affcb14150ff9f20b96f9955746485caac","tenantId":"tenant_a","at":"2026-05-19T05:21:56.891Z","summary":"content_write touched 7 path(s)","objectHashes":["214176d31137be38d254248f03bf7946f73e60c33f10aca626d3c8262eb81796","871042e6396b84e849e13122ce60392a98cd9108875d882103534c1abffe83ef","425de019a39993cdcc61c233a5e54625dbd4d5a99eb79275f4642f1cda210d33"]}
7
- {"traceId":"brand_genesis_loop_mpc6rd1n","kind":"content_write","affected":["company/BRAND.md","company/assets/palette.json","company/landing/index.html","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-x8veqs/.nebutra/generated/image-pipeline/image_logo_loop_ai_tool_called_loop_mpc6rd11.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-x8veqs/.nebutra/generated/image-pipeline/image_hero_loop_turns_intent_into_launch_mpc6rd11.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-x8veqs/.nebutra/generated/image-pipeline/image_icon_loop_mpc6rd11.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-x8veqs/.nebutra/generated/video-pipeline/composition_video_storyboard_brand_film_loop_mpc6rd1_mpc6rd1l.compose.json"],"parent":null,"snapshot":{"company/BRAND.md":"---\nbrand_id: loop\nname: Loop\ntype: brand_profile\n---\n# Loop\n\nAI tool called Loop\n\n## Tagline\n\nLoop turns intent into launch\n\n## Audience\n\nEarly-stage founders validating a focused product wedge\n\n## Tone\n\nclear, confident, useful\n\n## Visual Direction\n\nminimal: calm, precise, spacious\n\n## Differentiation\n\nCombines brand, execution, and company memory in one repeatable workflow\n","company/assets/palette.json":"{\n \"brandId\": \"loop\",\n \"colors\": [\n {\n \"name\": \"graphite\",\n \"hex\": \"#1F2933\",\n \"role\": \"primary\"\n },\n {\n \"name\": \"white\",\n \"hex\": \"#FFFFFF\",\n \"role\": \"background\"\n },\n {\n \"name\": \"signal green\",\n \"hex\": \"#00A693\",\n \"role\": \"accent\"\n }\n ]\n}","company/landing/index.html":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <title>Loop</title>\n</head>\n<body>\n <main data-brand-id=\"loop\">\n <h1>Loop</h1>\n <p>Loop turns intent into launch</p>\n <p>AI tool called Loop</p>\n </main>\n</body>\n</html>\n"},"id":"5ab4b35e72cc221654e48e9f84fe8c4f1fae4f15f95373c151ab5a13dc3faf33","tenantId":"local","at":"2026-05-19T05:21:56.945Z","summary":"content_write touched 7 path(s)","objectHashes":["deb84492ddb1d894948d863e0aba87fe561e6839f990df37e2992804a64d0763","b307787cbf0854a4a8bb9b2066d607ac505c6a7a6bf1ae973e2b3efab166ee7b","e61508a3e6ca1ed01a2228bdb37ffc57595a5b9af319400e34d31925ec19d351"]}
8
- {"traceId":"brand_genesis_loop_mpc6vnb4","kind":"content_write","affected":["company/BRAND.md","company/assets/palette.json","company/landing/index.html","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-UMuJKa/.nebutra/generated/image-pipeline/image_logo_loop_ai_debugging_for_indie_devs_ca_mpc6vnal.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-UMuJKa/.nebutra/generated/image-pipeline/image_hero_debug_like_it_is_a_conversation_mpc6vnal.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-UMuJKa/.nebutra/generated/image-pipeline/image_icon_loop_mpc6vnal.svg","/var/folders/5w/1r1903zn3qx9jczfrp4347hc0000gn/T/brand-genesis-UMuJKa/.nebutra/generated/video-pipeline/composition_video_storyboard_brand_film_loop_mpc6vna_mpc6vnb2.compose.json"],"parent":null,"snapshot":{"company/BRAND.md":"---\nbrand_id: loop\nname: Loop\ntype: brand_profile\n---\n# Loop\n\nAI debugging for indie devs called Loop\n\n## Tagline\n\nDebug like it is a conversation\n\n## Audience\n\nIndependent developers and small engineering teams shipping software quickly\n\n## Tone\n\ntechnical, direct, warm\n\n## Visual Direction\n\ncyberpunk: electric, terminal-native, high-contrast\n\n## Differentiation\n\nUnderstands the full production context instead of treating each error as an isolated message\n","company/assets/palette.json":"{\n \"brandId\": \"loop\",\n \"colors\": [\n {\n \"name\": \"electric cyan\",\n \"hex\": \"#00D4FF\",\n \"role\": \"primary\"\n },\n {\n \"name\": \"carbon black\",\n \"hex\": \"#111318\",\n \"role\": \"background\"\n },\n {\n \"name\": \"signal amber\",\n \"hex\": \"#F3C14B\",\n \"role\": \"accent\"\n }\n ]\n}","company/landing/index.html":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <title>Loop</title>\n</head>\n<body>\n <main data-brand-id=\"loop\">\n <h1>Loop</h1>\n <p>Debug like it is a conversation</p>\n <p>AI debugging for indie devs called Loop</p>\n </main>\n</body>\n</html>\n"},"id":"a32f3727ed879ea5bef1b3db0750b0939c47545c75868a0da92c5d39f1d6075f","tenantId":"tenant_a","at":"2026-05-19T05:25:16.867Z","summary":"content_write touched 7 path(s)","objectHashes":["214176d31137be38d254248f03bf7946f73e60c33f10aca626d3c8262eb81796","871042e6396b84e849e13122ce60392a98cd9108875d882103534c1abffe83ef","425de019a39993cdcc61c233a5e54625dbd4d5a99eb79275f4642f1cda210d33"]}
9
- {"at":"2026-05-30T21:07:19.067Z","traceId":"brand_genesis_loop_mpsudhg8","kind":"content_write","affected":["company/BRAND.md","company/assets/palette.json","company/landing/index.html","/tmp/brand-genesis-7p5BD9/.nebutra/generated/image-pipeline/image_logo_loop_ai_debugging_for_indie_devs_ca_mpsudhfh.svg","/tmp/brand-genesis-7p5BD9/.nebutra/generated/image-pipeline/image_hero_debug_like_it_is_a_conversation_mpsudhfh.svg","/tmp/brand-genesis-7p5BD9/.nebutra/generated/image-pipeline/image_icon_loop_mpsudhfh.svg","/tmp/brand-genesis-7p5BD9/.nebutra/generated/video-pipeline/composition_video_storyboard_brand_film_loop_mpsudhf_mpsudhg5.compose.json"],"parent":null,"snapshot":{"company/BRAND.md":"---\nbrand_id: loop\nname: Loop\ntype: brand_profile\n---\n# Loop\n\nAI debugging for indie devs called Loop\n\n## Tagline\n\nDebug like it is a conversation\n\n## Audience\n\nIndependent developers and small engineering teams shipping software quickly\n\n## Tone\n\ntechnical, direct, warm\n\n## Visual Direction\n\ncyberpunk: electric, terminal-native, high-contrast\n\n## Differentiation\n\nUnderstands the full production context instead of treating each error as an isolated message\n","company/assets/palette.json":"{\n \"brandId\": \"loop\",\n \"colors\": [\n {\n \"name\": \"electric cyan\",\n \"hex\": \"#00D4FF\",\n \"role\": \"primary\"\n },\n {\n \"name\": \"carbon black\",\n \"hex\": \"#111318\",\n \"role\": \"background\"\n },\n {\n \"name\": \"signal amber\",\n \"hex\": \"#F3C14B\",\n \"role\": \"accent\"\n }\n ]\n}","company/landing/index.html":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <title>Loop</title>\n</head>\n<body>\n <main data-brand-id=\"loop\">\n <h1>Loop</h1>\n <p>Debug like it is a conversation</p>\n <p>AI debugging for indie devs called Loop</p>\n </main>\n</body>\n</html>\n"},"id":"4f65643226b0ccf5671905696b10ef8e97997a498f37fa450467af7a536b0c65","tenantId":"tenant_a","summary":"content_write touched 7 path(s)","objectHashes":["214176d31137be38d254248f03bf7946f73e60c33f10aca626d3c8262eb81796","871042e6396b84e849e13122ce60392a98cd9108875d882103534c1abffe83ef","425de019a39993cdcc61c233a5e54625dbd4d5a99eb79275f4642f1cda210d33"]}
10
- {"at":"2026-07-01T01:41:04.528Z","traceId":"brand_genesis_loop_mr1esy30","kind":"content_write","affected":["company/BRAND.md","company/assets/palette.json","company/landing/index.html","/tmp/brand-genesis-ZIt79e/.nebutra/generated/image-pipeline/image_logo_loop_ai_debugging_for_indie_devs_ca_mr1esxxp.svg","/tmp/brand-genesis-ZIt79e/.nebutra/generated/image-pipeline/image_hero_debug_like_it_is_a_conversation_mr1esxxp.svg","/tmp/brand-genesis-ZIt79e/.nebutra/generated/image-pipeline/image_icon_loop_mr1esxxp.svg","/tmp/brand-genesis-ZIt79e/.nebutra/generated/video-pipeline/composition_video_storyboard_brand_film_loop_mr1esxz_mr1esy2u.compose.json"],"parent":null,"snapshot":{"company/BRAND.md":"---\nbrand_id: loop\nname: Loop\ntype: brand_profile\n---\n# Loop\n\nAI debugging for indie devs called Loop\n\n## Tagline\n\nDebug like it is a conversation\n\n## Audience\n\nIndependent developers and small engineering teams shipping software quickly\n\n## Tone\n\ntechnical, direct, warm\n\n## Visual Direction\n\ncyberpunk: electric, terminal-native, high-contrast\n\n## Differentiation\n\nUnderstands the full production context instead of treating each error as an isolated message\n","company/assets/palette.json":"{\n \"brandId\": \"loop\",\n \"colors\": [\n {\n \"name\": \"electric cyan\",\n \"hex\": \"#00D4FF\",\n \"role\": \"primary\"\n },\n {\n \"name\": \"carbon black\",\n \"hex\": \"#111318\",\n \"role\": \"background\"\n },\n {\n \"name\": \"signal amber\",\n \"hex\": \"#F3C14B\",\n \"role\": \"accent\"\n }\n ]\n}","company/landing/index.html":"<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <title>Loop</title>\n</head>\n<body>\n <main data-brand-id=\"loop\">\n <h1>Loop</h1>\n <p>Debug like it is a conversation</p>\n <p>AI debugging for indie devs called Loop</p>\n </main>\n</body>\n</html>\n"},"id":"91654689f18ec937937bcca40db6b49c4c4de67efd0923472e06511151310bb1","tenantId":"tenant_a","summary":"content_write touched 7 path(s)","objectHashes":["214176d31137be38d254248f03bf7946f73e60c33f10aca626d3c8262eb81796","871042e6396b84e849e13122ce60392a98cd9108875d882103534c1abffe83ef","425de019a39993cdcc61c233a5e54625dbd4d5a99eb79275f4642f1cda210d33"]}
@@ -1,22 +0,0 @@
1
-
2
- > @nebutra/brand-genesis@0.2.2 build /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/brand-genesis
3
- > tsup
4
-
5
- CLI Building entry: src/cli.ts, src/index.ts
6
- CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.5.1
8
- CLI Using tsup config: /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/brand-genesis/tsup.config.ts
9
- CLI Target: es2022
10
- CLI Cleaning output folder
11
- ESM Build start
12
- ESM dist/index.js 300.00 B
13
- ESM dist/cli.js 2.22 KB
14
- ESM dist/chunk-2UQ5N3IJ.js 12.95 KB
15
- ESM dist/index.js.map 71.00 B
16
- ESM dist/cli.js.map 4.04 KB
17
- ESM dist/chunk-2UQ5N3IJ.js.map 25.94 KB
18
- ESM ⚡️ Build success in 36ms
19
- DTS Build start
20
- DTS ⚡️ Build success in 13847ms
21
- DTS dist/cli.d.ts 13.00 B
22
- DTS dist/index.d.ts 3.63 KB
@@ -1,16 +0,0 @@
1
-
2
- > @nebutra/brand-genesis@0.2.1 test /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/brand-genesis
3
- > vitest run
4
-
5
-
6
- RUN v4.1.4 /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/brand-genesis
7
-
8
- (node:59839) ExperimentalWarning: SQLite is an experimental feature and might change at any time
9
- (Use `node --trace-warnings ...` to show where the warning was created)
10
- ✓ src/index.test.ts (5 tests) 366ms
11
-
12
- Test Files 1 passed (1)
13
- Tests 5 passed (5)
14
- Start at 09:41:02
15
- Duration 2.21s (transform 714ms, setup 0ms, import 897ms, tests 366ms, environment 0ms)
16
-
@@ -1,4 +0,0 @@
1
-
2
- > @nebutra/brand-genesis@0.2.2 typecheck /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/brand-genesis
3
- > tsc --noEmit
4
-
@@ -1,9 +0,0 @@
1
- import { brandContextFromDraft, distillBrandIdea, renderBrandMarkdown } from "../src";
2
-
3
- const draft = distillBrandIdea({
4
- idea: "Customer support copilot for solo founders called Harbor",
5
- visualDirectionHint: "minimal",
6
- });
7
- const brand = brandContextFromDraft(draft, "tenant_demo");
8
-
9
- process.stdout.write(renderBrandMarkdown(draft, brand));
@@ -1,11 +0,0 @@
1
- import { BrandGenesis } from "../src";
2
-
3
- const genesis = await BrandGenesis.open(".nebutra/brand-genesis-doctor", {
4
- tenantId: "tenant_demo",
5
- });
6
-
7
- try {
8
- process.stdout.write(`${JSON.stringify(await genesis.doctor(), null, 2)}\n`);
9
- } finally {
10
- await genesis.close();
11
- }
@@ -1,27 +0,0 @@
1
- import { BrandGenesis } from "../src";
2
-
3
- const genesis = await BrandGenesis.open(".nebutra/brand-genesis-example", {
4
- tenantId: "tenant_demo",
5
- });
6
-
7
- try {
8
- const result = await genesis.run({
9
- idea: "AI debugging for indie devs called Loop",
10
- visualDirectionHint: "cyberpunk",
11
- });
12
-
13
- process.stdout.write(
14
- `${JSON.stringify(
15
- {
16
- brand: result.brand.name,
17
- brandMd: result.brandMdPath,
18
- film: result.film.path,
19
- eventId: result.eventId,
20
- },
21
- null,
22
- 2,
23
- )}\n`,
24
- );
25
- } finally {
26
- await genesis.close();
27
- }
@@ -1,84 +0,0 @@
1
- ---
2
- name: brand_film_60s
3
- kind: play
4
- version: 1.0.0
5
- description: From one idea to a brand system, generated assets, narration, and a 60s film manifest
6
- inputs:
7
- idea:
8
- type: string
9
- max_length: 500
10
- description: One-sentence company idea
11
- founder_voice_id:
12
- type: string
13
- optional: true
14
- description: Enrolled voice profile for narration
15
- visual_direction_hint:
16
- type: enum
17
- options: [cyberpunk, minimal, organic, playful, corporate, retro, futurist]
18
- optional: true
19
- outputs:
20
- brand_md: { type: file, path: company/BRAND.md, mime: text/markdown }
21
- logo: { type: file, path: company/assets/logo.svg, mime: image/svg+xml }
22
- palette: { type: file, path: company/assets/palette.json, mime: application/json }
23
- film: { type: file, path: company/film_60s.mp4, mime: video/mp4 }
24
- landing: { type: file, path: company/landing/index.html, mime: text/html }
25
- bgm: { type: file, path: company/audio/bgm.wav, mime: audio/wav }
26
- budget:
27
- duration_s: 300
28
- cost_usd: 5
29
- alert_at_pct: 80
30
- required_skills:
31
- - image_pipeline.generate
32
- - video_pipeline.plan
33
- - video_pipeline.render
34
- - video_pipeline.compose
35
- - audio_pipeline.generate
36
- - voice_realtime.synthesize_narration
37
- - mesh_pipeline.from_image
38
- - content_store.write
39
- required_plays:
40
- - one_pager
41
- sub_agents:
42
- - role: brand_strategist
43
- allowed_skills: [llm_gateway.complete, content_store.write]
44
- - role: visual_designer
45
- allowed_skills: [image_pipeline.generate, mesh_pipeline.from_image, content_store.write]
46
- - role: video_director
47
- allowed_skills: [video_pipeline.plan, video_pipeline.render, video_pipeline.compose]
48
- - role: music_composer
49
- allowed_skills: [audio_pipeline.generate]
50
- - role: narrator
51
- allowed_skills: [voice_realtime.synthesize_narration]
52
- - role: web_builder
53
- allowed_skills: [play_loader.run]
54
- depends_on_plays: []
55
- checkpoints:
56
- - after_step: brand_distillation
57
- - after_step: visual_direction
58
- - after_step: assets_generated
59
- - after_step: video_rendered
60
- - after_step: final_compose
61
- ---
62
-
63
- ## What this play does
64
-
65
- Creates a first brand package from one short company idea. The Play must first
66
- materialize `company/BRAND.md`; every downstream media call reads the resulting
67
- BrandContext instead of inventing its own style.
68
-
69
- ## Steps
70
-
71
- 1. Distill the idea into a compact brand identity.
72
- 2. Choose one visual direction and write `company/BRAND.md`.
73
- 3. Generate independent visual assets in parallel.
74
- 4. Plan the storyboard before any video rendering.
75
- 5. Render video, then generate music and narration with the final timing.
76
- 6. Compose the film manifest and write a landing handoff manifest.
77
- 7. Commit the resulting paths to the event log.
78
-
79
- ## Anti-patterns
80
-
81
- - Do not generate assets without BrandContext.
82
- - Do not define image, video, audio, voice, or mesh generation logic here.
83
- - Do not skip storyboard planning.
84
- - Do not hardcode one visual style across all companies.
@@ -1,5 +0,0 @@
1
- {
2
- "tenantId": "tenant_demo",
3
- "idea": "AI debugging for indie devs called Loop",
4
- "visualDirectionHint": "cyberpunk"
5
- }
@@ -1,5 +0,0 @@
1
- {
2
- "tenantId": "tenant_demo",
3
- "idea": "Customer support copilot for solo founders called Harbor",
4
- "visualDirectionHint": "minimal"
5
- }
@@ -1,5 +0,0 @@
1
- {
2
- "tenantId": "tenant_demo",
3
- "idea": "Analytics workspace for creator businesses called Signal Garden",
4
- "visualDirectionHint": "organic"
5
- }
@@ -1,29 +0,0 @@
1
- ---
2
- type: brand_profile
3
- brand_id: {{brand_id}}
4
- name: {{name}}
5
- ---
6
-
7
- # {{name}}
8
-
9
- {{one_liner}}
10
-
11
- ## Tagline
12
-
13
- {{tagline}}
14
-
15
- ## Audience
16
-
17
- {{target_audience}}
18
-
19
- ## Tone
20
-
21
- {{tone_keywords}}
22
-
23
- ## Visual Direction
24
-
25
- {{visual_style}}
26
-
27
- ## Differentiation
28
-
29
- {{differentiation}}
@@ -1,4 +0,0 @@
1
- {
2
- "brandId": "{{brand_id}}",
3
- "colors": []
4
- }
package/src/cli.ts DELETED
@@ -1,64 +0,0 @@
1
- import { mkdir, rm, stat } from "node:fs/promises";
2
- import { join } from "node:path";
3
- import { BrandGenesis, readBrandGenesisDebug } from "./index";
4
-
5
- const command = process.argv[2] ?? "doctor";
6
- const root = process.env.BRAND_GENESIS_ROOT ?? ".nebutra/brand-genesis";
7
- const tenantId = process.env.NEBUTRA_TENANT_ID ?? "local";
8
-
9
- async function sleep(ms: number): Promise<void> {
10
- await new Promise((resolve) => setTimeout(resolve, ms));
11
- }
12
-
13
- async function acquireCliLock(rootPath: string): Promise<() => Promise<void>> {
14
- const lockPath = join(rootPath, ".cli.lock");
15
- await mkdir(rootPath, { recursive: true });
16
- for (let attempt = 0; attempt < 40; attempt += 1) {
17
- try {
18
- await mkdir(lockPath);
19
- return async () => {
20
- await rm(lockPath, { recursive: true, force: true });
21
- };
22
- } catch (error) {
23
- const code = (error as NodeJS.ErrnoException).code;
24
- if (code !== "EEXIST") throw error;
25
- const lockStat = await stat(lockPath).catch(() => ({ mtimeMs: Date.now() }));
26
- if (Date.now() - lockStat.mtimeMs > 30_000) {
27
- await rm(lockPath, { recursive: true, force: true });
28
- continue;
29
- }
30
- await sleep(50);
31
- }
32
- }
33
- throw new Error("brand-genesis CLI is busy. Suggestion: wait a moment and retry the command.");
34
- }
35
-
36
- if (command === "doctor") {
37
- const releaseLock = await acquireCliLock(root);
38
- const genesis = await BrandGenesis.open(root, { tenantId });
39
- try {
40
- process.stdout.write(`${JSON.stringify(await genesis.doctor(), null, 2)}\n`);
41
- } finally {
42
- await genesis.close();
43
- await releaseLock();
44
- }
45
- } else if (command === "quickstart") {
46
- const idea = process.argv.slice(3).join(" ") || "AI debugging for indie devs called Loop";
47
- const releaseLock = await acquireCliLock(root);
48
- const genesis = await BrandGenesis.open(root, { tenantId });
49
- try {
50
- process.stdout.write(
51
- `${JSON.stringify({ capability: "brand-genesis", result: await genesis.run({ idea }) }, null, 2)}\n`,
52
- );
53
- } finally {
54
- await genesis.close();
55
- await releaseLock();
56
- }
57
- } else if (command === "debug") {
58
- process.stdout.write(
59
- `${JSON.stringify({ capability: "brand-genesis", entries: await readBrandGenesisDebug() }, null, 2)}\n`,
60
- );
61
- } else {
62
- process.stderr.write(`Unknown brand-genesis command: ${command}\n`);
63
- process.exitCode = 1;
64
- }
package/src/index.test.ts DELETED
@@ -1,123 +0,0 @@
1
- import { mkdtemp, readFile, rm } from "node:fs/promises";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
- import { parsePlayMarkdown } from "@nebutra/play-loader";
5
- import { afterEach, describe, expect, it } from "vitest";
6
- import {
7
- BrandGenesis,
8
- brandContextFromDraft,
9
- distillBrandIdea,
10
- readBrandGenesisDebug,
11
- renderBrandMarkdown,
12
- } from "./index";
13
-
14
- let root: string | undefined;
15
- let genesis: BrandGenesis | undefined;
16
-
17
- afterEach(async () => {
18
- if (genesis) await genesis.close();
19
- if (root) await rm(root, { recursive: true, force: true });
20
- root = undefined;
21
- genesis = undefined;
22
- });
23
-
24
- async function open(tenantId = "tenant_demo"): Promise<BrandGenesis> {
25
- root = await mkdtemp(join(tmpdir(), "brand-genesis-"));
26
- genesis = await BrandGenesis.open(root, { tenantId });
27
- return genesis;
28
- }
29
-
30
- describe("brand-genesis", () => {
31
- it("distills an idea into a BrandContext without owning generation primitives", () => {
32
- const draft = distillBrandIdea({
33
- idea: "AI debugging for indie devs called Loop",
34
- visualDirectionHint: "cyberpunk",
35
- });
36
- const brand = brandContextFromDraft(draft, "tenant_a");
37
- const markdown = renderBrandMarkdown(draft, brand);
38
-
39
- expect(draft.name).toBe("Loop");
40
- expect(brand).toMatchObject({
41
- tenantId: "tenant_a",
42
- brandId: "loop",
43
- sourcePath: "company/BRAND.md",
44
- });
45
- expect(markdown).toContain("type: brand_profile");
46
- expect(markdown).toContain("Debug like it is a conversation");
47
- });
48
-
49
- it("runs the brand_film_60s play through lower capabilities and writes checkpoints", async () => {
50
- const runtime = await open("tenant_a");
51
-
52
- const result = await runtime.run({
53
- idea: "AI debugging for indie devs called Loop",
54
- visualDirectionHint: "cyberpunk",
55
- founderVoiceId: "founder_voice",
56
- });
57
-
58
- expect(result.brand.name).toBe("Loop");
59
- expect(result.logo.brandId).toBe(result.brand.brandId);
60
- expect(result.mesh.brandId).toBe(result.brand.brandId);
61
- expect(result.film.kind).toBe("video");
62
- expect(result.bgm.license.status).toBe("commercial-ok");
63
- expect(result.narration.voiceProfileId).toBe("founder_voice");
64
- expect(result.checkpoints).toEqual([
65
- "brand_distillation",
66
- "visual_direction",
67
- "assets_generated",
68
- "video_rendered",
69
- "final_compose",
70
- ]);
71
- await expect(readBrandGenesisDebug(root)).resolves.toEqual(expect.any(Array));
72
- });
73
-
74
- it("requires tenant context before persistent operations", async () => {
75
- root = await mkdtemp(join(tmpdir(), "brand-genesis-"));
76
- const runtime = await BrandGenesis.open(root);
77
- genesis = runtime;
78
-
79
- await expect(runtime.run({ tenantId: "", idea: "AI tool called Loop" })).rejects.toMatchObject({
80
- capability: "brand-genesis",
81
- suggestion: expect.stringContaining("tenantId"),
82
- });
83
- });
84
-
85
- it("keeps the flagship Play as SKILL.md instead of a new workflow format", async () => {
86
- const skill = await readFile(join(process.cwd(), "plays", "brand_film_60s", "SKILL.md"), {
87
- encoding: "utf8",
88
- }).catch(async () =>
89
- readFile(
90
- join(
91
- process.cwd(),
92
- "packages",
93
- "ai",
94
- "brand-genesis",
95
- "plays",
96
- "brand_film_60s",
97
- "SKILL.md",
98
- ),
99
- "utf8",
100
- ),
101
- );
102
- const play = parsePlayMarkdown(skill);
103
-
104
- expect(play.meta).toMatchObject({
105
- name: "brand_film_60s",
106
- kind: "play",
107
- version: "1.0.0",
108
- });
109
- expect(play.requiredSkills).toContain("image_pipeline.generate");
110
- expect(play.requiredSkills).toContain("content_store.write");
111
- expect(play.subAgents.map((agent) => agent.role)).toContain("visual_designer");
112
- });
113
-
114
- it("reports doctor health from delegated media capabilities", async () => {
115
- const runtime = await open("tenant_a");
116
-
117
- await expect(runtime.doctor()).resolves.toMatchObject({
118
- capability: "brand-genesis",
119
- ok: true,
120
- play: { ok: true, name: "brand_film_60s" },
121
- });
122
- });
123
- });
package/src/index.ts DELETED
@@ -1,514 +0,0 @@
1
- import { mkdir } from "node:fs/promises";
2
- import { dirname, join } from "node:path";
3
- import { type MeshAsset, MeshPipeline } from "@nebutra/3d-pipeline";
4
- import { type AudioAsset, AudioPipeline } from "@nebutra/audio-pipeline";
5
- import { requireCapabilityTenant } from "@nebutra/capability-kit";
6
- import { appendCapabilityDebug, readCapabilityDebug } from "@nebutra/capability-kit/debug";
7
- import { ContentStore, serializeContentFrontmatter } from "@nebutra/content-store";
8
- import { CapabilityError } from "@nebutra/errors";
9
- import { EventLog } from "@nebutra/event-log";
10
- import {
11
- assetId,
12
- type BrandColor,
13
- type BrandContext,
14
- type VisualStyle,
15
- } from "@nebutra/generation-context";
16
- import { type ImageAsset, ImagePipeline } from "@nebutra/image-pipeline";
17
- import { type Storyboard, type VideoAsset, VideoPipeline } from "@nebutra/video-pipeline";
18
- import { type VoiceAsset, VoiceRealtime } from "@nebutra/voice-realtime";
19
-
20
- export type VisualDirectionHint =
21
- | "cyberpunk"
22
- | "minimal"
23
- | "organic"
24
- | "playful"
25
- | "corporate"
26
- | "retro"
27
- | "futurist";
28
-
29
- export interface BrandFilmInput {
30
- readonly tenantId?: string;
31
- readonly idea: string;
32
- readonly founderVoiceId?: string;
33
- readonly visualDirectionHint?: VisualDirectionHint;
34
- }
35
-
36
- export interface BrandIdentityDraft {
37
- readonly name: string;
38
- readonly oneLiner: string;
39
- readonly tagline: string;
40
- readonly targetAudience: string;
41
- readonly toneKeywords: readonly string[];
42
- readonly differentiation: string;
43
- readonly visualStyle: VisualStyle;
44
- }
45
-
46
- export interface BrandPackage {
47
- readonly tenantId: string;
48
- readonly play: "brand_film_60s";
49
- readonly brand: BrandContext;
50
- readonly draft: BrandIdentityDraft;
51
- readonly brandMdPath: string;
52
- readonly palettePath: string;
53
- readonly landingPath: string;
54
- readonly logo: ImageAsset;
55
- readonly hero: ImageAsset;
56
- readonly icon: ImageAsset;
57
- readonly mesh: MeshAsset;
58
- readonly storyboard: Storyboard;
59
- readonly film: VideoAsset;
60
- readonly bgm: AudioAsset;
61
- readonly narration: VoiceAsset;
62
- readonly eventId: string;
63
- readonly checkpoints: readonly string[];
64
- }
65
-
66
- export interface BrandGenesisDoctorReport {
67
- readonly capability: "brand-genesis";
68
- readonly ok: boolean;
69
- readonly checkedAt: string;
70
- readonly play: {
71
- readonly ok: boolean;
72
- readonly name: "brand_film_60s";
73
- readonly requiredSkills: readonly string[];
74
- };
75
- readonly media: {
76
- readonly image: readonly unknown[];
77
- readonly video: readonly unknown[];
78
- readonly audio: readonly unknown[];
79
- readonly voice: readonly unknown[];
80
- readonly mesh: readonly unknown[];
81
- };
82
- readonly suggestion?: string;
83
- }
84
-
85
- export interface BrandGenesisOptions {
86
- readonly tenantId?: string;
87
- readonly root?: string;
88
- readonly debugRoot?: string;
89
- readonly contentStore?: ContentStore;
90
- readonly eventLog?: EventLog;
91
- readonly imagePipeline?: ImagePipeline;
92
- readonly videoPipeline?: VideoPipeline;
93
- readonly audioPipeline?: AudioPipeline;
94
- readonly voiceRealtime?: VoiceRealtime;
95
- readonly meshPipeline?: MeshPipeline;
96
- }
97
-
98
- const PLAY_NAME = "brand_film_60s" as const;
99
- const CHECKPOINTS = [
100
- "brand_distillation",
101
- "visual_direction",
102
- "assets_generated",
103
- "video_rendered",
104
- "final_compose",
105
- ] as const;
106
-
107
- function normalizeBrandId(name: string): string {
108
- return name
109
- .slice(0, 200)
110
- .toLowerCase()
111
- .replace(/[^a-z0-9]{1,200}/g, "_")
112
- .replace(/^_{1,200}|_{1,200}$/g, "")
113
- .slice(0, 32);
114
- }
115
-
116
- function pickName(idea: string): string {
117
- const called = idea.match(/\bcalled\s+([A-Z][a-zA-Z0-9]*(?:\s+[A-Z][a-zA-Z0-9]*)?)/);
118
- if (called?.[1]) return called[1].trim();
119
- const capitalized = [...idea.matchAll(/\b[A-Z][a-zA-Z0-9]{2,}\b/g)]
120
- .map((match) => match[0])
121
- .filter((value) => !["AI", "SaaS", "API"].includes(value));
122
- return capitalized.at(-1) ?? "Venture";
123
- }
124
-
125
- function paletteFor(hint: VisualDirectionHint | undefined): readonly BrandColor[] {
126
- switch (hint) {
127
- case "cyberpunk":
128
- case "futurist":
129
- return [
130
- { name: "electric cyan", hex: "#00D4FF", role: "primary" },
131
- { name: "carbon black", hex: "#111318", role: "background" },
132
- { name: "signal amber", hex: "#F3C14B", role: "accent" },
133
- ];
134
- case "organic":
135
- return [
136
- { name: "moss", hex: "#3D7A57", role: "primary" },
137
- { name: "paper", hex: "#F7F4EA", role: "background" },
138
- { name: "clay", hex: "#C86B4A", role: "accent" },
139
- ];
140
- case "playful":
141
- return [
142
- { name: "coral", hex: "#FF6B6B", role: "primary" },
143
- { name: "ink", hex: "#202124", role: "neutral" },
144
- { name: "mint", hex: "#7CE2C6", role: "accent" },
145
- ];
146
- case "corporate":
147
- return [
148
- { name: "trust blue", hex: "#2454D6", role: "primary" },
149
- { name: "slate", hex: "#202A36", role: "neutral" },
150
- { name: "clear sky", hex: "#E8F0FF", role: "background" },
151
- ];
152
- case "retro":
153
- return [
154
- { name: "oxide", hex: "#B95F3B", role: "primary" },
155
- { name: "night ink", hex: "#18202A", role: "neutral" },
156
- { name: "cream light", hex: "#F8E7C9", role: "background" },
157
- ];
158
- default:
159
- return [
160
- { name: "graphite", hex: "#1F2933", role: "primary" },
161
- { name: "white", hex: "#FFFFFF", role: "background" },
162
- { name: "signal green", hex: "#00A693", role: "accent" },
163
- ];
164
- }
165
- }
166
-
167
- function styleFor(hint: VisualDirectionHint | undefined): VisualStyle {
168
- const name = hint ?? "minimal";
169
- const keywordsByHint: Record<VisualDirectionHint, readonly string[]> = {
170
- cyberpunk: ["electric", "terminal-native", "high-contrast"],
171
- minimal: ["calm", "precise", "spacious"],
172
- organic: ["warm", "natural", "human"],
173
- playful: ["bright", "friendly", "kinetic"],
174
- corporate: ["credible", "structured", "clear"],
175
- retro: ["nostalgic", "tactile", "characterful"],
176
- futurist: ["clean", "technical", "forward"],
177
- };
178
- return {
179
- name,
180
- keywords: keywordsByHint[name],
181
- avoid: ["generic stock", "dark horror", "visual clutter"],
182
- };
183
- }
184
-
185
- export function distillBrandIdea(input: BrandFilmInput): BrandIdentityDraft {
186
- const idea = input.idea.trim();
187
- if (idea.length === 0) {
188
- throw new CapabilityError("brand-genesis", "Brand idea is empty", {
189
- suggestion: "Pass a one-sentence company idea before running Brand Genesis.",
190
- statusCode: 400,
191
- });
192
- }
193
- const name = pickName(idea);
194
- const devAudience = /\bdev|debug|code|developer|engineering/i.test(idea);
195
- const audience = devAudience
196
- ? "Independent developers and small engineering teams shipping software quickly"
197
- : "Early-stage founders validating a focused product wedge";
198
- const toneKeywords = devAudience
199
- ? ["technical", "direct", "warm"]
200
- : ["clear", "confident", "useful"];
201
- return {
202
- name,
203
- oneLiner: idea,
204
- tagline: devAudience ? "Debug like it is a conversation" : `${name} turns intent into launch`,
205
- targetAudience: audience,
206
- toneKeywords,
207
- differentiation: devAudience
208
- ? "Understands the full production context instead of treating each error as an isolated message"
209
- : "Combines brand, execution, and company memory in one repeatable workflow",
210
- visualStyle: styleFor(input.visualDirectionHint),
211
- };
212
- }
213
-
214
- export function brandContextFromDraft(
215
- draft: BrandIdentityDraft,
216
- tenantId: string,
217
- sourcePath = "company/BRAND.md",
218
- palette = paletteFor(draft.visualStyle.name as VisualDirectionHint),
219
- ): BrandContext {
220
- return {
221
- tenantId,
222
- brandId: normalizeBrandId(draft.name),
223
- name: draft.name,
224
- palette,
225
- typography: {
226
- heading: draft.visualStyle.name === "cyberpunk" ? "Geist Mono" : "Geist Sans",
227
- body: "Geist Sans",
228
- accent: "Geist Mono",
229
- },
230
- visualStyle: draft.visualStyle,
231
- referenceImages: [],
232
- forbidden: draft.visualStyle.avoid ?? [],
233
- toneKeywords: draft.toneKeywords,
234
- sourcePath,
235
- };
236
- }
237
-
238
- export function renderBrandMarkdown(draft: BrandIdentityDraft, brand: BrandContext): string {
239
- return serializeContentFrontmatter(
240
- {
241
- type: "brand_profile",
242
- brand_id: brand.brandId,
243
- name: brand.name,
244
- },
245
- [
246
- `# ${brand.name}`,
247
- "",
248
- draft.oneLiner,
249
- "",
250
- "## Tagline",
251
- "",
252
- draft.tagline,
253
- "",
254
- "## Audience",
255
- "",
256
- draft.targetAudience,
257
- "",
258
- "## Tone",
259
- "",
260
- brand.toneKeywords.join(", "),
261
- "",
262
- "## Visual Direction",
263
- "",
264
- `${brand.visualStyle.name}: ${brand.visualStyle.keywords.join(", ")}`,
265
- "",
266
- "## Differentiation",
267
- "",
268
- draft.differentiation,
269
- "",
270
- ].join("\n"),
271
- );
272
- }
273
-
274
- function renderLandingManifest(draft: BrandIdentityDraft, brand: BrandContext): string {
275
- return [
276
- "<!doctype html>",
277
- '<html lang="en">',
278
- "<head>",
279
- ' <meta charset="utf-8" />',
280
- ` <title>${brand.name}</title>`,
281
- "</head>",
282
- "<body>",
283
- ` <main data-brand-id="${brand.brandId}">`,
284
- ` <h1>${brand.name}</h1>`,
285
- ` <p>${draft.tagline}</p>`,
286
- ` <p>${draft.oneLiner}</p>`,
287
- " </main>",
288
- "</body>",
289
- "</html>",
290
- "",
291
- ].join("\n");
292
- }
293
-
294
- export class BrandGenesis {
295
- readonly #tenantId: string | undefined;
296
- readonly #root: string;
297
- readonly #debugRoot: string;
298
- readonly #contentStore: ContentStore;
299
- readonly #eventLog: EventLog;
300
- readonly #image: ImagePipeline;
301
- readonly #video: VideoPipeline;
302
- readonly #audio: AudioPipeline;
303
- readonly #voice: VoiceRealtime;
304
- readonly #mesh: MeshPipeline;
305
-
306
- private constructor(
307
- options: BrandGenesisOptions & { contentStore: ContentStore; eventLog: EventLog },
308
- ) {
309
- this.#tenantId = options.tenantId;
310
- this.#root = options.root ?? join(process.cwd(), ".nebutra", "brand-genesis");
311
- this.#debugRoot = options.debugRoot ?? process.cwd();
312
- this.#contentStore = options.contentStore;
313
- this.#eventLog = options.eventLog;
314
- this.#image = options.imagePipeline ?? new ImagePipeline({ root: this.#root });
315
- this.#video = options.videoPipeline ?? new VideoPipeline({ root: this.#root });
316
- this.#audio = options.audioPipeline ?? new AudioPipeline({ root: this.#root });
317
- this.#voice = options.voiceRealtime ?? new VoiceRealtime({ root: this.#root });
318
- this.#mesh = options.meshPipeline ?? new MeshPipeline({ root: this.#root });
319
- }
320
-
321
- static async open(
322
- root = ".nebutra/brand-genesis",
323
- options: Omit<BrandGenesisOptions, "root" | "contentStore" | "eventLog"> = {},
324
- ): Promise<BrandGenesis> {
325
- const tenantId = options.tenantId ?? "local";
326
- await mkdir(root, { recursive: true });
327
- const contentStore = await ContentStore.open(join(root, "content"), { tenantId });
328
- const eventLog = await EventLog.open(join(root, "event-log"), { tenantId });
329
- return new BrandGenesis({ ...options, tenantId, root, contentStore, eventLog });
330
- }
331
-
332
- async run(input: BrandFilmInput): Promise<BrandPackage> {
333
- const tenantId = requireCapabilityTenant({
334
- explicit: input.tenantId,
335
- fallback: this.#tenantId,
336
- onMissing: () =>
337
- new CapabilityError("brand-genesis", "Brand Genesis requires tenant context", {
338
- suggestion: "Pass tenantId on the input or construct BrandGenesis with tenantId.",
339
- statusCode: 400,
340
- }),
341
- });
342
- const draft = distillBrandIdea(input);
343
- const brand = brandContextFromDraft(draft, tenantId);
344
- const brandMarkdown = renderBrandMarkdown(draft, brand);
345
- await this.#contentStore.write(brand.sourcePath, brandMarkdown);
346
- const palettePath = "company/assets/palette.json";
347
- await this.#contentStore.write(
348
- palettePath,
349
- `${JSON.stringify({ brandId: brand.brandId, colors: brand.palette }, null, 2)}\n`,
350
- );
351
- await this.#debug({
352
- type: "checkpoint",
353
- step: CHECKPOINTS[0],
354
- tenantId,
355
- brandId: brand.brandId,
356
- });
357
- await this.#debug({
358
- type: "checkpoint",
359
- step: CHECKPOINTS[1],
360
- tenantId,
361
- brandId: brand.brandId,
362
- });
363
-
364
- const [logo, hero, icon] = await Promise.all([
365
- this.#image.generate({ type: "logo", company: brand.name, oneLiner: draft.oneLiner }, brand),
366
- this.#image.generate({ type: "hero", headline: draft.tagline }, brand),
367
- this.#image.generate({ type: "icon", subject: brand.name }, brand),
368
- ]);
369
- const mesh = await this.#mesh.fromImage(logo, brand);
370
- await this.#debug({
371
- type: "checkpoint",
372
- step: CHECKPOINTS[2],
373
- tenantId,
374
- brandId: brand.brandId,
375
- });
376
-
377
- const storyboard = await this.#video.plan(
378
- { type: "brand-film", durationS: 60, theme: draft.tagline },
379
- brand,
380
- );
381
- const rendered = await this.#video.render(storyboard, brand);
382
- await this.#debug({
383
- type: "checkpoint",
384
- step: CHECKPOINTS[3],
385
- tenantId,
386
- brandId: brand.brandId,
387
- });
388
-
389
- const bgm = await this.#audio.generate(
390
- { type: "bgm", durationS: rendered.durationS, mood: brand.toneKeywords.join(" ") },
391
- brand,
392
- true,
393
- );
394
- const narration = await this.#voice.synthesizeNarration(
395
- {
396
- script: `${draft.tagline}. ${draft.oneLiner}. ${draft.differentiation}.`,
397
- targetDurationS: Math.max(8, Math.min(20, rendered.durationS - 3)),
398
- ...(input.founderVoiceId !== undefined ? { voiceProfileId: input.founderVoiceId } : {}),
399
- },
400
- brand,
401
- );
402
- const film = await this.#video.compose({
403
- videoTrack: [rendered],
404
- audioTrack: [bgm],
405
- voiceTrack: [narration],
406
- captionTrack: [{ startS: 0, endS: narration.durationS, text: narration.transcript }],
407
- });
408
- const landingPath = "company/landing/index.html";
409
- await this.#contentStore.write(landingPath, renderLandingManifest(draft, brand));
410
- await this.#debug({
411
- type: "checkpoint",
412
- step: CHECKPOINTS[4],
413
- tenantId,
414
- brandId: brand.brandId,
415
- });
416
-
417
- const eventId = await this.#eventLog.commit({
418
- traceId: assetId("brand_genesis", brand.brandId),
419
- kind: "content_write",
420
- affected: [
421
- brand.sourcePath,
422
- palettePath,
423
- landingPath,
424
- logo.path,
425
- hero.path,
426
- icon.path,
427
- film.path,
428
- ],
429
- parent: null,
430
- snapshot: {
431
- [brand.sourcePath]: brandMarkdown,
432
- [palettePath]: JSON.stringify({ brandId: brand.brandId, colors: brand.palette }, null, 2),
433
- [landingPath]: renderLandingManifest(draft, brand),
434
- },
435
- });
436
-
437
- const result: BrandPackage = {
438
- tenantId,
439
- play: PLAY_NAME,
440
- brand,
441
- draft,
442
- brandMdPath: brand.sourcePath,
443
- palettePath,
444
- landingPath,
445
- logo,
446
- hero,
447
- icon,
448
- mesh,
449
- storyboard,
450
- film,
451
- bgm,
452
- narration,
453
- eventId,
454
- checkpoints: CHECKPOINTS,
455
- };
456
- await this.#debug({ type: "run", tenantId, brandId: brand.brandId, eventId });
457
- return result;
458
- }
459
-
460
- async doctor(): Promise<BrandGenesisDoctorReport> {
461
- const [image, video, audio, rawVoice, mesh] = await Promise.all([
462
- this.#image.doctor(),
463
- this.#video.doctor(),
464
- this.#audio.doctor(),
465
- this.#voice.doctor(),
466
- this.#mesh.doctor(),
467
- ]);
468
- const voice = [{ provider: "narration-local", ok: true }, ...rawVoice];
469
- const localOk = [image, video, audio, voice, mesh].every((checks) =>
470
- checks.some((check) => Boolean((check as { ok?: boolean }).ok)),
471
- );
472
- return {
473
- capability: "brand-genesis",
474
- ok: localOk,
475
- checkedAt: new Date().toISOString(),
476
- play: {
477
- ok: true,
478
- name: PLAY_NAME,
479
- requiredSkills: [
480
- "image_pipeline.generate",
481
- "video_pipeline.plan",
482
- "video_pipeline.render",
483
- "video_pipeline.compose",
484
- "audio_pipeline.generate",
485
- "voice_realtime.synthesize_narration",
486
- "mesh_pipeline.from_image",
487
- "content_store.write",
488
- ],
489
- },
490
- media: { image, video, audio, voice, mesh },
491
- ...(!localOk
492
- ? {
493
- suggestion:
494
- "Run the individual media doctor commands and configure missing local or remote providers.",
495
- }
496
- : {}),
497
- };
498
- }
499
-
500
- async close(): Promise<void> {
501
- await this.#contentStore.close();
502
- }
503
-
504
- async #debug(entry: Record<string, unknown>): Promise<void> {
505
- await mkdir(dirname(join(this.#debugRoot, ".nebutra", "debug", "brand-genesis.jsonl")), {
506
- recursive: true,
507
- });
508
- await appendCapabilityDebug("brand-genesis", entry, { root: this.#debugRoot });
509
- }
510
- }
511
-
512
- export async function readBrandGenesisDebug(root = process.cwd(), limit = 20): Promise<unknown[]> {
513
- return readCapabilityDebug("brand-genesis", { root, limit });
514
- }
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "rootDir": ".",
6
- "types": ["node", "vitest"]
7
- },
8
- "include": ["src/**/*.ts", "examples/**/*.ts"]
9
- }
package/tsup.config.ts DELETED
@@ -1,11 +0,0 @@
1
- import { defineConfig } from "tsup";
2
-
3
- export default defineConfig({
4
- entry: ["src/index.ts", "src/cli.ts"],
5
- format: ["esm"],
6
- sourcemap: true,
7
- dts: true,
8
- clean: true,
9
- target: "es2022",
10
- external: [/^@nebutra\//],
11
- });