@synap-core/workspace-templates 0.30.0 → 0.32.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 (45) hide show
  1. package/README.md +13 -5
  2. package/agents/hermes.agent.yaml +3 -0
  3. package/dist/{define-DqoItRiR.d.ts → define-DHDi8C33.d.ts} +19 -18
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +428 -239
  6. package/dist/index.js.map +1 -1
  7. package/dist/wire.d.ts +1 -1
  8. package/package.json +1 -1
  9. package/src/brand-library.yaml +0 -6
  10. package/src/builder-dev-fold.template.test.ts +2 -3
  11. package/src/builder-dev-playbooks.template.test.ts +7 -5
  12. package/src/builder.yaml +60 -42
  13. package/src/business-model.yaml +20 -1
  14. package/src/civic-france.yaml +9 -0
  15. package/src/content-creation.yaml +1 -1
  16. package/src/content-os.yaml +22 -18
  17. package/src/crm-absorbs-outreach.template.test.ts +1 -1
  18. package/src/crm-build-plan.template.test.ts +1 -1
  19. package/src/crm.yaml +5 -14
  20. package/src/decisions-wave.template.test.ts +7 -5
  21. package/src/define.primary-surface.test.ts +9 -0
  22. package/src/define.ts +4 -1
  23. package/src/finance.yaml +10 -6
  24. package/src/foundation.yaml +1 -2
  25. package/src/hr.yaml +3 -2
  26. package/src/intent.test.ts +43 -2
  27. package/src/internal-runbook.yaml +0 -1
  28. package/src/kanban-grouping.test.ts +72 -0
  29. package/src/legal.yaml +4 -4
  30. package/src/lifecycle-coverage.test.ts +7 -64
  31. package/src/lifecycle-declarations.test.ts +70 -74
  32. package/src/marketing.yaml +4 -3
  33. package/src/meetings-knowledge.yaml +1 -2
  34. package/src/operations.yaml +13 -9
  35. package/src/process-contract.validate.test.ts +40 -55
  36. package/src/project-management.yaml +2 -2
  37. package/src/publish-official-lib.test.ts +3 -2
  38. package/src/research-base.yaml +12 -5
  39. package/src/research-decision.yaml +18 -2
  40. package/src/ship-a-change.template.test.ts +3 -2
  41. package/src/social.yaml +4 -1
  42. package/src/start.test.ts +22 -0
  43. package/src/templates.ts +324 -183
  44. package/src/types.ts +28 -18
  45. package/src/validate.ts +143 -77
