@cratis/pi 7.1.4 → 7.2.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 (31) hide show
  1. package/README.md +44 -3
  2. package/package/corpus/harnesses/pi/extensions/cratis-path-guidance/LoadedSkill.ts +9 -0
  3. package/package/corpus/harnesses/pi/extensions/cratis-path-guidance/SkillMatch.ts +10 -0
  4. package/package/corpus/harnesses/pi/extensions/cratis-path-guidance/SkillTrigger.ts +13 -0
  5. package/package/corpus/harnesses/pi/extensions/cratis-path-guidance/ToolName.ts +11 -0
  6. package/package/corpus/harnesses/pi/extensions/cratis-path-guidance/index.ts +166 -0
  7. package/package/corpus/harnesses/pi/extensions/cratis-path-guidance/skillReads.ts +62 -0
  8. package/package/corpus/harnesses/pi/extensions/cratis-path-guidance/skills.ts +72 -0
  9. package/package/corpus/harnesses/pi/extensions/cratis-path-guidance/standDown.ts +48 -0
  10. package/package/corpus/harnesses/pi/extensions/cratis-path-guidance/touchedPaths.ts +52 -0
  11. package/package/corpus/harnesses/pi/extensions/cratis-rules/index.ts +6 -237
  12. package/package/corpus/harnesses/pi/extensions/shared/AiConfiguration.ts +8 -0
  13. package/package/corpus/harnesses/pi/extensions/shared/ManagedRule.ts +13 -0
  14. package/package/corpus/harnesses/pi/extensions/shared/corpusRoot.ts +12 -0
  15. package/package/corpus/harnesses/pi/extensions/shared/frontmatter.ts +31 -0
  16. package/package/corpus/harnesses/pi/extensions/shared/globs.ts +62 -0
  17. package/package/corpus/harnesses/pi/extensions/shared/rules.ts +98 -0
  18. package/package/corpus/harnesses/pi/extensions/shared/skillFrontmatter.ts +9 -0
  19. package/package/corpus/harnesses/pi/extensions/shared/skillSelection.ts +67 -0
  20. package/package/corpus/skills/cratis-application-react-specifications/SKILL.md +3 -0
  21. package/package/corpus/skills/cratis-application-slice-specifications/SKILL.md +3 -0
  22. package/package/corpus/skills/cratis-documentation-writing/SKILL.md +18 -3
  23. package/package/corpus/skills/cratis-documentation-writing/references/cratis-site.md +14 -0
  24. package/package/corpus/skills/cratis-documentation-writing/verification.json +5 -1
  25. package/package/corpus/skills/cratis-engineering-docs-authoring/SKILL.md +2 -0
  26. package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +2 -0
  27. package/package/corpus/skills/cratis-specifications-typescript/SKILL.md +3 -0
  28. package/package/corpus/skills/cratis-technical-examples/SKILL.md +15 -0
  29. package/package/corpus/skills/cratis-technical-examples/verification.json +4 -1
  30. package/package.json +2 -1
  31. package/src/index.ts +11 -0
@@ -25,6 +25,16 @@ imports and JSX. Use one where it clearly teaches better than plain Markdown.
25
25
  - The site links each expanded tab to its exact snippet file in the owning
26
26
  repository. Don't add those links by hand.
27
27
  - Arc's authoring check rejects `ArcBackendTabs` nested inside `Steps`.
28
+ Tabs can't sit inside `Steps` anywhere, so write a backend procedure as
29
+ numbered H2 steps and keep `Steps` for shared, untabbed procedures such as
30
+ the React screen.
31
+ - Site-owned MDX under `web/src/content/docs/` can use `<ArcBackendTabs>` and
32
+ `<ChronicleClientTabs>` without an import. The site expands them from the
33
+ same manifest and client-owned snippets as product pages, including in the
34
+ Copy Markdown mirror; check the mirror to confirm the macro expanded.
35
+ - The variant-docs audit (`web/variant-docs.yml`) also covers site-owned
36
+ pages. Every site page is audited or explicitly excluded with a reason, and
37
+ direct single-language backend fences are ratcheted.
28
38
  - `TopicHero` declares `title` (required), `icon` and `eyebrow`. Don't copy
29
39
  props from a page that passes others; they are ignored.
30
40
 
