diff --git a/.cratis/ai.json b/.cratis/ai.json
index da5456e..0b6250b 100644
--- a/.cratis/ai.json
+++ b/.cratis/ai.json
@@ -9,7 +9,9 @@
"pi"
],
"profiles": [
- "cratis/chronicle/client-java"
+ "cratis/application/java",
+ "cratis/arc/java",
+ "cratis/chronicle/java"
],
"languages": [
"java"
diff --git a/.cratis/ai.manifest.json b/.cratis/ai.manifest.json
index 1bf9bbc..d63e599 100644
--- a/.cratis/ai.manifest.json
+++ b/.cratis/ai.manifest.json
@@ -1,71 +1,131 @@
{
- "SourceRevision": "5743599184c88c13cd636ddf7e2ebefd5b134f4e",
+ "SourceRevision": "c1ee33665f352f830739f4ed5c623422d7c8f15b",
"Files": [
{
"Source": "agents/backend-developer.md",
"Destination": "agents/backend-developer.md",
- "Hash": "AD863EA11CC08DAB8C1948BE3E1AF8423E02634E9F39973B36F7F4B2E71E2D1B"
+ "Hash": "C08EE69FA6A0F5A1DF331C6180632D0103BF9361C7BFC9654CDD3028F0C15D84"
},
{
"Source": "agents/code-reviewer.md",
"Destination": "agents/code-reviewer.md",
- "Hash": "8EF996E113B6245DDA7AA4DBB1319B2C3FA8D8349B18B904D21648E3FDD6C710"
+ "Hash": "E01F8AC5B0C3610B6695199ADA885AAC2F9812DB12361710A311CBEE65EA0B75"
},
{
"Source": "agents/coordinator.md",
"Destination": "agents/coordinator.md",
- "Hash": "3C1F618A8C3478E03DE8F464F3D13DE4FA0AACD7254E2D51EF43DECDD26EA7EF"
+ "Hash": "2C705BF52392E11B6FC92E67351F2C85D54618029AA258A7A797128BE3C18D94"
},
{
"Source": "agents/frontend-developer.md",
"Destination": "agents/frontend-developer.md",
- "Hash": "8D73F206E9188A2E5F0F59C48C1C33D63552C3A6DF795BB95625C880FB4284BD"
+ "Hash": "952B1BA9D418852F4C2067DB15DE2C42F9D5D0AAA491B9BCA1C704BF361CB7B3"
},
{
"Source": "agents/orchestrator.md",
"Destination": "agents/orchestrator.md",
- "Hash": "C42F1C53D00BC6D85AB8A2217639B45B5F6DDF05475DA3AB3F6F9100C258F506"
+ "Hash": "1F12004B43ADBB0672A004E60422EE5B679940F9DFDD2201386C90038F6A0C13"
},
{
"Source": "agents/performance-reviewer.md",
"Destination": "agents/performance-reviewer.md",
- "Hash": "F3EFB91297D78E629381A1F3405A549031B0030F7FBEA5F10FECFADA12D1429B"
+ "Hash": "DB013283D4790BF6C18BEAAB8B369B088DCE1E000DB9E961F9CE1D02A9CEA755"
},
{
"Source": "agents/planner.md",
"Destination": "agents/planner.md",
- "Hash": "C0CD9942B1F34B01B98B282643B96225142D7DF04A885628ACD2A5171EC86506"
+ "Hash": "FD9BBE66E93A06FB322E5F3D02B223AA410122E248B7C1FB08C0A960D7A2DC3C"
},
{
"Source": "agents/repository-investigation-reviewer.md",
"Destination": "agents/repository-investigation-reviewer.md",
- "Hash": "D07C48EE9A0D7D4A560A911AB676AE1E0E3AE8F01580C2553F359BD49A0D528D"
+ "Hash": "15BBB7FB638EFA68B715BA28640D573D3F0C047097A615B6E22B1443337B5146"
},
{
"Source": "agents/repository-investigator.md",
"Destination": "agents/repository-investigator.md",
- "Hash": "400589BF2CE7D5E432A94441BB09174B5F7FA6EB9ECE5777A641409D1E594286"
+ "Hash": "B434953C63EFB9E65D9F9E1D80997CB625BDED3B85E4407913B8928D02517703"
},
{
"Source": "agents/security-reviewer.md",
"Destination": "agents/security-reviewer.md",
- "Hash": "F101A63062D8B458A4D5B7CCE8924FC0010F82F947C5CCCFCBA2C2BC2BD49E80"
+ "Hash": "BF54B79AD86250CDA2D9F5D720210233D6D5D42B41C7E9454F030E77CE573D22"
},
{
"Source": "agents/slice-implementer.md",
"Destination": "agents/slice-implementer.md",
- "Hash": "554FA24469180C28CA97CD165396C396453FD70CCDC8BBA9101C7BFB74718C6B"
+ "Hash": "8C8F7B826DD3AF9959AEB144D2C42A17EDDDF78264B7655C5CB9DFF994350F74"
},
{
"Source": "agents/spec-writer.md",
"Destination": "agents/spec-writer.md",
- "Hash": "E32056E6133ADF0F9077902069D0AB73B9F2F24FF9984C602B83D3249627F450"
+ "Hash": "21FB3229BB6797AABA57354288BDC04CF43520A57C2973C009D1F00C3A7B376B"
},
{
"Source": "harnesses/cursor/rules/cratis.mdc",
"Destination": "harnesses/cursor/rules/cratis.mdc",
"Hash": "BA7BBC34869D441AD0119347CD514AC114AF55403F5170475D25DCB109B9B5AA"
},
+ {
+ "Source": "harnesses/opencode/agents/backend-developer.md",
+ "Destination": "harnesses/opencode/agents/backend-developer.md",
+ "Hash": "614A8A98D31D2DFFB0945870B1493C1F6EB53426542D9E1934D74BE4AD630090"
+ },
+ {
+ "Source": "harnesses/opencode/agents/code-reviewer.md",
+ "Destination": "harnesses/opencode/agents/code-reviewer.md",
+ "Hash": "545CB519E6DCCCC6C7C891E8344CF6807932874B6B293826F9FFE035DA3B351C"
+ },
+ {
+ "Source": "harnesses/opencode/agents/coordinator.md",
+ "Destination": "harnesses/opencode/agents/coordinator.md",
+ "Hash": "B308DFF7A1B9C0A6F005BA27E0F031A81A31B834E940FC747338372768DF38FA"
+ },
+ {
+ "Source": "harnesses/opencode/agents/frontend-developer.md",
+ "Destination": "harnesses/opencode/agents/frontend-developer.md",
+ "Hash": "3A6A7DC13D20887C99B3A12E7B6662B456F5221248207C0E3632F4013DAB30D5"
+ },
+ {
+ "Source": "harnesses/opencode/agents/orchestrator.md",
+ "Destination": "harnesses/opencode/agents/orchestrator.md",
+ "Hash": "B93800F1EC0383E62BC9C9B14D840B8325321B1579D86973B540574EB9C7095C"
+ },
+ {
+ "Source": "harnesses/opencode/agents/performance-reviewer.md",
+ "Destination": "harnesses/opencode/agents/performance-reviewer.md",
+ "Hash": "34222D3BBC076F7C10BF05F7BA24BD5067B529ECBC79F9FFAF1C6631545A52AA"
+ },
+ {
+ "Source": "harnesses/opencode/agents/planner.md",
+ "Destination": "harnesses/opencode/agents/planner.md",
+ "Hash": "DD6C35F947CD63659FA563495DC2BC941CE88180043215F791596D3B9D81B4D8"
+ },
+ {
+ "Source": "harnesses/opencode/agents/repository-investigation-reviewer.md",
+ "Destination": "harnesses/opencode/agents/repository-investigation-reviewer.md",
+ "Hash": "C7318859F1E32A8ACE9597232F9EF8872151F84CE2D4E5396BECBDFB3F9B4071"
+ },
+ {
+ "Source": "harnesses/opencode/agents/repository-investigator.md",
+ "Destination": "harnesses/opencode/agents/repository-investigator.md",
+ "Hash": "91B7AED10F247D219917531F89A323C7E42877516E717BD8BE184B03366FBA9A"
+ },
+ {
+ "Source": "harnesses/opencode/agents/security-reviewer.md",
+ "Destination": "harnesses/opencode/agents/security-reviewer.md",
+ "Hash": "C472724BA545070A6EC14CDF58B9B9B6A3D48923CC7FE31D21A9D4C91E3841D0"
+ },
+ {
+ "Source": "harnesses/opencode/agents/slice-implementer.md",
+ "Destination": "harnesses/opencode/agents/slice-implementer.md",
+ "Hash": "44B959665126E3727BFBCE6274764583E43B23FD27009C9DD899866223C8F917"
+ },
+ {
+ "Source": "harnesses/opencode/agents/spec-writer.md",
+ "Destination": "harnesses/opencode/agents/spec-writer.md",
+ "Hash": "6CAFFA99B755386AF4D964FFC5DC1B3DB772A0662592C7F94CB8455E8E0D2284"
+ },
{
"Source": "harnesses/pi/extensions/cratis-hooks/index.ts",
"Destination": "harnesses/pi/extensions/cratis-hooks/index.ts",
@@ -74,7 +134,7 @@
{
"Source": "harnesses/pi/extensions/cratis-rules/index.ts",
"Destination": "harnesses/pi/extensions/cratis-rules/index.ts",
- "Hash": "5EE3F174C4E134544F88082302B4B6E15B2348453C99AD3446D0443A0D0FA2B4"
+ "Hash": "355706DD005B8B828B50205C0763C9EDA99431DF47B2EC655376C382C99F4B52"
},
{
"Source": "harnesses/pi/extensions/package.json",
@@ -84,22 +144,22 @@
{
"Source": "harnesses/pi/extensions/subagent/agents.ts",
"Destination": "harnesses/pi/extensions/subagent/agents.ts",
- "Hash": "0BFBBC90DE5766872FA4190D6B83428D16ACB573FB3D86AD6EF8AFA5B879F53B"
+ "Hash": "D4A329AD5E73F77BCD6FBAEF2F7BF0FD9109A60B07596522858CA9689A8A9E22"
},
{
"Source": "harnesses/pi/extensions/subagent/index.ts",
"Destination": "harnesses/pi/extensions/subagent/index.ts",
- "Hash": "04476E00DD4ED2578ED11C2B58C1BC98553E9D907710C890609BCC296202456E"
+ "Hash": "05AD5431B6AEB95D5F8F1900F1E9E3B136F96229EF8F6490C1F90F4A78EC56DD"
},
{
"Source": "hooks/README.md",
"Destination": "hooks/README.md",
- "Hash": "4FD12AD0A26C7B7614F1DD8D999068A4B36F1BDDFCCA40F15A656184A52186D4"
+ "Hash": "3E12FECFD8408D5FC660565BA7B51CE86ADB2A8A0F51D47BD4D0689566642E47"
},
{
"Source": "hooks/agent-stop.md",
"Destination": "hooks/agent-stop.md",
- "Hash": "5CD4CBCD49495C76244697D941275BB2E4E1898326F157A13A9C82AA08107CBB"
+ "Hash": "91947EBFDE19DC70BB753FBCA4B5088D2BD932CAA3827845AAA2BCEBA5E7C92C"
},
{
"Source": "hooks/pre-commit.md",
@@ -124,7 +184,7 @@
{
"Source": "hooks/scripts/cratis-patterns.json",
"Destination": "hooks/scripts/cratis-patterns.json",
- "Hash": "9F0138373807CC5818CBEB6DC2D1ADD110CE37D1CA34C9ABC2D2A5BEF6B63FE4"
+ "Hash": "B85E9E53FB766B9649B9BF72CFAA3B009659EB14774BAB2BAAE0545D1FC34CDB"
},
{
"Source": "hooks/scripts/cratis-quality-gate.sh",
@@ -154,7 +214,7 @@
{
"Source": "hooks/scripts/validate-package-subpaths.sh",
"Destination": "hooks/scripts/validate-package-subpaths.sh",
- "Hash": "0562F1FE6F53661ABA39520DA59DCEDFBB49123C963F0A273BAF8F320EE222CE"
+ "Hash": "8D076BCA8964EFC5E038E4615A5722B987A2E2FAF9A326BEEB873F8B6C5A3D6F"
},
{
"Source": "hooks/scripts/validate-type-references.sh",
@@ -239,12 +299,12 @@
{
"Source": "prompts/ship-changes.prompt.md",
"Destination": "prompts/ship-changes.prompt.md",
- "Hash": "70FD2ADC8EC907AAD84A8B165A0A08486E2A7995FD0025ECD95CC82A28DC6E7A"
+ "Hash": "3C4C8959A7A493910CC9FBED706BC6E86EBCE3E827F60273DAC1B2E1CAB2B66F"
},
{
"Source": "prompts/verify-ai-setup.prompt.md",
"Destination": "prompts/verify-ai-setup.prompt.md",
- "Hash": "7260E68D6CE26AA41C18D89ABBF1D2462F47DFD3471E78CEC0249BD4EDFADFAA"
+ "Hash": "A83B9C531C187259618165DF3A16C45B87139411445B666CF94E50F2E5378A54"
},
{
"Source": "prompts/write-documentation.prompt.md",
@@ -256,6 +316,16 @@
"Destination": "prompts/write-specs.prompt.md",
"Hash": "D0F9AFFF2E166E000282A848EE58EFD0BEE5E82A8954FFB1E92EA3C733F2296B"
},
+ {
+ "Source": "rules/ai-distribution.md",
+ "Destination": "rules/ai-distribution.md",
+ "Hash": "BE0425B66E61370F15D195C5E36AE556B316CC03EC64944A964A0F6A6F1EED77"
+ },
+ {
+ "Source": "rules/application-profile.md",
+ "Destination": "rules/application-profile.md",
+ "Hash": "4602FA194E7857CD8C37FA4336087D5C9C25EAA6A39EEFD3D10627CF10DE375A"
+ },
{
"Source": "rules/capability-is-not-authority.md",
"Destination": "rules/capability-is-not-authority.md",
@@ -271,10 +341,20 @@
"Destination": "rules/exit-codes-and-wrappers.md",
"Hash": "E3037712FA23B75B2978F07031492B0FC236EECCB621BD518E24F37B6FFFC8FD"
},
+ {
+ "Source": "rules/frontend-quality.md",
+ "Destination": "rules/frontend-quality.md",
+ "Hash": "EE4194222EE3A0E27CCB07403B1E9F3BAC7DA65AABB5625B6B86B4732720E3A9"
+ },
+ {
+ "Source": "rules/frontend-testing.md",
+ "Destination": "rules/frontend-testing.md",
+ "Hash": "B0439D0EC798713C430C83DA03C96CCC466E92FBB24A84B5F26AED38493D7FFF"
+ },
{
"Source": "rules/general.md",
"Destination": "rules/general.md",
- "Hash": "7B39ED0F5FEE449C5FFFFB33F16908BED636DC7F234EAD81B1A00A475DCB036A"
+ "Hash": "608E1C3D8ED9F89C126D1349665AB4EAC3FD0F88FFD4AB0700405C45797A6DD1"
},
{
"Source": "rules/git-commits.md",
@@ -294,42 +374,72 @@
{
"Source": "rules/guards-and-fuses.md",
"Destination": "rules/guards-and-fuses.md",
- "Hash": "9ED019EBBFCBB08361C434E196BBCBB8B27528AA64F868A759545B7CE64DE211"
+ "Hash": "8504C66038C48CE9DF70C7581B65F6D82495A55C4E52096A5CD87010716FCEB9"
+ },
+ {
+ "Source": "rules/java.md",
+ "Destination": "rules/java.md",
+ "Hash": "FF4BF6A511B80078B7EC1A0AFCA13C078869C434CE3928827BA8884478103363"
+ },
+ {
+ "Source": "rules/kotlin.md",
+ "Destination": "rules/kotlin.md",
+ "Hash": "B1F4E127AD4959B3AE8D76B5C72418D4B471BC2F9562198167DB4932AA5ED884"
},
{
"Source": "rules/local-work-artifacts.md",
"Destination": "rules/local-work-artifacts.md",
- "Hash": "8CB6E077B85230F91BE8A5427F4453AB23D2EEEEE7718243B58BF3C842BC8BF2"
+ "Hash": "0E36CBCFC5741C857DB6F911ED7C7C0E405D0402472A71E660D0E8A2C523A776"
},
{
"Source": "rules/profiles.md",
"Destination": "rules/profiles.md",
- "Hash": "B0A36B5CF43B01ECB8CA3309BFE751B4E039C0E5B4EDBCB69D3F73F0EC9797EE"
+ "Hash": "73878EF5C260E1BE597995C4A353A6CF213E5DB236E888484F8E3156D079602D"
},
{
"Source": "rules/pull-requests.md",
"Destination": "rules/pull-requests.md",
- "Hash": "2D60C975F8815EB4C5EB4ECC812D3475FE7083808155147E229AD18F2BB5163C"
+ "Hash": "21C4A295BEE227EF63B63342BB00EDDDB9D9B1A513DB25926985A0F6D4E9C8E2"
},
{
"Source": "rules/specs.md",
"Destination": "rules/specs.md",
"Hash": "39A50496B02E5AADB9AAAD94079090E080F2054D1DB511B19BC0F843ECC00504"
},
- {
- "Source": "rules/terminal-commands.md",
- "Destination": "rules/terminal-commands.md",
- "Hash": "21881167A948D80F94B5422AE6E1F7B11D76B0D9C846C2E01436B17BA965AA97"
- },
{
"Source": "rules/verification-discipline.md",
"Destination": "rules/verification-discipline.md",
- "Hash": "73B96865CC6175851D37981F0A257349C41205CA763E75023D8C6080EC2B8A5B"
+ "Hash": "03163409D8E6B68B60430C661E9C201B3E65365EDE4877086FDA45BEB67B0197"
},
{
"Source": "rules/web-fetching.md",
"Destination": "rules/web-fetching.md",
"Hash": "075B37CFCF6C0115032BD9C68A80051942475FB5AF284ED74B2343E2CC5A14B2"
+ },
+ {
+ "Source": "skills/cratis-arc-command-kotlin/SKILL.md",
+ "Destination": "skills/cratis-arc-command-kotlin/SKILL.md",
+ "Hash": "AF9F1381D952F6F390EDDB51DA9084400ED7990221423DBBB428078D4DFBAED4"
+ },
+ {
+ "Source": "skills/cratis-arc-query-kotlin/SKILL.md",
+ "Destination": "skills/cratis-arc-query-kotlin/SKILL.md",
+ "Hash": "6D5F552D1AAD81D6A66BD36AA60D57C664FAE11F5AAA62562A987BE9408A93AA"
+ },
+ {
+ "Source": "skills/cratis-arc-validation-kotlin/SKILL.md",
+ "Destination": "skills/cratis-arc-validation-kotlin/SKILL.md",
+ "Hash": "AC9B7D09EDEA1763A83D0506C71365638598238BE9B4C81BD2CA3391C0D292DB"
+ },
+ {
+ "Source": "skills/cratis-chronicle-client-kotlin/LICENSE",
+ "Destination": "skills/cratis-chronicle-client-kotlin/LICENSE",
+ "Hash": "6A6E2C7365B7FF52A41F6F0A383A89E8429688746B8B1B9D9A74868B9B236DB1"
+ },
+ {
+ "Source": "skills/cratis-chronicle-client-kotlin/SKILL.md",
+ "Destination": "skills/cratis-chronicle-client-kotlin/SKILL.md",
+ "Hash": "8642B0033EA9C0E9381F613EAE0787F1E83F8D9E306EED53CC97A919A477F7C5"
}
],
"Integrations": [
@@ -713,7 +823,7 @@
},
{
"Path": ".opencode/agents",
- "Target": "../.cratis/ai/agents",
+ "Target": "../.cratis/ai/harnesses/opencode/agents",
"IsDirectory": true,
"PreserveExisting": false
},
diff --git a/.cratis/ai/agents/backend-developer.md b/.cratis/ai/agents/backend-developer.md
index 32529c5..5aaa1c4 100644
--- a/.cratis/ai/agents/backend-developer.md
+++ b/.cratis/ai/agents/backend-developer.md
@@ -7,11 +7,12 @@ description: >
and reactors — all in strict compliance with the vertical slice architecture.
model: claude-sonnet-4-5
tools:
- - githubRepo
- - codeSearch
- - usages
- - rename
- - terminalLastCommand
+ - Read
+ - Grep
+ - Glob
+ - Bash
+ - Edit
+ - Write
---
diff --git a/.cratis/ai/agents/code-reviewer.md b/.cratis/ai/agents/code-reviewer.md
index 5594f3f..e65a30f 100644
--- a/.cratis/ai/agents/code-reviewer.md
+++ b/.cratis/ai/agents/code-reviewer.md
@@ -6,11 +6,11 @@ description: >
TypeScript conventions, and vertical slice correctness before merge.
model: claude-sonnet-4-5
tools:
- - githubRepo
- - codeSearch
- - usages
- - rename
- - terminalLastCommand
+ - Read
+ - Grep
+ - Glob
+ - Bash
+readonly: true
---
@@ -111,7 +111,7 @@ When checking unused code, references, or naming, use semantic navigation if the
## TypeScript Styling checklist
-- [ ] No hard-coded hex/rgb values — PrimeReact CSS variables used
+- [ ] No hard-coded hex/rgb values — `--cratis-*` tokens used
- [ ] CSS co-located with component (`.css` file in same folder)
- [ ] No `!important` unless absolutely required and justified with a comment
@@ -129,7 +129,7 @@ When checking unused code, references, or naming, use semantic navigation if the
- [ ] README.md exists for complex component folders
- [ ] `CommandDialog` from `@cratis/components/CommandDialog` used for command-based dialogs
- [ ] `Dialog` from `@cratis/components/Dialogs` used for data-only dialogs
-- [ ] Never imports `Dialog` directly from `primereact/dialog`
+- [ ] Never uses a vendor or hand-rolled modal — `CommandDialog` / `Dialog` from Cratis Components
- [ ] No monolithic components — decomposed into smaller, focused sub-components
---
diff --git a/.cratis/ai/agents/coordinator.md b/.cratis/ai/agents/coordinator.md
index b93ae0f..f4dd92f 100644
--- a/.cratis/ai/agents/coordinator.md
+++ b/.cratis/ai/agents/coordinator.md
@@ -10,10 +10,11 @@ description: >
and review).
model: claude-sonnet-4-5
tools:
- - githubRepo
- - codeSearch
- - usages
- - terminalLastCommand
+ - Read
+ - Grep
+ - Glob
+ - Bash
+ - Agent
---
diff --git a/.cratis/ai/agents/frontend-developer.md b/.cratis/ai/agents/frontend-developer.md
index 20ff16b..a96f500 100644
--- a/.cratis/ai/agents/frontend-developer.md
+++ b/.cratis/ai/agents/frontend-developer.md
@@ -6,11 +6,12 @@ description: >
proxies, following the project's component and styling conventions.
model: claude-sonnet-4-5
tools:
- - githubRepo
- - codeSearch
- - usages
- - rename
- - terminalLastCommand
+ - Read
+ - Grep
+ - Glob
+ - Bash
+ - Edit
+ - Write
---
@@ -65,7 +66,7 @@ Confirm that the TypeScript proxies exist in the slice folder before writing any
- Place `.tsx` files in the **same folder** as the corresponding `.cs` file.
- Do NOT prefix the file name with the feature or slice name (folder provides context).
- Each component has its own `.css` file for static styles.
-- Use PrimeReact CSS variables for all colors, backgrounds, and borders — never hard-code hex values. The default stack is Cratis Components on PrimeReact theming — not Tailwind.
+- Use the `--cratis-*` design tokens for all colors, backgrounds, and borders — never hard-code hex values. The default stack is Cratis Components 4 (Components-owned markup and tokens; no PrimeReact) — not Tailwind.
- Use `const` over `let`.
- Use full descriptive names (never abbreviations like `e`, `idx`, `prev`).
- **Move non-trivial state out of the render function** into a `withViewModel` view model (or a tested state module) — see `react.md`. Extract as soon as a component has 3+ `useState`, a state-syncing `useEffect`, or derived values. A view model is a plain class with no React hooks, constructible in a spec.
@@ -91,28 +92,22 @@ const handleSubmit = async () => {
## Query usage pattern (with paging)
```tsx
-const pageSize = 10;
-
-export const Listing = () => {
- const [allProjectsResult, , setPage] = AllProjects.useWithPaging(pageSize);
-
- return (
- setPage(event.page ?? 0)}
- scrollable scrollHeight="flex"
- emptyMessage="No items found.">
-
-
- );
-};
+import { DataTableForQuery, Column } from '@cratis/components/DataTables';
+import { AllProjects } from './AllProjects';
+
+// The table subscribes to the query itself and pages server-side (20 rows a page);
+// do not fetch rows and pass an items array.
+export const Listing = () => (
+
+
+
+);
```
+For caller-controlled paging outside a table, use the proxy hook directly —
+`const [result, , , setPage] = AllProjects.useWithPaging(pageSize)`; `result.data` and
+`result.paging` (`page`, `size`, `totalItems`, `totalPages`) drive your own layout.
+
---
## Dialog patterns
@@ -134,7 +129,7 @@ export const AddProject = ({ closeDialog }: DialogProps) => {
title="Add Project"
okLabel="Add"
cancelLabel="Cancel"
- onConfirm={() => closeDialog(DialogResult.Ok)}
+ onSuccess={() => closeDialog(DialogResult.Ok)}
onCancel={() => closeDialog(DialogResult.Cancelled)}
>
@@ -158,7 +153,7 @@ Use this for dialogs that collect data and return it without executing a command
import { useState } from 'react';
import { DialogProps, DialogResult } from '@cratis/arc.react/dialogs';
import { Dialog } from '@cratis/components/Dialogs';
-import { InputText } from 'primereact/inputtext';
+import { TextInput } from '@cratis/components/Common';
export const AddProject = ({ closeDialog }: DialogProps<{ name: string }>) => {
const [name, setName] = useState('');
@@ -174,18 +169,18 @@ export const AddProject = ({ closeDialog }: DialogProps<{ name: string }>) => {
onConfirm={() => closeDialog(DialogResult.Ok, { name })}
onCancel={() => closeDialog(DialogResult.Cancelled)}
>
- setName(event.target.value)}
+ onChange={value => setName(value)}
placeholder="Enter a name"
- autoFocus
+ aria-label="Project name"
/>
);
};
```
-> **Never** import `Dialog` from `primereact/dialog` directly.
+> **Never** use a vendor or hand-rolled modal — dialogs are Components-owned.
---
@@ -196,20 +191,19 @@ import { Page } from '@cratis/components/Common';
import { AddProject } from './Registration/AddProject';
import { Listing } from './Listing/Listing';
import { DialogResult, useDialog } from '@cratis/arc.react/dialogs';
-import { Button } from 'primereact/button';
-import * as mdIcons from 'react-icons/md';
+import { Button } from '@cratis/components/Common';
+import { MdAdd } from 'react-icons/md';
export const Projects = () => {
const [AddProjectDialog, showAddProjectDialog] = useDialog(AddProject);
// For a query-backed list page, prefer `DataPage` with ``
- // (it owns the action bar). PrimeReact 11 removed the standalone `Menubar`;
- // for a custom toolbar, compose `Button`s (content is children in v11).
+ // (it owns the action bar). For a custom action row, compose Components `Button`s
+ // (`variant`: solid | outline | ghost | link; `tone`: neutral | accent | positive | caution | critical).
return (
-
@@ -239,7 +233,7 @@ Before handing back:
- [ ] `npx tsc -b` passes with zero errors
- [ ] Components are in the correct slice folder
- [ ] If the app has a localization convention, user-visible text is routed through it (product policy — not a Cratis rule)
-- [ ] No hard-coded hex/rgb color values — PrimeReact CSS variables used throughout
+- [ ] No hard-coded hex/rgb color values — `--cratis-*` tokens used throughout
- [ ] All variable/parameter names are fully descriptive (no abbreviations)
- [ ] No `any` types — `unknown` with type guards where needed
- [ ] Composition page updated to include the new component
diff --git a/.cratis/ai/agents/orchestrator.md b/.cratis/ai/agents/orchestrator.md
index dba0942..db5ba23 100644
--- a/.cratis/ai/agents/orchestrator.md
+++ b/.cratis/ai/agents/orchestrator.md
@@ -10,10 +10,11 @@ description: >
large refactors, or any goal that spans more than one concern.
model: claude-sonnet-4-5
tools:
- - githubRepo
- - codeSearch
- - usages
- - terminalLastCommand
+ - Read
+ - Grep
+ - Glob
+ - Bash
+ - Agent
---
diff --git a/.cratis/ai/agents/performance-reviewer.md b/.cratis/ai/agents/performance-reviewer.md
index d5c0540..1e7969e 100644
--- a/.cratis/ai/agents/performance-reviewer.md
+++ b/.cratis/ai/agents/performance-reviewer.md
@@ -6,10 +6,11 @@ description: >
React render overhead, and Chronicle anti-patterns before merge.
model: claude-sonnet-4-5
tools:
- - githubRepo
- - codeSearch
- - usages
- - terminalLastCommand
+ - Read
+ - Grep
+ - Glob
+ - Bash
+readonly: true
---
diff --git a/.cratis/ai/agents/planner.md b/.cratis/ai/agents/planner.md
index 85265e0..1f3c296 100644
--- a/.cratis/ai/agents/planner.md
+++ b/.cratis/ai/agents/planner.md
@@ -7,10 +7,11 @@ description: >
the work is considered done.
model: claude-sonnet-4-5
tools:
- - githubRepo
- - codeSearch
- - usages
- - terminalLastCommand
+ - Read
+ - Grep
+ - Glob
+ - Bash
+ - Agent
---
diff --git a/.cratis/ai/agents/repository-investigation-reviewer.md b/.cratis/ai/agents/repository-investigation-reviewer.md
index 50295fc..70a63d1 100644
--- a/.cratis/ai/agents/repository-investigation-reviewer.md
+++ b/.cratis/ai/agents/repository-investigation-reviewer.md
@@ -7,8 +7,9 @@ description: >
model: claude-opus-5
tools:
- Read
- - Glob
- Grep
+ - Glob
+readonly: true
---
diff --git a/.cratis/ai/agents/repository-investigator.md b/.cratis/ai/agents/repository-investigator.md
index 93aba00..644ac6e 100644
--- a/.cratis/ai/agents/repository-investigator.md
+++ b/.cratis/ai/agents/repository-investigator.md
@@ -7,9 +7,10 @@ description: >
model: claude-opus-5
tools:
- Read
- - Glob
- Grep
+ - Glob
- Bash
+readonly: true
---
diff --git a/.cratis/ai/agents/security-reviewer.md b/.cratis/ai/agents/security-reviewer.md
index eddd0c7..05e3634 100644
--- a/.cratis/ai/agents/security-reviewer.md
+++ b/.cratis/ai/agents/security-reviewer.md
@@ -7,10 +7,11 @@ description: >
attack surface.
model: claude-sonnet-4-5
tools:
- - githubRepo
- - codeSearch
- - usages
- - terminalLastCommand
+ - Read
+ - Grep
+ - Glob
+ - Bash
+readonly: true
---
diff --git a/.cratis/ai/agents/slice-implementer.md b/.cratis/ai/agents/slice-implementer.md
index 3f9297e..550ba34 100644
--- a/.cratis/ai/agents/slice-implementer.md
+++ b/.cratis/ai/agents/slice-implementer.md
@@ -5,7 +5,13 @@ description: >
in when_*/ folders, and the React surface (page and/or command dialog). Use for new slices and for
non-trivial slice changes spanning backend and frontend.
model: claude-opus-4-8
-tools: [githubRepo, codeSearch, usages, rename, terminalLastCommand]
+tools:
+ - Read
+ - Grep
+ - Glob
+ - Bash
+ - Edit
+ - Write
---
@@ -53,7 +59,7 @@ Proxies now exist. Build React components from the generated proxies (`react.md`
- Events: no arguments on `[EventType]`, non-nullable, past tense, ``, never carry the event-source id.
- `[OnceOnly]` on non-idempotent reactor side effects; reactors return side-effect events or use `ICommandPipeline` (never `IEventLog`).
- Specs `#if DEBUG`, command aliased, per-test unique values.
-- Frontend via `withViewModel` + Arc proxy hooks + Cratis Components; never edit generated proxies; never import `Dialog` from `primereact/dialog`.
+- Frontend via `withViewModel` + Arc proxy hooks + Cratis Components; never edit generated proxies; never use a vendor or hand-rolled modal (dialogs come from `@cratis/components/CommandDialog` and `/Dialogs`).
## Output
diff --git a/.cratis/ai/agents/spec-writer.md b/.cratis/ai/agents/spec-writer.md
index 18140c5..45f2aba 100644
--- a/.cratis/ai/agents/spec-writer.md
+++ b/.cratis/ai/agents/spec-writer.md
@@ -6,10 +6,12 @@ description: >
comprehensive behavior coverage following the project's BDD conventions.
model: claude-sonnet-4-5
tools:
- - githubRepo
- - codeSearch
- - usages
- - terminalLastCommand
+ - Read
+ - Grep
+ - Glob
+ - Bash
+ - Edit
+ - Write
---
diff --git a/.cratis/ai/harnesses/opencode/agents/backend-developer.md b/.cratis/ai/harnesses/opencode/agents/backend-developer.md
new file mode 100644
index 0000000..0d43cf6
--- /dev/null
+++ b/.cratis/ai/harnesses/opencode/agents/backend-developer.md
@@ -0,0 +1,124 @@
+---
+description: >
+ Specialist for C# backend code within a vertical slice.
+ Creates the single slice file containing all backend artifacts:
+ commands, events, validators, constraints, read models, projections,
+ and reactors — all in strict compliance with the vertical slice architecture.
+mode: subagent
+model: anthropic/claude-sonnet-4-5
+permission:
+ edit: allow
+ bash: allow
+---
+
+
+
+# Backend Developer
+
+## Scope before checklists
+
+Identify the repository profile and changed lane before selecting rules or running a checklist. Read the repository's `AGENTS.md` and applicable universal rules in `.cratis/ai/rules/`. For framework contributions, load `.cratis/ai/rules/framework.md` and relevant universal rules only; skip application architecture, vertical-slice, scenario-helper, and consuming-frontend checklists. Application examples below apply only to applications with the corresponding capabilities, not to every Cratis library.
+
+Scope verification to affected projects/packages and behavior. Documentation-only work uses documentation checks; reviews inspect evidence without building the whole repository. Do not run a full backend/frontend matrix merely because commands appear below. Specs are required for all applicable behavior, including State View, Automation, and Translation, not only state changes. Report skipped or unavailable checks honestly.
+
+You are the **Backend Developer** for Cratis-based projects.
+Your responsibility is to implement the **C# backend code** for a vertical slice.
+
+Select from these canonical rules in `.cratis/ai/rules/` only after applying the profile and lane scope above:
+- `vertical-slices.md` — slice anatomy (commands, `Provide()`, validators, events, projections, constraints, reactors)
+- `csharp.md` — C# conventions
+- `concepts.md` — `ConceptAs` / `EventSourceId`
+- `efcore.md` — EF Core read models (only if the project uses EF Core)
+- `general.md` — the operating manual
+
+---
+
+## Inputs you expect
+
+- Feature name and slice name
+- Slice type (`State Change`, `State View`, `Automation`, `Translation`)
+- Domain requirements (what the slice should do)
+- Any existing events from other slices this slice depends on
+- The namespace root (read from `global.json` or existing source files, e.g. `Studio`, `Library`)
+
+---
+
+## Process
+
+1. **Determine the namespace root** by reading an existing source file to identify the convention (e.g. `Studio`, `Library`, `MyApp`).
+2. **Read existing slices** in the same feature to understand naming, existing concepts, and events you may reference.
+3. **Create a single `.cs` file** at `//.cs` (under the app source root; an optional `/` may group the feature — there is **no** top-level `Features/` wrapper).
+4. **Validate** by building Debug *and* Release (Debug regenerates the TypeScript proxies and compiles `#if DEBUG` spec code; build Release with `-p:CratisProxiesOutputPath=` to skip re-running proxy generation).
+5. Fix all compiler errors and warnings before handing back.
+
+---
+
+## File structure rules (mandatory)
+
+- **One file per slice** — all artifacts in `.cs`.
+- File header:
+ ```csharp
+ // Copyright (c) Cratis. All rights reserved.
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ ```
+- Namespace mirrors the folder path under the source root: `...` (no `Features` segment — drop any level that isn't present).
+- Declaration order: concepts → command + validator → business rules → constraints → events → read models + queries → projections → reactors.
+
+---
+
+## Commands — critical rules
+
+- Record decorated with `[Command]` from `Cratis.Arc.Commands.ModelBound`, with a public instance **`Handle()`** — never a separate handler class.
+- Put fetched/computed handler data in **`Provide()`** (runs after validation/authorization); keep `Handle()` focused on event construction.
+- **Business rejection is validation, never a throw.** Use `CommandValidator`, `ConceptValidator`, `Provide()` short-circuit, or `Result` for a concurrency-sensitive in-`Handle()` rule. A thrown exception is HTTP 500, not a validation error.
+- Return from `Handle()`: a single event, `IEnumerable