package/src/templates.ts CHANGED
@@ -3286,12 +3286,8 @@ const DATA = {
3286
3286
  "description": "Turn a request for a logo, image, icon or template into a draft built from the approved brand, and approve it with a person before anything uses it.",
3287
3287
  "goalTemplate": "Make this brand asset ({asset}); each stage moves its status. DRAFT: read the request and the approved brand only — approved colours, fonts, references and the active token set; never a draft — and load the creative-director skill to pick the recipe. Make the draft (or up to three variants, each its own asset derived from this one) and record the generator, prompt and parameters on it. APPROVE: a person approves one draft as final; with variants, the approval asks them to `choose` one, your recommendation first, and that choice is the approval. Until then nothing may use it. Deprecating an asset is a person's call.",
3288
3288
  "subjectProfile": {
3289
- "profileSlug": "brand-asset",
3290
- "statusProperty": "asset-status"
3289
+ "profileSlug": "brand-asset"
3291
3290
  },
3292
- "humanOnlyStatuses": [
3293
- "deprecated"
3294
- ],
3295
3291
  "params": [
3296
3292
  {
3297
3293
  "name": "asset",
@@ -3356,12 +3352,8 @@ const DATA = {
3356
3352
  "description": "Draft or revise the brand voice guide from what the brand already publishes, and approve it with a person.",
3357
3353
  "goalTemplate": "Write this brand voice guide ({guide}); each stage moves its status. DRAFT: read the brand identity, the approved assets and the last posts and emails the brand published; write the voice in a few traits, each with a do and a don't taken from real examples, and the words to use and avoid. APPROVE: a person approves the guide; then it is what every draft is checked against. Retiring a guide is a person's call.",
3358
3354
  "subjectProfile": {
3359
- "profileSlug": "brand-voice-guide",
3360
- "statusProperty": "voice-status"
3355
+ "profileSlug": "brand-voice-guide"
3361
3356
  },
3362
- "humanOnlyStatuses": [
3363
- "deprecated"
3364
- ],
3365
3357
  "params": [
3366
3358
  {
3367
3359
  "name": "guide",
@@ -3409,12 +3401,8 @@ const DATA = {
3409
3401
  "description": "Distil approved references into a content guideline (base, format or the frame for one goal), and approve it with a person.",
3410
3402
  "goalTemplate": "Write this content guideline ({guideline}); each stage moves its status. DRAFT: read the brand identity, the approved voice guide and the approved references; load the content-taste skill. Write what to take and what to avoid as rules a maker can follow, link the guideline to every reference it was distilled from, and fill the summary. For a frame guideline, set the goal and give the structure in order. APPROVE: a person approves the guideline; then content is made and checked against it. Retiring a guideline is a person's call.",
3411
3403
  "subjectProfile": {
3412
- "profileSlug": "content-guideline",
3413
- "statusProperty": "guideline-status"
3404
+ "profileSlug": "content-guideline"
3414
3405
  },
3415
- "humanOnlyStatuses": [
3416
- "deprecated"
3417
- ],
3418
3406
  "params": [
3419
3407
  {
3420
3408
  "name": "guideline",
@@ -3545,6 +3533,7 @@ const DATA = {
3545
3533
  },
3546
3534
  "intent": {
3547
3535
  "label": "Product",
3536
+ "primary": "devplane_feature",
3548
3537
  "produces": [
3549
3538
  {
3550
3539
  "profile": "devplane_feature"
@@ -4661,6 +4650,23 @@ const DATA = {
4661
4650
  "icon": "alert-triangle",
4662
4651
  "color": "red",
4663
4652
  "description": "A production incident with severity, status, and root cause tracking",
4653
+ "lifecycle": {
4654
+ "property": "incidentStatus",
4655
+ "options": [
4656
+ {
4657
+ "key": "open",
4658
+ "category": "open"
4659
+ },
4660
+ {
4661
+ "key": "investigating",
4662
+ "category": "active"
4663
+ },
4664
+ {
4665
+ "key": "resolved",
4666
+ "category": "done"
4667
+ }
4668
+ ]
4669
+ },
4664
4670
  "properties": [
4665
4671
  {
4666
4672
  "slug": "severity",
@@ -5594,6 +5600,27 @@ const DATA = {
5594
5600
  "icon": "workflow",
5595
5601
  "color": "blue",
5596
5602
  "description": "A user flow or business process — a sequence of steps through system components",
5603
+ "lifecycle": {
5604
+ "property": "workflowStatus",
5605
+ "options": [
5606
+ {
5607
+ "key": "documented",
5608
+ "category": "open"
5609
+ },
5610
+ {
5611
+ "key": "in-progress",
5612
+ "category": "active"
5613
+ },
5614
+ {
5615
+ "key": "needs-review",
5616
+ "category": "active"
5617
+ },
5618
+ {
5619
+ "key": "complete",
5620
+ "category": "done"
5621
+ }
5622
+ ]
5623
+ },
5597
5624
  "properties": [
5598
5625
  {
5599
5626
  "slug": "workflowStatus",
@@ -5934,10 +5961,52 @@ const DATA = {
5934
5961
  "slug": "task-board",
5935
5962
  "type": "kanban",
5936
5963
  "scopeProfileSlug": "task",
5937
- "groupBy": "task-status",
5964
+ "config": {
5965
+ "groupByField": "task-status"
5966
+ },
5938
5967
  "defaultView": true,
5939
5968
  "description": "All delegated tasks by status: Backlog → Queued → Running → Review → Done."
5940
5969
  },
5970
+ {
5971
+ "name": "Feature Board",
5972
+ "slug": "feature-board",
5973
+ "type": "kanban",
5974
+ "scopeProfileSlug": "devplane_feature",
5975
+ "description": "Features by stage, Idea to Shipped.",
5976
+ "config": {
5977
+ "groupByField": "featureStatus"
5978
+ }
5979
+ },
5980
+ {
5981
+ "name": "Story Board",
5982
+ "slug": "story-board",
5983
+ "type": "kanban",
5984
+ "scopeProfileSlug": "devplane_story",
5985
+ "description": "User stories by status, Draft to Done.",
5986
+ "config": {
5987
+ "groupByField": "storyStatus"
5988
+ }
5989
+ },
5990
+ {
5991
+ "name": "Issue Board",
5992
+ "slug": "issue-board",
5993
+ "type": "kanban",
5994
+ "scopeProfileSlug": "issue",
5995
+ "description": "Bugs and problems by status, Open to Fixed.",
5996
+ "config": {
5997
+ "groupByField": "issueStatus"
5998
+ }
5999
+ },
6000
+ {
6001
+ "name": "Design Board",
6002
+ "slug": "design-board",
6003
+ "type": "kanban",
6004
+ "scopeProfileSlug": "ui-design",
6005
+ "description": "Designs by status, from draft to implemented.",
6006
+ "config": {
6007
+ "groupByField": "design-status"
6008
+ }
6009
+ },
5941
6010
  {
5942
6011
  "name": "Deployments",
5943
6012
  "type": "calendar",
@@ -5981,7 +6050,9 @@ const DATA = {
5981
6050
  "slug": "service-health",
5982
6051
  "type": "kanban",
5983
6052
  "scopeProfileSlug": "devplane_service",
5984
- "groupBy": "serviceStatus",
6053
+ "config": {
6054
+ "groupByField": "serviceStatus"
6055
+ },
5985
6056
  "description": "Every service by health — healthy, degraded, down, maintenance."
5986
6057
  },
5987
6058
  {
@@ -5989,7 +6060,9 @@ const DATA = {
5989
6060
  "slug": "services-by-type",
5990
6061
  "type": "kanban",
5991
6062
  "scopeProfileSlug": "devplane_service",
5992
- "groupBy": "serviceType",
6063
+ "config": {
6064
+ "groupByField": "serviceType"
6065
+ },
5993
6066
  "description": "Services grouped by what they are — API, worker, cron, database, cache, queue."
5994
6067
  },
5995
6068
  {
@@ -6129,13 +6202,8 @@ const DATA = {
6129
6202
  "description": "Take a UI design request from three variants built only of real Storybook components, through a rubric critique and a person's review on the canvas, to a pull request verified by the gates, a before/after compare and a walk in the running app.",
6130
6203
  "goalTemplate": "Take this UI design ({design}) for {surface} from draft to implemented. Load the designing-with-real-components skill first, and design-critique for the Critique stage. GENERATE: read the Storybook component manifest (/manifests/components.json, or the Storybook MCP), the design's goal and scope and the entities it references, and write THREE variants as Puck JSON — this design and two sibling ui-designs sharing its variant-group — using ONLY components the manifest lists, with props each one declares, design tokens and named motion presets only; each variant lays out every state the screen has (empty, loading, failed, full, long content); fill components-used from the JSON and set schema-version. CRITIQUE: judge each variant with the design-critique rubric and write the findings into its critique; a checked or pattern blocker sends the run back to Generate; opinions are never applied. REVIEW: a person compares the variants on the canvas and approves one; nothing is implemented from an unapproved design, and only a person sets approved. IMPLEMENT: read design-json and the Storybook MCP, build the screen from those same real components, open a pull request and record its URL in implementation-pr and the built screen's story in implemented-story-id. VERIFY: typecheck, story coverage, interaction and accessibility tests, visual regression and the token guards are green, the implemented story was captured and compared with the design and the current story, and the screen was walked in the running app. Move the design's status only through its lifecycle (update_entity with expectedStatus); never invent a status.",
6131
6204
  "subjectProfile": {
6132
- "profileSlug": "ui-design",
6133
- "statusProperty": "design-status"
6205
+ "profileSlug": "ui-design"
6134
6206
  },
6135
- "humanOnlyStatuses": [
6136
- "approved",
6137
- "archived"
6138
- ],
6139
6207
  "activators": [
6140
6208
  {
6141
6209
  "on": "manual",
@@ -6652,13 +6720,8 @@ const DATA = {
6652
6720
  "description": "Take a shaped change from branch to pull request, green checks, merge, lab and a dogfood walk, until its criteria are verified. The facts (PR opened, CI finished, merged, deployed) move the step; the person approves only the lab deploy.",
6653
6721
  "goalTemplate": "Ship this change ({feature}) through one session, one branch and its pull requests, then the merge, the lab and a dogfood walk, until its criteria are verified. The step follows the work; move the feature's status only through its lifecycle (update_entity with expectedStatus), never invent one. SHAPE: write the end state and 2-5 binary criteria on this session, set the feature's change type (feature, refactor or chore), and name the repos it touches. BUILD: branch <type>/<slug> from origin/main in your own worktree, commit in verified slices, and run the smallest gate that answers for each finished slice, with its negative control; quote the output. PR OPENED: open a draft pull request whose body carries the line \"Pod session: <this session id>\", and record it on this session as the outcome pr-<repo>-<number> (kind pull_request, ref url); one outcome per pull request, and for each a session criterion keyed the same, \"<repo>#<number> is merged\", checked by the capability github_check_pr_merged, so the pod grades the merge itself. CHECKS: read the checks on the pull request's head with github_pr_checks (the github-read capability, on the person's own token) or wait for the ci.finished event; a red check sends the work back to Build. MERGE: a person merges; never merge and never push to main. The merge marks the outcome met. DEPLOY: ask the person for the lab deploy (synap_request_deploy_approval); the deploy is their call. DOGFOOD: walk the change in the running lab as a person would and report WORKS, BROKEN or CANNOT-TELL with what was seen. VERIFY: grade every criterion with its evidence, and separate VERIFIED (gate or check output quoted) from NEEDS-DOGFOOD.",
6654
6722
  "subjectProfile": {
6655
- "profileSlug": "devplane_feature",
6656
- "statusProperty": "featureStatus"
6723
+ "profileSlug": "devplane_feature"
6657
6724
  },
6658
- "humanOnlyStatuses": [
6659
- "backlog",
6660
- "cancelled"
6661
- ],
6662
6725
  "activators": [
6663
6726
  {
6664
6727
  "on": "enters_status",
@@ -6907,21 +6970,12 @@ const DATA = {
6907
6970
  },
6908
6971
  {
6909
6972
  "name": "Build a change",
6910
- "description": "Dev set (decision d05), key: build. Works one feature (devplane_feature) from shaped criteria to a verified change on main; its stages follow the feature's lifecycle (spec, in_progress, in_review, done), and a cancelled or failed session puts the feature back to spec so nothing is left half-claimed. One feature per session, never two subjects (founder default, 2026-11-05). A quick change is this playbook with size small (no plan); a night shift run is this playbook with unattended true. No activators until binding is turned on; the shape would be {on: enters_status, status: spec, size: per_thing, mode: propose}, the trigger Ship a change uses today. Reuses Ship a change (2c5aa553) stage text and evidence keys; absorbs AI Dev Session and Quick change once they are re-pointed. Draft until the founder activates it.",
6973
+ "description": "Dev set (decision d05), key: build. Works one feature (devplane_feature) from shaped criteria to a verified change on main; its stages follow the feature's lifecycle (spec, in_progress, in_review, done); a cancelled or failed session leaves the feature where it is. One feature per session, never two subjects (founder default, 2026-11-05). A quick change is this playbook with size small (no plan); a night shift run is this playbook with unattended true. No activators until binding is turned on; the shape would be {on: enters_status, status: spec, size: per_thing, mode: propose}, the trigger Ship a change uses today. Reuses Ship a change (2c5aa553) stage text and evidence keys; absorbs AI Dev Session and Quick change once they are re-pointed. Draft until the founder activates it.",
6911
6974
  "goalTemplate": "Build {feature} through one session and one PR per repo (or gated commits on main in a private repo), size {size}. SHAPE: write the end state and 2-5 binary criteria on this session (plan skill, skipped when size is small). BUILD: branch <type>/<slug> from origin/main in your own worktree, commit in verified slices, run the smallest gate that answers with its negative control, quote the output. LAND: follow the land stages (Change proposed, Checks green, Landed on main, Deployed to lab, Dogfooded, Criteria verified). Unattended: {unattended}. When unattended is true, ask no person, stop at a draft PR or a gated branch, never merge, push main or deploy, and post one \"Look at first:\" paragraph in the room.",
6912
6975
  "scope": "session",
6913
6976
  "subjectProfile": {
6914
- "onEnd": {
6915
- "failed": "spec",
6916
- "cancelled": "spec"
6917
- },
6918
- "profileSlug": "devplane_feature",
6919
- "statusProperty": "featureStatus"
6977
+ "profileSlug": "devplane_feature"
6920
6978
  },
6921
- "humanOnlyStatuses": [
6922
- "backlog",
6923
- "cancelled"
6924
- ],
6925
6979
  "params": [
6926
6980
  {
6927
6981
  "name": "feature",
@@ -7160,21 +7214,12 @@ const DATA = {
7160
7214
  },
7161
7215
  {
7162
7216
  "name": "Fix a bug",
7163
- "description": "Dev set (decision d05), key: fix. Works an issue at its root: reproduce it with a failing test, fix the canonical path, a clean-context review, then the shared land stages. Its stages follow the issue's lifecycle (open, investigating, fixed); a cancelled or failed session puts the issue back to open, as Fix a finding does. Small fixes may be batched (founder default, 2026-11-05): several issues in one session, one as the subject and the rest as session targets; today a stage moves only the subject, and the session end moves the subject and every target still open. No activators until binding is turned on; a batch would be {on: count, status: open, min: 3} or {on: schedule, cron, status: open} (both one session per moment). A night shift run is this playbook with unattended true. Reuses Bugfix (8c335e2e), Night shift: build an issue (c101dd75) and Ship a change (2c5aa553). Draft until the founder activates it.",
7217
+ "description": "Dev set (decision d05), key: fix. Works an issue at its root: reproduce it with a failing test, fix the canonical path, a clean-context review, then the shared land stages. Its stages follow the issue's lifecycle (open, investigating, fixed); a cancelled or failed session leaves the issue where it is, as Fix a finding does. Small fixes may be batched (founder default, 2026-11-05): several issues in one session, one as the subject and the rest as session targets; today a stage moves only the subject. No activators until binding is turned on; a batch would be {on: count, status: open, min: 3} or {on: schedule, cron, status: open} (both one session per moment). A night shift run is this playbook with unattended true. Reuses Bugfix (8c335e2e), Night shift: build an issue (c101dd75) and Ship a change (2c5aa553). Draft until the founder activates it.",
7164
7218
  "goalTemplate": "Fix the issue {issue} at its root and prove it with a test that fails before the fix and passes after. REPRODUCE (recall first, smallest reproduction, root cause file:line), FIX on the canonical path in your own worktree, a clean-context REVIEW, then LAND through the shared land stages (Change proposed, Checks green, Landed on main, Deployed to lab, Dogfooded, Criteria verified). Unattended: {unattended}. When unattended is true, ask no person, stop at a draft PR or a gated branch, never merge, push main or deploy; if no code fix is right, write the root cause as a pod document; post one \"Look at first:\" paragraph in the room.",
7165
7219
  "scope": "session",
7166
7220
  "subjectProfile": {
7167
- "onEnd": {
7168
- "failed": "open",
7169
- "cancelled": "open"
7170
- },
7171
- "profileSlug": "issue",
7172
- "statusProperty": "issueStatus"
7221
+ "profileSlug": "issue"
7173
7222
  },
7174
- "humanOnlyStatuses": [
7175
- "open",
7176
- "wont_fix"
7177
- ],
7178
7223
  "params": [
7179
7224
  {
7180
7225
  "name": "issue",
@@ -8020,14 +8065,8 @@ const DATA = {
8020
8065
  "goalTemplate": "Fix the finding and see the fix live",
8021
8066
  "scope": "session",
8022
8067
  "subjectProfile": {
8023
- "profileSlug": "finding",
8024
- "statusProperty": "status"
8068
+ "profileSlug": "finding"
8025
8069
  },
8026
- "humanOnlyStatuses": [
8027
- "open",
8028
- "wont_fix",
8029
- "superseded"
8030
- ],
8031
8070
  "params": [],
8032
8071
  "executor": "is-agent",
8033
8072
  "status": "active",
@@ -8300,6 +8339,27 @@ const DATA = {
8300
8339
  "displayName": "Question",
8301
8340
  "icon": "help-circle",
8302
8341
  "profileKind": "kind",
8342
+ "lifecycle": {
8343
+ "property": "questionStatus",
8344
+ "options": [
8345
+ {
8346
+ "key": "open",
8347
+ "category": "open"
8348
+ },
8349
+ {
8350
+ "key": "exploring",
8351
+ "category": "active"
8352
+ },
8353
+ {
8354
+ "key": "answered",
8355
+ "category": "done"
8356
+ },
8357
+ {
8358
+ "key": "abandoned",
8359
+ "category": "lost"
8360
+ }
8361
+ ]
8362
+ },
8303
8363
  "properties": [
8304
8364
  {
8305
8365
  "slug": "questionStatus",
@@ -8320,6 +8380,27 @@ const DATA = {
8320
8380
  "displayName": "Decision",
8321
8381
  "icon": "gavel",
8322
8382
  "profileKind": "kind",
8383
+ "lifecycle": {
8384
+ "property": "decisionStatus",
8385
+ "options": [
8386
+ {
8387
+ "key": "proposed",
8388
+ "category": "open"
8389
+ },
8390
+ {
8391
+ "key": "accepted",
8392
+ "category": "done"
8393
+ },
8394
+ {
8395
+ "key": "superseded",
8396
+ "category": "lost"
8397
+ },
8398
+ {
8399
+ "key": "rejected",
8400
+ "category": "lost"
8401
+ }
8402
+ ]
8403
+ },
8323
8404
  "properties": [
8324
8405
  {
8325
8406
  "slug": "decisionStatus",
@@ -8641,7 +8722,9 @@ const DATA = {
8641
8722
  "slug": "business-model-open-questions",
8642
8723
  "type": "kanban",
8643
8724
  "scopeProfileSlug": "question",
8644
- "groupBy": "questionStatus",
8725
+ "config": {
8726
+ "groupByField": "questionStatus"
8727
+ },
8645
8728
  "description": "The nine component questions and everything they spawned, by status."
8646
8729
  }
8647
8730
  ],
@@ -9025,6 +9108,27 @@ const DATA = {
9025
9108
  "icon": "help-circle",
9026
9109
  "color": "blue",
9027
9110
  "description": "An open question driving a civic-data investigation.",
9111
+ "lifecycle": {
9112
+ "property": "questionStatus",
9113
+ "options": [
9114
+ {
9115
+ "key": "open",
9116
+ "category": "open"
9117
+ },
9118
+ {
9119
+ "key": "exploring",
9120
+ "category": "active"
9121
+ },
9122
+ {
9123
+ "key": "answered",
9124
+ "category": "done"
9125
+ },
9126
+ {
9127
+ "key": "abandoned",
9128
+ "category": "lost"
9129
+ }
9130
+ ]
9131
+ },
9028
9132
  "properties": [
9029
9133
  {
9030
9134
  "slug": "questionStatus",
@@ -9593,7 +9697,7 @@ const DATA = {
9593
9697
  "scopeProfileSlug": "content-program",
9594
9698
  "description": "Programs grouped by status — a running scoreboard for the content operation.",
9595
9699
  "config": {
9596
- "groupBy": "status"
9700
+ "groupByField": "status"
9597
9701
  }
9598
9702
  }
9599
9703
  ],
@@ -9714,7 +9818,6 @@ const DATA = {
9714
9818
  "musician",
9715
9819
  "photographer"
9716
9820
  ],
9717
- "profile": "post",
9718
9821
  "views": [
9719
9822
  "content-posts",
9720
9823
  "content-calendar"
@@ -9768,6 +9871,7 @@ const DATA = {
9768
9871
  },
9769
9872
  "intent": {
9770
9873
  "label": "Content",
9874
+ "primary": "post",
9771
9875
  "produces": [
9772
9876
  {
9773
9877
  "profile": "post"
@@ -10482,6 +10586,27 @@ const DATA = {
10482
10586
  "color": "#0EA5E9",
10483
10587
  "description": "An ordered run of posts that teaches one thing end to end — the curriculum axis of the content engine.",
10484
10588
  "scope": "WORKSPACE",
10589
+ "lifecycle": {
10590
+ "property": "series-status",
10591
+ "options": [
10592
+ {
10593
+ "key": "Planned",
10594
+ "category": "open"
10595
+ },
10596
+ {
10597
+ "key": "Running",
10598
+ "category": "active"
10599
+ },
10600
+ {
10601
+ "key": "Complete",
10602
+ "category": "done"
10603
+ },
10604
+ {
10605
+ "key": "Abandoned",
10606
+ "category": "lost"
10607
+ }
10608
+ ]
10609
+ },
10485
10610
  "properties": [
10486
10611
  {
10487
10612
  "slug": "series-status",
@@ -11645,7 +11770,9 @@ const DATA = {
11645
11770
  "slug": "content-posts",
11646
11771
  "type": "kanban",
11647
11772
  "scopeProfileSlug": "post",
11648
- "groupBy": "post-status",
11773
+ "config": {
11774
+ "groupByField": "post-status"
11775
+ },
11649
11776
  "description": "Content posts by status."
11650
11777
  },
11651
11778
  {
@@ -11689,7 +11816,9 @@ const DATA = {
11689
11816
  "slug": "content-newsletters",
11690
11817
  "type": "kanban",
11691
11818
  "scopeProfileSlug": "newsletter",
11692
- "groupBy": "newsletter-status",
11819
+ "config": {
11820
+ "groupByField": "newsletter-status"
11821
+ },
11693
11822
  "description": "Newsletter issues by status."
11694
11823
  },
11695
11824
  {
@@ -11985,13 +12114,8 @@ const DATA = {
11985
12114
  "description": "Take a briefed post from brief to script to published in any format — text, visual or video (HyperFrames) — from the pod's brand kit, one stage per post status, with a person approving the script before anything is generated.",
11986
12115
  "goalTemplate": "Produce content for {platform} from this idea ({post}) in the {format} format. Read the brand first from the pod's brand kit (GET /api/hub/brand/kit) — never re-derive it from a website capture — and load the creative-director skill (linked to this space) to pick the approved brand-template (layout and recipe), references and assets for this format and style; drafts never feed generation. Work the stages in order; each stage moves the post's status. SCRIPT before anything is made: write the script or outline for the format (carousel slide outline, deck outline, video script and storyboard, or the text draft) by filling the narrative frame for the post's goal — the approved content-guideline of type frame for that goal, else the default frame (sell: story, example, lesson, link; hot-take: claim, tension, reason, invitation; tutorial: promise, steps, result, next; product-demo: problem, real screen, outcome, try it). A person approves the script before the draft; nothing is generated from an unapproved script. At the draft, run the creative-director readiness check first (approved references, an approved base guideline, an approved brand-template for this format); if anything is missing, stop and route to the content-taste skill or brand onboarding instead of improvising. Then branch on the format. TEXT (article, thread, newsletter section, caption): draft it with a scroll-stopping hook and a clear CTA. VISUAL: build it pass by pass through the edit-loop skill, a person answering each pass — a carousel, LinkedIn PDF or image post as a layered composition saved on the post (carousel-format), a deck, PDF document or presentation in Open Design (open-design-edit). VIDEO (short or long video): first pick the route — FROM SCRATCH (script, storyboard, frames), FROM A VOICE (an existing voice-over or talk: transcribe it, cut on its beats, build the frames under it) or RE-EDIT (existing footage plus a voice: cut, caption, add music and motion); takes ({takes}) mean RE-EDIT, and the Draft stage says how takes, transcripts and passes are handled. Then run the HyperFrames workflow on your own agent with HYPERFRAMES_NO_TELEMETRY=1, from the kit's frame.md (format=frame-md), with GSAP vendored locally — never `hyperframes publish`, never a cloud render. For a visual or video format, record a content-composition made for this post (for a video: the brief and storyboard documents, the project zip, the MP4, key-frame stills and the brand-kit hash). Keep every format on the post's pillar and the brand voice. A human approves the script before the draft, each pass as it is built, and the draft on the preview at Review. At Schedule, a post whose account is a Postiz channel is queued through the capability that serves publish_post (postiz_schedule_post); that queueing is itself a proposal a person approves. Nothing publishes itself, and the post reads Published only once it went live: reported by Postiz, or confirmed by a person at Publish.",
11987
12116
  "subjectProfile": {
11988
- "profileSlug": "post",
11989
- "statusProperty": "post-status"
12117
+ "profileSlug": "post"
11990
12118
  },
11991
- "humanOnlyStatuses": [
11992
- "Idea",
11993
- "Archived"
11994
- ],
11995
12119
  "activators": [
11996
12120
  {
11997
12121
  "on": "enters_status",
@@ -12429,8 +12553,7 @@ const DATA = {
12429
12553
  "description": "Turn a published post into new posts for other formats and platforms, each linked to the original.",
12430
12554
  "goalTemplate": "Repurpose this published post ({post}). Read what it says and how it performed, then propose one to three new pieces in other formats or on other platforms where the same idea travels (a thread from an article, a short video from a thread, a newsletter section from a series). Create each as a new post at the Idea status, on the same pillar, with its own hook, and link it derived_from the original. Never republish the original as is.",
12431
12555
  "subjectProfile": {
12432
- "profileSlug": "post",
12433
- "statusProperty": "post-status"
12556
+ "profileSlug": "post"
12434
12557
  },
12435
12558
  "activators": [
12436
12559
  {
@@ -12466,12 +12589,8 @@ const DATA = {
12466
12589
  "description": "Take a newsletter issue from idea to sent — angle, draft, edit, schedule — with a person approving before it goes out.",
12467
12590
  "goalTemplate": "Produce this newsletter issue ({newsletter}). Read the brand voice from the pod's brand kit, then work the stages in order: settle the issue's angle and the posts it draws on, draft it, edit it down with a subject line and preview text, and schedule the send. A person approves the final issue before it is sent, nothing sends itself, and the issue reads Sent only once a person confirms it went out.",
12468
12591
  "subjectProfile": {
12469
- "profileSlug": "newsletter",
12470
- "statusProperty": "newsletter-status"
12592
+ "profileSlug": "newsletter"
12471
12593
  },
12472
- "humanOnlyStatuses": [
12473
- "Archived"
12474
- ],
12475
12594
  "params": [
12476
12595
  {
12477
12596
  "name": "newsletter",
@@ -13206,7 +13325,6 @@ const DATA = {
13206
13325
  "small-business",
13207
13326
  "founder"
13208
13327
  ],
13209
- "profile": "deal",
13210
13328
  "views": [
13211
13329
  "deal-pipeline",
13212
13330
  "deals-table",
@@ -13265,6 +13383,7 @@ const DATA = {
13265
13383
  },
13266
13384
  "intent": {
13267
13385
  "label": "Sales",
13386
+ "primary": "deal",
13268
13387
  "produces": [
13269
13388
  {
13270
13389
  "profile": "lead"
@@ -14238,10 +14357,9 @@ const DATA = {
14238
14357
  "slug": "outreach-touches",
14239
14358
  "type": "kanban",
14240
14359
  "scopeProfileSlug": "outreach-touch",
14241
- "groupBy": "status",
14242
14360
  "description": "Every outreach message, grouped by where it stands — drafted for a person to send, through replied.",
14243
14361
  "config": {
14244
- "groupBy": "status",
14362
+ "groupByField": "status",
14245
14363
  "cardFields": [
14246
14364
  "channel",
14247
14365
  "touchType",
@@ -14341,17 +14459,8 @@ const DATA = {
14341
14459
  "description": "Research one lead, decide with a person whether it is worth pursuing, and set a pursued lead qualified with \"book a meeting\" as its next action.",
14342
14460
  "goalTemplate": "Qualify this lead ({lead}). RESEARCH: verify and enrich only facts you can support — company, role, size, recent signal — and record the source of each. SCORE: assess fit against the offers and the ideal client, set the ICP score, qualification notes and outreach channels, and write the step you recommend as the lead's next action: `nextAction` one imperative line (e.g. \"Send the first message on LinkedIn\") and `nextActionAt` its date. DECIDE: ask the person to `choose` pursue, nurture or drop, your recommendation first; that answer is the decision. NURTURE: set the lead to nurturing, with `nextAction` to check in again and `nextActionAt` the date they gave (three months out when they gave none). DROP: write their reason in `disqualificationReason` and move the lead to disqualified; that move is the person's (disqualified is human-only), so it comes back proposed for them to approve, which is success; never write it another way. PURSUE: only when they chose pursue, set the lead to qualified with `nextAction` \"Book a meeting\" (one line naming the channel, e.g. \"Ask for a meeting on LinkedIn\") and `nextActionAt` its date. Never create a deal: a deal is opened when a person records a booked meeting, and that same step converts the lead. Never mark the lead a client.",
14343
14461
  "subjectProfile": {
14344
- "profileSlug": "lead",
14345
- "statusProperty": "leadStage"
14346
- },
14347
- "humanOnlyStatuses": [
14348
- "new",
14349
- "outreach",
14350
- "engaged",
14351
- "nurturing",
14352
- "converted",
14353
- "disqualified"
14354
- ],
14462
+ "profileSlug": "lead"
14463
+ },
14355
14464
  "activators": [
14356
14465
  {
14357
14466
  "on": "manual",
@@ -14475,12 +14584,8 @@ const DATA = {
14475
14584
  "description": "Take a deal from first conversation to won or lost — qualify it, write and send the proposal, negotiate, and hand a won deal to delivery, with a person deciding every commitment.",
14476
14585
  "goalTemplate": "Work this deal ({deal}) through its stages; each stage moves the deal's commercial stage. QUALIFY: from the pod (the company, its people, every past message and meeting) and public sources, establish the four facts a proposal needs — the problem the buyer wants solved and what it costs them, a budget range, who signs, and when they need it — and link the people involved to the deal. Do not guess a fact: when one is missing, ask the person who owns the relationship. WRITE: draft the proposal document (scope, deliverables, timeline, price, terms) from the agency's offers and past won proposals, and set the deal's value and close date. SEND: a person approves the proposal before it goes to the client; nothing is sent without that approval. AWAIT: wait for the client's answer and record it on the deal. NEGOTIATE: its check reads that answer; log every objection and counter-offer and propose the next step. WON: once a person confirms the client said yes, reuse the engagement Operations already has for this company; only when there is none, open one at proposed with its client set to the company. Then attach the client role to the company with handoff status handed_off. The daily \"Pick up handed-off clients\" automation skips any client that already has an engagement, so no second one is opened. A lost deal is a person's call — record why it was lost.",
14477
14586
  "subjectProfile": {
14478
- "profileSlug": "deal",
14479
- "statusProperty": "commercialStage"
14587
+ "profileSlug": "deal"
14480
14588
  },
14481
- "humanOnlyStatuses": [
14482
- "lost"
14483
- ],
14484
14589
  "activators": [
14485
14590
  {
14486
14591
  "on": "created",
@@ -15188,8 +15293,7 @@ const DATA = {
15188
15293
  "description": "Each weekday, read the channels of the leads in outreach; summarise a reply and propose the next step, or, when the follow-up is due with no reply, draft the next message in the angle of its outreach campaign as a proposed message for a person to approve; the agent never sends.",
15189
15294
  "goalTemplate": "Follow up on the leads in outreach. For each, read its channels (synap_get_channel, mode person: for a company lead, the channels of the person who decides there) and its notes. A REPLY is an inbound message after our last outbound one in a channel. With a reply, draft nothing: summarise it for a person; when they show interest, propose the next step (prepare the free estimate, \"Prepare a pre-sale estimate\", or book a meeting) and propose moving the lead to engaged; when they decline, propose nurturing or disqualified with their reason (in disqualificationReason). Unless you propose dropping them, write the next step on the lead as nextAction, one imperative line, and nextActionAt, the date they named or today. Never open a deal and never answer the reply yourself; a person does. With no reply, and only when the lead's next action date is today or past and no proposed message to it is still waiting, draft the next message, to the lead (for a company, the person who decides there) and in the angle of the lead's outreach campaign: follow its value proposition and call to action, short and in the lead's language, offering the next useful step, never pressure. For a lead with no campaign, ask the person which one. Draft at most two follow-ups per lead: a lead already sent two follow-ups gets no draft, never a third follow-up; when its last date passes in silence, propose moving it to nurturing through the status door, with its expected status. DRAFT RULES: each draft is one proposed message in the channel of the person it is written to, filed through the pod's send door: run messaging.send with to = that person's entity id (for a company lead, its decider: when that person is not in the pod, create them through the entity door with only their own fields, such as name, role and LinkedIn URL, never the company's website, domain or email), text = the message, and provider linkedin or email. Read their channel first (synap_get_channel, mode person) for what was already said. The pod files it for a person to review in that channel; it goes out only once they approve it. Never call a tool's own send verb (Unipile, Gmail), never create an outreach touch, a note or a task holding the message, and never use synap_capture for it. Never send. A LinkedIn message is drafted whatever their reach: the pod holds a draft to someone who is not a connection yet, shows it with the next step and lets it go out once they connect, so never hold a draft back for want of a connection. Draft it, then, in this order: (1) a person with no linkedinUrl: find their profile with linkedin_find_profile (their full name and company); on a match, propose its linkedinUrl and linkedinProviderId on the person for a person to approve; on none or several, ask the person to choose among its candidates (the process \"Find their LinkedIn\" does this for one lead). (2) Read their linkedinConnection, which only the pod writes (never set it or linkedinInvitedAt): connected, nothing more; none or not set, ask to connect with linkedin_send_invite (it refuses someone already connected or already invited: then nothing more); pending, the draft waits for them; ignored, draft by email instead when they have an email address. While the draft waits for them to connect, set the lead's nextAction to \"Wait for <name> to accept the LinkedIn request\" and its nextActionAt 7 days later. An email message needs none of this. For each draft, set the lead's `nextAction` to send it (e.g. \"Send the drafted message to Ana on LinkedIn\") and `nextActionAt` to today. The person reviews each proposed message in its channel, edits it if needed and approves it; the agent never sends. CADENCE: when a message is sent (a person approved its proposed message, so it is an outbound message in the channel), set its lead's lastContactedAt to the sent day, count the messages sent to the lead (the outbound messages in its channels, read with synap_get_channel mode person: for a company lead, the channels of the person written to there), and set the lead's next action: after the first message, nextAction \"Follow up with <name> if no reply\" and nextActionAt the sent day + 3 days; after the first follow-up, nextAction \"Follow up with <name> a last time if no reply\" and nextActionAt the sent day + 7 days; after the second follow-up, nextAction \"No reply after two follow-ups: nurture or drop <name>\" and nextActionAt the sent day + 7 days, and when that date passes with no reply, \"Follow up on leads in outreach\" proposes nurturing. Never a third follow-up. Propose moving a lead at new or researching to outreach through the status door, with its expected status. A reply stops the cadence: a reply is an inbound message after our last outbound one in the channel, and \"Follow up on leads in outreach\" reads it and proposes the next step.",
15190
15295
  "subjectProfile": {
15191
- "profileSlug": "lead",
15192
- "statusProperty": "leadStage"
15296
+ "profileSlug": "lead"
15193
15297
  },
15194
15298
  "activators": [
15195
15299
  {
@@ -15275,13 +15379,8 @@ const DATA = {
15275
15379
  "description": "Run one outreach campaign — write the angle and its offer, pick the people, draft one personal first message each as a proposed message in their channel; a person approves the list, then approves each message, which the pod sends.",
15276
15380
  "goalTemplate": "Run this outreach campaign ({campaign}) on {channel}; each stage moves its status. If its type is not outreach, stop and say so. PREPARE: write the target audience, the value proposition and the call to action. Pick the people to reach from the pod (and public sources when the pod has too few), resolving each one before creating anything, link each as a member of the campaign with the lead role (lead source cold-outreach when it has none), and for each draft one first message to that person in this campaign's angle, specific to them — their company, role and any past message — never a generic template. DRAFT RULES: each draft is one proposed message in the channel of the person it is written to, filed through the pod's send door: run messaging.send with to = that person's entity id (for a company lead, its decider: when that person is not in the pod, create them through the entity door with only their own fields, such as name, role and LinkedIn URL, never the company's website, domain or email), text = the message, and provider linkedin or email. Read their channel first (synap_get_channel, mode person) for what was already said. The pod files it for a person to review in that channel; it goes out only once they approve it. Never call a tool's own send verb (Unipile, Gmail), never create an outreach touch, a note or a task holding the message, and never use synap_capture for it. Never send. A LinkedIn message is drafted whatever their reach: the pod holds a draft to someone who is not a connection yet, shows it with the next step and lets it go out once they connect, so never hold a draft back for want of a connection. Draft it, then, in this order: (1) a person with no linkedinUrl: find their profile with linkedin_find_profile (their full name and company); on a match, propose its linkedinUrl and linkedinProviderId on the person for a person to approve; on none or several, ask the person to choose among its candidates (the process \"Find their LinkedIn\" does this for one lead). (2) Read their linkedinConnection, which only the pod writes (never set it or linkedinInvitedAt): connected, nothing more; none or not set, ask to connect with linkedin_send_invite (it refuses someone already connected or already invited: then nothing more); pending, the draft waits for them; ignored, draft by email instead when they have an email address. While the draft waits for them to connect, set the lead's nextAction to \"Wait for <name> to accept the LinkedIn request\" and its nextActionAt 7 days later. An email message needs none of this. START: a person approves the audience, the offer and the list, then reviews each proposed message in its channel and approves it; nothing goes out before they approve it, and the agent never sends. Once a message is sent, follow the cadence, so \"Follow up on leads in outreach\" drafts the next one. CADENCE: when a message is sent (a person approved its proposed message, so it is an outbound message in the channel), set its lead's lastContactedAt to the sent day, count the messages sent to the lead (the outbound messages in its channels, read with synap_get_channel mode person: for a company lead, the channels of the person written to there), and set the lead's next action: after the first message, nextAction \"Follow up with <name> if no reply\" and nextActionAt the sent day + 3 days; after the first follow-up, nextAction \"Follow up with <name> a last time if no reply\" and nextActionAt the sent day + 7 days; after the second follow-up, nextAction \"No reply after two follow-ups: nurture or drop <name>\" and nextActionAt the sent day + 7 days, and when that date passes with no reply, \"Follow up on leads in outreach\" proposes nurturing. Never a third follow-up. Propose moving a lead at new or researching to outreach through the status door, with its expected status. A reply stops the cadence: a reply is an inbound message after our last outbound one in the channel, and \"Follow up on leads in outreach\" reads it and proposes the next step. FINISH: when every person written to has replied or their follow-ups ended in silence, record in the campaign notes how many messages were sent (the outbound messages in their channels), how many got a reply and how many led to a booked meeting. Pausing or cancelling is a person's call.",
15277
15381
  "subjectProfile": {
15278
- "profileSlug": "campaign",
15279
- "statusProperty": "campaign-status"
15382
+ "profileSlug": "campaign"
15280
15383
  },
15281
- "humanOnlyStatuses": [
15282
- "paused",
15283
- "cancelled"
15284
- ],
15285
15384
  "activators": [
15286
15385
  {
15287
15386
  "on": "created",
@@ -15383,15 +15482,8 @@ const DATA = {
15383
15482
  "description": "Once a person has marked an outreach touch sent (messages recorded before the channels), watch for the reply; summarise it and propose the next step — the free estimate or a meeting — and never open a deal.",
15384
15483
  "goalTemplate": "Watch this sent outreach message ({touch}) for a reply; each stage moves its status. WAIT: watch its conversation. Set it bounced when it did not reach the person, or no response when its lead's next action date passes with no reply; that date is the cadence's (the sent day + 3 days after the first message, the sent day + 7 days after each follow-up), so when the lead has none, count from this message's sent date. The next message is drafted by \"Follow up on leads in outreach\", not here. When this message is the second follow-up (the third message sent to the lead) and its date passes with no reply, mark it no response and propose moving the lead to nurturing through the status door, with its expected status; there is never a third follow-up. REPLIED: its check reads the reply. Summarise it for a person. When they show interest, propose the next step — prepare the free estimate (\"Prepare a pre-sale estimate\") or book a meeting — and propose moving the lead to engaged; when they decline, propose nurturing or disqualified with their reason (in `disqualificationReason`). Unless you propose dropping them, write the next step you propose on the lead as `nextAction`, one imperative line (e.g. \"Book a meeting with Ana\"; \"Check in again\" for nurturing), and `nextActionAt`, the date they named or today; never leave it only in the summary. BOUNCED: set the lead's `nextAction` to find another way to reach them and `nextActionAt` to today. Never open a deal: a deal is opened only when a person records a booked meeting. Never answer the reply yourself; a person does. Opened is recorded by a person.",
15385
15484
  "subjectProfile": {
15386
- "profileSlug": "outreach-touch",
15387
- "statusProperty": "status"
15388
- },
15389
- "humanOnlyStatuses": [
15390
- "drafted",
15391
- "sent",
15392
- "opened",
15393
- "replaced"
15394
- ],
15485
+ "profileSlug": "outreach-touch"
15486
+ },
15395
15487
  "activators": [
15396
15488
  {
15397
15489
  "on": "enters_status",
@@ -16387,6 +16479,7 @@ const DATA = {
16387
16479
  "isPublic": true,
16388
16480
  "intent": {
16389
16481
  "label": "Finance",
16482
+ "primary": "invoice",
16390
16483
  "produces": [
16391
16484
  {
16392
16485
  "profile": "invoice"
@@ -16982,15 +17075,24 @@ const DATA = {
16982
17075
  }
16983
17076
  }
16984
17077
  },
17078
+ {
17079
+ "name": "Invoice Board",
17080
+ "slug": "invoice-board",
17081
+ "type": "kanban",
17082
+ "scopeProfileSlug": "invoice",
17083
+ "description": "Invoices by status, draft to paid — the flow board of Bill a client.",
17084
+ "config": {
17085
+ "groupByField": "status"
17086
+ }
17087
+ },
16985
17088
  {
16986
17089
  "name": "Expenses",
16987
17090
  "slug": "expenses",
16988
17091
  "type": "kanban",
16989
17092
  "scopeProfileSlug": "expense",
16990
- "groupBy": "status",
16991
17093
  "description": "Accounts payable and spend, grouped by approval/payment status.",
16992
17094
  "config": {
16993
- "groupBy": "status",
17095
+ "groupByField": "status",
16994
17096
  "cardFields": [
16995
17097
  "category",
16996
17098
  "amount",
@@ -17296,12 +17398,8 @@ const DATA = {
17296
17398
  "description": "Take an invoice from draft to paid — prepare it, send it with a person's approval, chase it when late, and confirm the payment.",
17297
17399
  "goalTemplate": "Bill this invoice ({invoice}); each stage moves its status. PREPARE: set the invoice number, customer, amount, currency, issue date and due date from the engagement or deal it bills, and check the amount against what was agreed. SEND: a person approves the invoice before it goes to the client; record the issue date. DUE: wait for the payment; look for it in the bank or payment provider (match the amount and the reference), and move on once it is found or the due date has passed. PAID: its check reads the payment; set the paid date and link the account it was deposited to. When the due date passed unpaid, the check sends the run to CHASE instead: the invoice becomes overdue and you draft a polite reminder for a person to send; once the payment is found, move the run back to Paid. Voiding an invoice is a person's call.",
17298
17400
  "subjectProfile": {
17299
- "profileSlug": "invoice",
17300
- "statusProperty": "status"
17401
+ "profileSlug": "invoice"
17301
17402
  },
17302
- "humanOnlyStatuses": [
17303
- "void"
17304
- ],
17305
17403
  "activators": [
17306
17404
  {
17307
17405
  "on": "created",
@@ -17459,13 +17557,8 @@ const DATA = {
17459
17557
  "description": "Review an expense against its budget, get a person's approval, and record the payment.",
17460
17558
  "goalTemplate": "Handle this expense ({expense}); each stage moves its status. REVIEW: check the vendor, amount, date, category and receipt, link the budget it counts against and say how much of that budget is left after it. APPROVE: a person approves or rejects the spend. PAY: a person confirms it was paid; link the account it was paid from. Reimbursement and rejection are a person's call.",
17461
17559
  "subjectProfile": {
17462
- "profileSlug": "expense",
17463
- "statusProperty": "status"
17560
+ "profileSlug": "expense"
17464
17561
  },
17465
- "humanOnlyStatuses": [
17466
- "reimbursed",
17467
- "rejected"
17468
- ],
17469
17562
  "activators": [
17470
17563
  {
17471
17564
  "on": "created",
@@ -18476,9 +18569,8 @@ const DATA = {
18476
18569
  "slug": "pain-points",
18477
18570
  "type": "kanban",
18478
18571
  "scopeProfileSlug": "pain-point",
18479
- "groupBy": "severity",
18480
18572
  "config": {
18481
- "groupBy": "severity",
18573
+ "groupByField": "severity",
18482
18574
  "cardFields": [
18483
18575
  "description",
18484
18576
  "audience",
@@ -20522,6 +20614,7 @@ const DATA = {
20522
20614
  "isPublic": true,
20523
20615
  "intent": {
20524
20616
  "label": "Team",
20617
+ "primary": "candidate",
20525
20618
  "produces": [
20526
20619
  {
20527
20620
  "profile": "candidate"
@@ -21089,10 +21182,9 @@ const DATA = {
21089
21182
  "slug": "reviews",
21090
21183
  "type": "kanban",
21091
21184
  "scopeProfileSlug": "review",
21092
- "groupBy": "status",
21093
21185
  "description": "Performance reviews across the cycle, by status.",
21094
21186
  "config": {
21095
- "groupBy": "status",
21187
+ "groupByField": "status",
21096
21188
  "cardFields": [
21097
21189
  "cycle",
21098
21190
  "rating",
@@ -21898,7 +21990,6 @@ const DATA = {
21898
21990
  "slug": "workflows",
21899
21991
  "type": "kanban",
21900
21992
  "scopeProfileSlug": "workflow",
21901
- "groupBy": "workflow-status",
21902
21993
  "description": "Recurring processes on a board by status.",
21903
21994
  "config": {
21904
21995
  "groupByField": "workflow-status",
@@ -22278,6 +22369,7 @@ const DATA = {
22278
22369
  "isPublic": true,
22279
22370
  "intent": {
22280
22371
  "label": "Legal",
22372
+ "primary": "legal-contract",
22281
22373
  "produces": [
22282
22374
  {
22283
22375
  "profile": "legal-contract"
@@ -22885,10 +22977,9 @@ const DATA = {
22885
22977
  "slug": "renewals",
22886
22978
  "type": "kanban",
22887
22979
  "scopeProfileSlug": "legal-contract",
22888
- "groupBy": "status",
22889
22980
  "description": "Contracts by lifecycle stage — catch renewals and expirations before they bite.",
22890
22981
  "config": {
22891
- "groupBy": "status",
22982
+ "groupByField": "status",
22892
22983
  "cardFields": [
22893
22984
  "counterparty",
22894
22985
  "renewalType",
@@ -22903,10 +22994,9 @@ const DATA = {
22903
22994
  "slug": "compliance",
22904
22995
  "type": "kanban",
22905
22996
  "scopeProfileSlug": "compliance-item",
22906
- "groupBy": "status",
22907
22997
  "description": "Obligations by status — nothing goes overdue.",
22908
22998
  "config": {
22909
- "groupBy": "status",
22999
+ "groupByField": "status",
22910
23000
  "cardFields": [
22911
23001
  "obligationType",
22912
23002
  "jurisdiction",
@@ -25675,6 +25765,7 @@ const DATA = {
25675
25765
  "isPublic": true,
25676
25766
  "intent": {
25677
25767
  "label": "Marketing",
25768
+ "primary": "campaign",
25678
25769
  "produces": [
25679
25770
  {
25680
25771
  "profile": "campaign"
@@ -26023,7 +26114,9 @@ const DATA = {
26023
26114
  "slug": "campaigns",
26024
26115
  "type": "kanban",
26025
26116
  "scopeProfileSlug": "campaign",
26026
- "groupBy": "campaign-status",
26117
+ "config": {
26118
+ "groupByField": "campaign-status"
26119
+ },
26027
26120
  "description": "Campaign kanban board by status."
26028
26121
  },
26029
26122
  {
@@ -26164,13 +26257,8 @@ const DATA = {
26164
26257
  "description": "Take a campaign from brief to results — goal, audience, plan, content, launch with a person's approval, and a report on the leads it brought.",
26165
26258
  "goalTemplate": "Run this campaign ({campaign}); each stage moves its status. BRIEF: write the campaign's goal as a number, its target audience, channel, budget, start and end dates, from the brand kit and the agency's offers. PLAN: list the pieces to make and the outreach to send, each with a date. MAKE: create each piece as a post at the Idea status in Content OS and each outreach sequence as an outreach campaign, so their own processes produce them. LAUNCH: a person approves the launch; nothing is published, sent or paid for before that. REPORT: after the end date, record the lead count and conversion rate, link every new lead the campaign brought, and write what worked and what to change. Pausing or cancelling is a person's call.",
26166
26259
  "subjectProfile": {
26167
- "profileSlug": "campaign",
26168
- "statusProperty": "campaign-status"
26260
+ "profileSlug": "campaign"
26169
26261
  },
26170
- "humanOnlyStatuses": [
26171
- "paused",
26172
- "cancelled"
26173
- ],
26174
26262
  "activators": [
26175
26263
  {
26176
26264
  "on": "created",
@@ -26533,10 +26621,9 @@ const DATA = {
26533
26621
  "slug": "meeting-action-items",
26534
26622
  "type": "kanban",
26535
26623
  "scopeProfileSlug": "task",
26536
- "groupBy": "status",
26537
26624
  "description": "Tasks generated from meetings, by status.",
26538
26625
  "config": {
26539
- "groupBy": "status"
26626
+ "groupByField": "status"
26540
26627
  }
26541
26628
  }
26542
26629
  ],
@@ -27475,7 +27562,6 @@ const DATA = {
27475
27562
  "suggestFor": [
27476
27563
  "consultant"
27477
27564
  ],
27478
- "profile": "engagement",
27479
27565
  "views": [
27480
27566
  "engagements"
27481
27567
  ],
@@ -27521,6 +27607,7 @@ const DATA = {
27521
27607
  },
27522
27608
  "intent": {
27523
27609
  "label": "Delivery",
27610
+ "primary": "engagement",
27524
27611
  "produces": [
27525
27612
  {
27526
27613
  "profile": "engagement"
@@ -27936,7 +28023,9 @@ const DATA = {
27936
28023
  "slug": "engagements",
27937
28024
  "type": "kanban",
27938
28025
  "scopeProfileSlug": "engagement",
27939
- "groupBy": "engagement-status",
28026
+ "config": {
28027
+ "groupByField": "engagement-status"
28028
+ },
27940
28029
  "description": "Client engagements on a board by status."
27941
28030
  },
27942
28031
  {
@@ -27944,7 +28033,9 @@ const DATA = {
27944
28033
  "slug": "deliverables",
27945
28034
  "type": "kanban",
27946
28035
  "scopeProfileSlug": "deliverable",
27947
- "groupBy": "deliverable-status",
28036
+ "config": {
28037
+ "groupByField": "deliverable-status"
28038
+ },
27948
28039
  "description": "Deliverables on a board by status."
27949
28040
  },
27950
28041
  {
@@ -27954,6 +28045,16 @@ const DATA = {
27954
28045
  "scopeProfileSlug": "contract",
27955
28046
  "description": "Contracts with their status, value, and term."
27956
28047
  },
28048
+ {
28049
+ "name": "Contract Board",
28050
+ "slug": "contract-board",
28051
+ "type": "kanban",
28052
+ "scopeProfileSlug": "contract",
28053
+ "description": "Contracts by status — the flow board of Get a contract signed.",
28054
+ "config": {
28055
+ "groupByField": "contract-status"
28056
+ }
28057
+ },
27957
28058
  {
27958
28059
  "name": "Client Briefings",
27959
28060
  "slug": "client-briefings",
@@ -28576,13 +28677,8 @@ const DATA = {
28576
28677
  "description": "Run one client engagement from kick-off to close — scope, contract, deliverables, final review and the closing invoice — with a person approving the start and the close.",
28577
28678
  "goalTemplate": "Run this client engagement ({engagement}); each stage moves its status. KICK-OFF: read the won deal, the proposal and every message with the client; write the scope, owner, start and end dates and value on the engagement; create one deliverable per promised output (each with a due date and an owner); reuse the draft contract already linked to the engagement (the daily client pick-up opens one), and create a draft contract only when none is linked. START: a person confirms the contract is signed and the work may start. DELIVER: track every deliverable to accepted (or cancelled by a person), post a short weekly status in this session's room, and flag any deliverable past its due date. CLOSE: once every deliverable is accepted or cancelled, write the closing review (what was delivered, what slipped, what the client said), create the closing invoice in Finance at the draft status for the engagement value still owed (when the engagement bills per deliverable, subtract every milestone invoice already created for it), and propose the renewal or next engagement. A person approves the close. Pausing or cancelling an engagement is a person's call.",
28578
28679
  "subjectProfile": {
28579
- "profileSlug": "engagement",
28580
- "statusProperty": "engagement-status"
28680
+ "profileSlug": "engagement"
28581
28681
  },
28582
- "humanOnlyStatuses": [
28583
- "on-hold",
28584
- "cancelled"
28585
- ],
28586
28682
  "activators": [
28587
28683
  {
28588
28684
  "on": "created",
@@ -28716,13 +28812,8 @@ const DATA = {
28716
28812
  "description": "Take one deliverable from in progress to accepted by the client — plan, produce, review internally, send, get the client's sign-off, and bill it when the engagement bills per deliverable.",
28717
28813
  "goalTemplate": "Deliver this deliverable ({deliverable}); each stage moves its status. PLAN: read the engagement's scope and the client's brief, and write what done looks like for this deliverable. PRODUCE: make it, or break it into tasks for the people who will. REVIEW: check it against what done looks like before anyone outside sees it. SEND: a person approves before it goes to the client; record the date it was delivered. ACCEPTED: a person confirms the client accepted it; if the client asked for changes, go back to producing. Then read the engagement's billing: only when it bills per deliverable, create this deliverable's invoice in Finance at the draft status for its share of the engagement value, linked to the deliverable. When it bills at close, create no invoice; the engagement's close bills it.",
28718
28814
  "subjectProfile": {
28719
- "profileSlug": "deliverable",
28720
- "statusProperty": "deliverable-status"
28815
+ "profileSlug": "deliverable"
28721
28816
  },
28722
- "humanOnlyStatuses": [
28723
- "not-started",
28724
- "cancelled"
28725
- ],
28726
28817
  "activators": [
28727
28818
  {
28728
28819
  "on": "enters_status",
@@ -28851,13 +28942,8 @@ const DATA = {
28851
28942
  "description": "Take a client contract from draft to signed and active, with a person approving what is sent and confirming the signature.",
28852
28943
  "goalTemplate": "Get this contract ({contract}) signed; each stage moves its status. DRAFT: fill the contract from the engagement's scope, value, dates and the agency's standard terms, and list every term that differs from the standard. SEND: a person approves the contract before it goes to the client. SIGNED: ask the person to `provide` the signed file; their approval confirms both sides signed. ACTIVE: set the start and end dates and link the signed document. Expiry and termination are a person's call.",
28853
28944
  "subjectProfile": {
28854
- "profileSlug": "contract",
28855
- "statusProperty": "contract-status"
28945
+ "profileSlug": "contract"
28856
28946
  },
28857
- "humanOnlyStatuses": [
28858
- "expired",
28859
- "terminated"
28860
- ],
28861
28947
  "activators": [
28862
28948
  {
28863
28949
  "on": "created",
@@ -28970,6 +29056,7 @@ const DATA = {
28970
29056
  "isPublic": true,
28971
29057
  "intent": {
28972
29058
  "label": "Planning",
29059
+ "primary": "sprint",
28973
29060
  "produces": [
28974
29061
  {
28975
29062
  "profile": "sprint"
@@ -29258,7 +29345,6 @@ const DATA = {
29258
29345
  "slug": "sprint-board",
29259
29346
  "type": "kanban",
29260
29347
  "scopeProfileSlug": "task",
29261
- "groupBy": "task-status",
29262
29348
  "description": "Active sprint tasks in Backlog / Todo / In Progress / Review / Done lanes",
29263
29349
  "config": {
29264
29350
  "groupByField": "task-status",
@@ -29374,7 +29460,6 @@ const DATA = {
29374
29460
  "slug": "retrospective-board",
29375
29461
  "type": "kanban",
29376
29462
  "scopeProfileSlug": "sprint",
29377
- "groupBy": "sprint-status",
29378
29463
  "description": "Sprint retrospectives — completed sprints with retrospective notes attached as documents",
29379
29464
  "config": {
29380
29465
  "groupByField": "sprint-status"
@@ -30232,6 +30317,7 @@ const DATA = {
30232
30317
  "isPublic": true,
30233
30318
  "intent": {
30234
30319
  "label": "Research",
30320
+ "primary": "research-finding",
30235
30321
  "produces": [
30236
30322
  {
30237
30323
  "profile": "hypothesis"
@@ -30262,6 +30348,27 @@ const DATA = {
30262
30348
  "icon": "help-circle",
30263
30349
  "color": "blue",
30264
30350
  "description": "An open question driving an investigation — the thing research answers.",
30351
+ "lifecycle": {
30352
+ "property": "questionStatus",
30353
+ "options": [
30354
+ {
30355
+ "key": "open",
30356
+ "category": "open"
30357
+ },
30358
+ {
30359
+ "key": "exploring",
30360
+ "category": "active"
30361
+ },
30362
+ {
30363
+ "key": "answered",
30364
+ "category": "done"
30365
+ },
30366
+ {
30367
+ "key": "abandoned",
30368
+ "category": "lost"
30369
+ }
30370
+ ]
30371
+ },
30265
30372
  "properties": [
30266
30373
  {
30267
30374
  "slug": "questionStatus",
@@ -30647,10 +30754,9 @@ const DATA = {
30647
30754
  "slug": "research-hypotheses",
30648
30755
  "type": "kanban",
30649
30756
  "scopeProfileSlug": "hypothesis",
30650
- "groupBy": "stance",
30651
30757
  "description": "Candidate theories, grouped by where the evidence has left them.",
30652
30758
  "config": {
30653
- "groupBy": "stance"
30759
+ "groupByField": "stance"
30654
30760
  }
30655
30761
  },
30656
30762
  {
@@ -30774,12 +30880,8 @@ const DATA = {
30774
30880
  "description": "Investigate a question end-to-end — gather and rank sources (keeping the rejected ones), weigh hypotheses, emit findings with calibrated confidence, and map them onto the knowledge graph.",
30775
30881
  "goalTemplate": "Investigate the question {question} and record the WHOLE investigation, not just the answer; each stage moves the question's status. FRAME: restate the question so it can be answered, and say what evidence would answer it. GATHER: use the source-triage skill to gather sources widely via web search, classify each by type and credibility, and create a `source` entity for every one — including the ones you rejected, marked rejected with a reason (never silently drop a source). WEIGH: form the candidate answers as `hypothesis` entities that answer the question; link every source that bears on a hypothesis with `supports` or `contradicts`; use the evidence-synthesis skill to emit `research-finding` entities with honestly calibrated confidence, each `supported_by` its sources and `derived_from` this research; use the concept-cartography skill to place the findings onto the knowledge map. ANSWER: create the `research` entity that `investigates` the question and `explored` the sources, write its conclusion and confidence, and set the question to answered. Abandoning a question is a person's call. Every write is proposal-gated and reviewable.",
30776
30882
  "subjectProfile": {
30777
- "profileSlug": "question",
30778
- "statusProperty": "questionStatus"
30883
+ "profileSlug": "question"
30779
30884
  },
30780
- "humanOnlyStatuses": [
30781
- "abandoned"
30782
- ],
30783
30885
  "activators": [
30784
30886
  {
30785
30887
  "on": "created",
@@ -30893,8 +30995,7 @@ const DATA = {
30893
30995
  "description": "When a finding is validated, propose the posts that would share it, each linked to the finding.",
30894
30996
  "goalTemplate": "Turn this validated finding ({finding}) into content. Read the finding, its sources and the research it came from. Propose one to three posts that share it with the audience — each created at the Idea status, on the pillar it fits, with its hook and the reason it is worth making — and link each one derived_from the finding. Quote only what the sources support.",
30895
30997
  "subjectProfile": {
30896
- "profileSlug": "research-finding",
30897
- "statusProperty": "status"
30998
+ "profileSlug": "research-finding"
30898
30999
  },
30899
31000
  "activators": [
30900
31001
  {
@@ -31097,6 +31198,27 @@ const DATA = {
31097
31198
  "icon": "help-circle",
31098
31199
  "color": "blue",
31099
31200
  "description": "The open question being decided.",
31201
+ "lifecycle": {
31202
+ "property": "questionStatus",
31203
+ "options": [
31204
+ {
31205
+ "key": "open",
31206
+ "category": "open"
31207
+ },
31208
+ {
31209
+ "key": "exploring",
31210
+ "category": "active"
31211
+ },
31212
+ {
31213
+ "key": "answered",
31214
+ "category": "done"
31215
+ },
31216
+ {
31217
+ "key": "abandoned",
31218
+ "category": "lost"
31219
+ }
31220
+ ]
31221
+ },
31100
31222
  "properties": [
31101
31223
  {
31102
31224
  "slug": "questionStatus",
@@ -31171,6 +31293,27 @@ const DATA = {
31171
31293
  "icon": "scale",
31172
31294
  "color": "amber",
31173
31295
  "description": "A resolved decision — the recommendation, why it won, and the alternatives that lost (and why).",
31296
+ "lifecycle": {
31297
+ "property": "decisionStatus",
31298
+ "options": [
31299
+ {
31300
+ "key": "proposed",
31301
+ "category": "open"
31302
+ },
31303
+ {
31304
+ "key": "accepted",
31305
+ "category": "done"
31306
+ },
31307
+ {
31308
+ "key": "superseded",
31309
+ "category": "lost"
31310
+ },
31311
+ {
31312
+ "key": "rejected",
31313
+ "category": "lost"
31314
+ }
31315
+ ]
31316
+ },
31174
31317
  "properties": [
31175
31318
  {
31176
31319
  "slug": "summary",
@@ -31275,13 +31418,8 @@ const DATA = {
31275
31418
  "description": "Put a proposed decision in front of a person with its options and evidence, and record what they chose.",
31276
31419
  "goalTemplate": "Bring this decision ({decision}) to a person. Summarise the question it resolves, the options that were considered, the evidence for and against each, and the recommendation, in one screen. A person accepts or rejects it. When a later decision replaces it, the person marks it superseded.",
31277
31420
  "subjectProfile": {
31278
- "profileSlug": "decision",
31279
- "statusProperty": "decisionStatus"
31421
+ "profileSlug": "decision"
31280
31422
  },
31281
- "humanOnlyStatuses": [
31282
- "superseded",
31283
- "rejected"
31284
- ],
31285
31423
  "activators": [
31286
31424
  {
31287
31425
  "on": "created",
@@ -31369,6 +31507,7 @@ const DATA = {
31369
31507
  "isPublic": true,
31370
31508
  "intent": {
31371
31509
  "label": "Distribution",
31510
+ "primary": "post",
31372
31511
  "produces": [
31373
31512
  {
31374
31513
  "profile": "post"
@@ -31753,7 +31892,9 @@ const DATA = {
31753
31892
  "slug": "content-calendar",
31754
31893
  "type": "kanban",
31755
31894
  "scopeProfileSlug": "post",
31756
- "groupBy": "post-status",
31895
+ "config": {
31896
+ "groupByField": "post-status"
31897
+ },
31757
31898
  "description": "Posts on a board by status — idea to published."
31758
31899
  },
31759
31900
  {