@@ -40,6 +50,10 @@ example in a `:::caution` aside, and state only the change and production
40
50
  limits the product source supports. Don't infer those limits from a
41
51
  site-wide label.
42
52
 
53
+ Label a preview variant on the first screen of every page that shows it, not
54
+ only on its own getting-started page. An unsupported-variant snippet is one
55
+ sentence with its tracking issue; the surrounding prose doesn't repeat it.
56
+
43
57
  ## Cross-product compatibility
44
58
 
45
59
  There is no numbered compatibility matrix across the Chronicle kernel and its
@@ -7,6 +7,10 @@
7
7
  { "kind": "skill-contains", "value": "## Work from the reader outward" },
8
8
  { "kind": "skill-contains", "value": "cratis-technical-examples" },
9
9
  { "kind": "skill-contains", "value": "## Completion checklist" },
10
- { "kind": "skill-contains", "value": "(references/cratis-site.md)" }
10
+ { "kind": "skill-contains", "value": "(references/cratis-site.md)" },
11
+ { "kind": "skill-contains", "value": "\"how the backends differ\" table" },
12
+ { "kind": "skill-contains", "value": "keep backend limitations in one table on the series index" },
13
+ { "kind": "skill-contains", "value": "single-language claims" },
14
+ { "kind": "skill-contains", "value": "the variant-docs audit" }
11
15
  ]
12
16
  }
@@ -2,6 +2,8 @@
2
2
  name: cratis-engineering-docs-authoring
3
3
  description: Draft accurate Cratis product or engineering documentation once the reader's goal, owning source, and product evidence are known. Use for tutorials, how-to guides, explanations, and references; use the owning repository's navigation and visual QA workflows for placement and rendering.
4
4
  license: LICENSE
5
+ cratis-hint-paths:
6
+ - "**/Documentation/**/*.{md,mdx}"
5
7
  ---
6
8
 
7
9
  # Cratis documentation authoring
@@ -2,6 +2,8 @@
2
2
  name: cratis-specifications-csharp
3
3
  description: Write C# specifications with Cratis.Specifications using the Establish/Because/should_ pattern and the for_/when_/and_ folder hierarchy. Use when adding or restructuring C# specs in any Cratis repository, choosing between an isolated unit spec and an in-process scenario spec, or building reusable given/ contexts. Do not use for TypeScript or React specs, and do not use it to decide what a command, projection, or reactor should do.
4
4
  license: MIT
5
+ cratis-hint-paths:
6
+ - "**/for_*/**/*.cs"
5
7
  ---
6
8
 
7
9
  # Cratis C# specifications
@@ -2,6 +2,9 @@
2
2
  name: cratis-specifications-typescript
3
3
  description: Write TypeScript specifications in the Cratis BDD style using the given() helper, reusable context classes, Sinon stubbing, and the Chai .should fluent interface. Use when adding or restructuring TypeScript specifications, building a given/ context class, or laying out a for_/when_ specification folder. Do not use for C# specifications, and do not use it to decide what the code under specification should do.
4
4
  license: MIT
5
+ cratis-hint-paths:
6
+ - "**/for_*/**/*.ts"
7
+ - "**/for_*/**/*.tsx"
5
8
  ---
6
9
 
7
10
  # Cratis TypeScript specifications
@@ -2,6 +2,8 @@
2
2
  name: cratis-technical-examples
3
3
  description: Design and verify developer-facing code samples, tutorial projects, and documentation snippets against real Cratis APIs. Use when adding or reviewing a runnable example, multi-client snippet, sample app, command/output pair, or migration before/after code. Do not invent API shapes or treat rendering as a compilation check.
4
4
  license: MIT
5
+ cratis-hint-paths:
6
+ - "**/Samples/**/*.{cs,ts,tsx}"
5
7
  ---
6
8
 
7
9
  # Technical examples readers can trust
@@ -31,6 +33,11 @@ language-tab layout or documentation site implementation.
31
33
  - **Multi-language client example:** keep one explanation; use the established
32
34
  client-owned snippet mechanism, compile each client against its own SDK, and
33
35
  offer only implementations that exist. Do not translate a C# call by guess.
36
+ Use the same domain type names in every tab; if the prose has to explain
37
+ which name each tab uses, fix the snippets instead. State each backend's id
38
+ and command-response wire type (for example `Guid` versus `string`) and keep
39
+ one id type per concept across every page of a series. Shared frontend code
40
+ that depends on those types must be backend-neutral or tabbed per backend.
34
41
  - **Sample application:** one realistic domain, explicit prerequisites and
35
42
  package versions, a documented run command, a reproducible state to start
36
43
  from, and a visible result. Keep it minimal enough for a new reader to finish.
@@ -83,6 +90,14 @@ elsewhere in product documentation. For those, verify against real source and
83
90
  a runnable sample/spec or an explicit snippet comparison; do not claim
84
91
  coverage from a site build or a validator that never scans the page.
85
92
 
93
+ A compiling tab is not a working tab. For each backend, confirm that the
94
+ artifact is discovered and registered, that proxy generation emits the file
95
+ and types the page names, and that any runtime behavior the page claims (live
96
+ updates, constraint rejection) was observed against a real kernel and sink. If
97
+ a tab's code compiles but fails at runtime, don't publish it with a workaround
98
+ in the prose after it. Put working code in the tab and reference the tracking
99
+ issue in a code comment.
100
+
86
101
  A simple process beats a large unmaintained examples gallery: give the reader
87
102
  one small success first, then link to a fuller sample when they need it. Update
88
103
  examples alongside public API changes and incoming reports of copy/paste failure.
@@ -6,6 +6,9 @@
6
6
  { "kind": "skill-contains", "value": "## Choose the right source" },
7
7
  { "kind": "skill-contains", "value": "**Multi-language client example:**" },
8
8
  { "kind": "skill-contains", "value": "## Build the example as a reader would" },
9
- { "kind": "skill-contains", "value": "## Stop conditions" }
9
+ { "kind": "skill-contains", "value": "## Stop conditions" },
10
+ { "kind": "skill-contains", "value": "A compiling tab is not a working tab." },
11
+ { "kind": "skill-contains", "value": "one id type per concept across every page of a series" },
12
+ { "kind": "skill-contains", "value": "Use the same domain type names in every tab" }
10
13
  ]
11
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cratis/pi",
3
- "version": "7.1.4",
3
+ "version": "7.2.0",
4
4
  "description": "Configuration-aware Cratis AI integration for Pi",
5
5
  "type": "module",
6
6
  "files": [
@@ -41,6 +41,7 @@
41
41
  "./src/index.ts",
42
42
  "./package/corpus/harnesses/pi/extensions/cratis-hooks/index.ts",
43
43
  "./package/corpus/harnesses/pi/extensions/cratis-mcp/index.ts",
44
+ "./package/corpus/harnesses/pi/extensions/cratis-path-guidance/index.ts",
44
45
  "./package/corpus/harnesses/pi/extensions/subagent/index.ts"
45
46
  ]
46
47
  }
package/src/index.ts CHANGED
@@ -88,6 +88,16 @@ function ruleMatchesConfiguration(path: string, content: string, configuration:
88
88
  (needsDocumentation && selectedProfiles.includes('cratis/documentation'));
89
89
  }
90
90
 
91
+ /**
92
+ * A rule scoped by `applyTo` to particular files is delivered by the packaged `cratis-path-guidance`
93
+ * extension when such a file is touched, so it stays out of the system prompt. Only rules that apply to
94
+ * every file, or declare no scope, belong there.
95
+ */
96
+ function isUniversalRule(content: string): boolean {
97
+ const applyTo = (frontmatterValue(content, 'applyTo') ?? '').split(',').map(glob => glob.trim().replace(/^["']|["']$/g, '')).filter(Boolean);
98
+ return applyTo.length === 0 || applyTo.some(glob => ['**', '**/*', '*'].includes(glob));
99
+ }
100
+
91
101
  function rules(cwd: string): string {
92
102
  const root = join(corpusRoot, 'rules');
93
103
  const configurationPath = join(cwd, '.cratis', 'ai.json');
@@ -99,6 +109,7 @@ function rules(cwd: string): string {
99
109
  .sort()
100
110
  .map(entry => ({ path: join(root, entry), content: readFileSync(join(root, entry), 'utf8') }))
101
111
  .filter(rule => !configuration || ruleMatchesConfiguration(rule.path, rule.content, configuration))
112
+ .filter(rule => isUniversalRule(rule.content))
102
113
  .map(rule => rule.content)
103
114
  .join('\n\n');
104
115
  }