@cratis/pi 2.28.1 → 2.30.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.
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +11 -0
- package/package/corpus/skills/cratis-screenplay-captures-and-reactions/verification.json +2 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +11 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/verification.json +8 -0
- package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +28 -7
- package/package/corpus/skills/cratis-screenplay-event-modeling/verification.json +12 -0
- package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +33 -1
- package/package/corpus/skills/cratis-screenplay-model-authoring/verification.json +27 -0
- package/package/corpus/skills/cratis-screenplay-projections/SKILL.md +11 -0
- package/package/corpus/skills/cratis-screenplay-projections/verification.json +2 -0
- package/package/corpus/skills/cratis-screenplay-read-surface/SKILL.md +11 -0
- package/package/corpus/skills/cratis-screenplay-read-surface/verification.json +2 -0
- package/package/corpus/skills/cratis-screenplay-specifications/SKILL.md +11 -0
- package/package/corpus/skills/cratis-screenplay-specifications/verification.json +8 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +11 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/verification.json +2 -0
- package/package/corpus/skills/cratis-social-feed-post/SKILL.md +93 -0
- package/package/corpus/skills/cratis-social-feed-post/verification.json +14 -0
- package/package/corpus/skills/cratis-writing-voice-and-cadence/SKILL.md +99 -0
- package/package/corpus/skills/cratis-writing-voice-and-cadence/verification.json +13 -0
- package/package/profile-catalog.json +14 -1
- package/package.json +1 -1
|
@@ -10,6 +10,17 @@ The two slice types that run without anyone pressing a button. A `capture` in a
|
|
|
10
10
|
`Translate` slice turns outside data into events; a `reaction` in an `Automation`
|
|
11
11
|
slice runs when something happens.
|
|
12
12
|
|
|
13
|
+
## Locate the model
|
|
14
|
+
|
|
15
|
+
Look first in `.cratis/screenplay/` at the repository root. This is the
|
|
16
|
+
conventional home for consumer-owned `.play` source; do not invent another
|
|
17
|
+
location or search the whole repository before checking it.
|
|
18
|
+
|
|
19
|
+
`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`. Never
|
|
20
|
+
hand-copy Screenplay source between repositories. Keep Markdown that explains,
|
|
21
|
+
questions or navigates the model in the repository's documentation; the `.play`
|
|
22
|
+
source is the single flow model.
|
|
23
|
+
|
|
13
24
|
## Verified product sources
|
|
14
25
|
|
|
15
26
|
| Package | Version | Purpose |
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
"input": "Translate external data into events and declare a reaction.",
|
|
4
4
|
"fixtures": [],
|
|
5
5
|
"assertions": [
|
|
6
|
+
{ "kind": "skill-contains", "value": ".cratis/screenplay/" },
|
|
7
|
+
{ "kind": "skill-contains", "value": "`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`" },
|
|
6
8
|
{ "kind": "skill-contains", "value": "cannot be mixed in one clause" },
|
|
7
9
|
{ "kind": "skill-contains", "value": "`where` belongs to the reaction, not to one trigger" },
|
|
8
10
|
{ "kind": "skill-contains", "value": "Startup` and `Shutdown" }
|
|
@@ -10,6 +10,17 @@ Everything that changes the system: the `command` that expresses intent, the
|
|
|
10
10
|
`event` it appends, the rules that can refuse it, and the strongly-typed values
|
|
11
11
|
they are all built from.
|
|
12
12
|
|
|
13
|
+
## Locate the model
|
|
14
|
+
|
|
15
|
+
Look first in `.cratis/screenplay/` at the repository root. This is the
|
|
16
|
+
conventional home for consumer-owned `.play` source; do not invent another
|
|
17
|
+
location or search the whole repository before checking it.
|
|
18
|
+
|
|
19
|
+
`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`. Never
|
|
20
|
+
hand-copy Screenplay source between repositories. Keep Markdown that explains,
|
|
21
|
+
questions or navigates the model in the repository's documentation; the `.play`
|
|
22
|
+
source is the single flow model.
|
|
23
|
+
|
|
13
24
|
## Verified product sources
|
|
14
25
|
|
|
15
26
|
| Package | Version | Purpose |
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
"input": "Declare a Screenplay command with validation, authorization and concurrency.",
|
|
4
4
|
"fixtures": [],
|
|
5
5
|
"assertions": [
|
|
6
|
+
{
|
|
7
|
+
"kind": "skill-contains",
|
|
8
|
+
"value": ".cratis/screenplay/"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"kind": "skill-contains",
|
|
12
|
+
"value": "`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`"
|
|
13
|
+
},
|
|
6
14
|
{
|
|
7
15
|
"kind": "skill-contains",
|
|
8
16
|
"value": "A second `identifier` on the same command is an error"
|
|
@@ -17,6 +17,17 @@ assumptions. Keep asking *"and then what happens?"* after every event, every
|
|
|
17
17
|
command, every answer. Use business language. Do not discuss databases, APIs, or
|
|
18
18
|
frameworks during modeling.
|
|
19
19
|
|
|
20
|
+
## Locate the model
|
|
21
|
+
|
|
22
|
+
Look first in `.cratis/screenplay/` at the repository root. This is the
|
|
23
|
+
conventional home for consumer-owned `.play` source; do not invent another
|
|
24
|
+
location or search the whole repository before checking it.
|
|
25
|
+
|
|
26
|
+
`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`. Never
|
|
27
|
+
hand-copy Screenplay source between repositories. Keep Markdown that explains,
|
|
28
|
+
questions or navigates the model in the repository's documentation; the `.play`
|
|
29
|
+
source is the single flow model.
|
|
30
|
+
|
|
20
31
|
## Verified product sources
|
|
21
32
|
|
|
22
33
|
| Package | Version | Purpose |
|
|
@@ -131,14 +142,24 @@ When one is found, ask the user to clarify, create the missing element, re-valid
|
|
|
131
142
|
instances — ask *"can there be more than one of these at once?"* for each field.
|
|
132
143
|
8. No cross-cutting infrastructure is modeled as a `Translate` slice.
|
|
133
144
|
|
|
134
|
-
##
|
|
145
|
+
## Choose a file layout
|
|
146
|
+
|
|
147
|
+
Treat `.cratis/screenplay/` as one application and choose the coarsest layout
|
|
148
|
+
that keeps both the source and its diffs readable:
|
|
149
|
+
|
|
150
|
+
- Keep one `application.play` while it stays readable top to bottom.
|
|
151
|
+
- Use one file per module when modules are simple.
|
|
152
|
+
- Use one file per feature when features have sub-features.
|
|
153
|
+
- Use one file per slice when the model is large enough that a change must be
|
|
154
|
+
reviewable in isolation.
|
|
135
155
|
|
|
136
|
-
|
|
137
|
-
|
|
156
|
+
Reviewability, not an arbitrary line count, triggers the next split. In a large
|
|
157
|
+
model, one slice per file makes a scripted edit's blast radius visible in the
|
|
158
|
+
diff instead of hiding cross-reference defects in a single enormous file.
|
|
138
159
|
|
|
139
|
-
|
|
140
|
-
at the root (`domain`, `import`, `concept`, `type`, `policy`,
|
|
141
|
-
`authentication`, `seed`), then `<Module>/<Module>.play`,
|
|
160
|
+
At the most granular layout, folders mirror the language, one folder per level:
|
|
161
|
+
`application.play` at the root (`domain`, `import`, `concept`, `type`, `policy`,
|
|
162
|
+
`persona`, `authentication`, `seed`), then `<Module>/<Module>.play`,
|
|
142
163
|
`<Module>/…/<Feature>/<Feature>.play`, and `<Module>/…/<Slice>/<Slice>.play` for
|
|
143
164
|
one slice, whole. A slice file restates its `module` and `feature`; nothing is
|
|
144
165
|
written twice.
|
|
@@ -155,7 +176,7 @@ and slices come back sorted by name. Never encode meaning in order.
|
|
|
155
176
|
## Verify
|
|
156
177
|
|
|
157
178
|
```shell
|
|
158
|
-
screenplay
|
|
179
|
+
screenplay .cratis/screenplay/ --warnaserror
|
|
159
180
|
```
|
|
160
181
|
|
|
161
182
|
- [ ] Zero errors **and zero warnings**. An unrecognized construct inside a slice
|
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
"input": "Facilitate an event modeling session and land the model as .play source.",
|
|
4
4
|
"fixtures": [],
|
|
5
5
|
"assertions": [
|
|
6
|
+
{
|
|
7
|
+
"kind": "skill-contains",
|
|
8
|
+
"value": ".cratis/screenplay/"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"kind": "skill-contains",
|
|
12
|
+
"value": "`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"kind": "skill-contains",
|
|
16
|
+
"value": "Use one file per slice"
|
|
17
|
+
},
|
|
6
18
|
{
|
|
7
19
|
"kind": "skill-contains",
|
|
8
20
|
"value": "expected StateChange, StateView, Automation or Translate"
|
|
@@ -18,6 +18,17 @@ application.** Nothing in it emits C#, TypeScript or any target artifact — tha
|
|
|
18
18
|
is Stage's job, and Stage admits less than Screenplay parses. Author against that
|
|
19
19
|
reality, not against the ecosystem diagram.
|
|
20
20
|
|
|
21
|
+
## Locate the model
|
|
22
|
+
|
|
23
|
+
Look first in `.cratis/screenplay/` at the repository root. This is the
|
|
24
|
+
conventional home for consumer-owned `.play` source; do not invent another
|
|
25
|
+
location or search the whole repository before checking it.
|
|
26
|
+
|
|
27
|
+
`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`. Never
|
|
28
|
+
hand-copy Screenplay source between repositories. Keep Markdown that explains,
|
|
29
|
+
questions or navigates the model in the repository's documentation; the `.play`
|
|
30
|
+
source is the single flow model.
|
|
31
|
+
|
|
21
32
|
## Verified product sources
|
|
22
33
|
|
|
23
34
|
| Package | Version | Purpose |
|
|
@@ -29,11 +40,32 @@ reality, not against the ecosystem diagram.
|
|
|
29
40
|
Behavior below is read from the repository at tag `v4.12.1`. Reverify before
|
|
30
41
|
claiming another version behaves the same.
|
|
31
42
|
|
|
43
|
+
## Choose a file layout
|
|
44
|
+
|
|
45
|
+
Treat `.cratis/screenplay/` as one application and choose the coarsest layout
|
|
46
|
+
that keeps both the source and its diffs readable:
|
|
47
|
+
|
|
48
|
+
- Keep one `application.play` while it stays readable top to bottom.
|
|
49
|
+
- Use one file per module when modules are simple.
|
|
50
|
+
- Use one file per feature when features have sub-features.
|
|
51
|
+
- Use one file per slice when the model is large enough that a change must be
|
|
52
|
+
reviewable in isolation.
|
|
53
|
+
|
|
54
|
+
Reviewability, not an arbitrary line count, triggers the next split. In a large
|
|
55
|
+
model, one slice per file makes a scripted edit's blast radius visible in the
|
|
56
|
+
diff instead of hiding cross-reference defects in a single enormous file.
|
|
57
|
+
When files are split, restate their parent `module` and `feature`; the folder
|
|
58
|
+
compiler merges declarations by name before resolving references.
|
|
59
|
+
|
|
60
|
+
Always verify `.cratis/screenplay/` as a folder after a change. Verifying one
|
|
61
|
+
split file alone produces false unknown-name diagnostics for declarations held
|
|
62
|
+
in its siblings.
|
|
63
|
+
|
|
32
64
|
## Verify a model
|
|
33
65
|
|
|
34
66
|
```shell
|
|
35
67
|
dotnet tool install -g Cratis.Screenplay.Tool
|
|
36
|
-
screenplay
|
|
68
|
+
screenplay .cratis/screenplay/ --warnaserror
|
|
37
69
|
```
|
|
38
70
|
|
|
39
71
|
The tool takes **one positional argument** — a directory or a single `.play`
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "cratis-screenplay-model-authoring",
|
|
3
|
+
"input": "Author and organize a Screenplay model in a repository.",
|
|
4
|
+
"fixtures": [],
|
|
5
|
+
"assertions": [
|
|
6
|
+
{
|
|
7
|
+
"kind": "skill-contains",
|
|
8
|
+
"value": ".cratis/screenplay/"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"kind": "skill-contains",
|
|
12
|
+
"value": "`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"kind": "skill-contains",
|
|
16
|
+
"value": "source is the single flow model"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"kind": "skill-contains",
|
|
20
|
+
"value": "Use one file per module"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"kind": "skill-contains",
|
|
24
|
+
"value": "Use one file per slice"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -10,6 +10,17 @@ A `projection` folds events into a read model. Its body is the **Projection
|
|
|
10
10
|
Declaration Language**, an embedded sub-grammar with its own parser — not free
|
|
11
11
|
text. This is half of every event model, and the half most easily got wrong.
|
|
12
12
|
|
|
13
|
+
## Locate the model
|
|
14
|
+
|
|
15
|
+
Look first in `.cratis/screenplay/` at the repository root. This is the
|
|
16
|
+
conventional home for consumer-owned `.play` source; do not invent another
|
|
17
|
+
location or search the whole repository before checking it.
|
|
18
|
+
|
|
19
|
+
`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`. Never
|
|
20
|
+
hand-copy Screenplay source between repositories. Keep Markdown that explains,
|
|
21
|
+
questions or navigates the model in the repository's documentation; the `.play`
|
|
22
|
+
source is the single flow model.
|
|
23
|
+
|
|
13
24
|
## Verified product sources
|
|
14
25
|
|
|
15
26
|
| Package | Version | Purpose |
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
"input": "Build a read model from events with the Projection Declaration Language.",
|
|
4
4
|
"fixtures": [],
|
|
5
5
|
"assertions": [
|
|
6
|
+
{ "kind": "skill-contains", "value": ".cratis/screenplay/" },
|
|
7
|
+
{ "kind": "skill-contains", "value": "`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`" },
|
|
6
8
|
{ "kind": "skill-contains", "value": "AutoMap is on by default" },
|
|
7
9
|
{ "kind": "skill-contains", "value": "PLAY0191" },
|
|
8
10
|
{ "kind": "skill-contains", "value": "every event type in the system" },
|
|
@@ -9,6 +9,17 @@ license: MIT
|
|
|
9
9
|
What the system can be asked, and what a user sees. The `readmodel` declares the
|
|
10
10
|
shape, the `query` is the entry point, and the `screen` renders it.
|
|
11
11
|
|
|
12
|
+
## Locate the model
|
|
13
|
+
|
|
14
|
+
Look first in `.cratis/screenplay/` at the repository root. This is the
|
|
15
|
+
conventional home for consumer-owned `.play` source; do not invent another
|
|
16
|
+
location or search the whole repository before checking it.
|
|
17
|
+
|
|
18
|
+
`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`. Never
|
|
19
|
+
hand-copy Screenplay source between repositories. Keep Markdown that explains,
|
|
20
|
+
questions or navigates the model in the repository's documentation; the `.play`
|
|
21
|
+
source is the single flow model.
|
|
22
|
+
|
|
12
23
|
## Verified product sources
|
|
13
24
|
|
|
14
25
|
| Package | Version | Purpose |
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
"input": "Declare a Screenplay query and the screen that binds to it.",
|
|
4
4
|
"fixtures": [],
|
|
5
5
|
"assertions": [
|
|
6
|
+
{ "kind": "skill-contains", "value": ".cratis/screenplay/" },
|
|
7
|
+
{ "kind": "skill-contains", "value": "`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`" },
|
|
6
8
|
{ "kind": "skill-contains", "value": "The tenant is the default and stays unstated" },
|
|
7
9
|
{ "kind": "skill-contains", "value": "belongs on a `from` parameter, never on a `filter`" },
|
|
8
10
|
{ "kind": "skill-contains", "value": "warnings, not errors" }
|
|
@@ -10,6 +10,17 @@ A `specification` is the acceptance criterion for a slice, written in the same
|
|
|
10
10
|
document as the behavior it pins. Given/when/then, in business language, with
|
|
11
11
|
concrete data.
|
|
12
12
|
|
|
13
|
+
## Locate the model
|
|
14
|
+
|
|
15
|
+
Look first in `.cratis/screenplay/` at the repository root. This is the
|
|
16
|
+
conventional home for consumer-owned `.play` source; do not invent another
|
|
17
|
+
location or search the whole repository before checking it.
|
|
18
|
+
|
|
19
|
+
`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`. Never
|
|
20
|
+
hand-copy Screenplay source between repositories. Keep Markdown that explains,
|
|
21
|
+
questions or navigates the model in the repository's documentation; the `.play`
|
|
22
|
+
source is the single flow model.
|
|
23
|
+
|
|
13
24
|
## Verified product sources
|
|
14
25
|
|
|
15
26
|
| Package | Version | Purpose |
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
"input": "Write given/when/then specifications for a Screenplay slice.",
|
|
4
4
|
"fixtures": [],
|
|
5
5
|
"assertions": [
|
|
6
|
+
{
|
|
7
|
+
"kind": "skill-contains",
|
|
8
|
+
"value": ".cratis/screenplay/"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"kind": "skill-contains",
|
|
12
|
+
"value": "`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`"
|
|
13
|
+
},
|
|
6
14
|
{
|
|
7
15
|
"kind": "skill-contains",
|
|
8
16
|
"value": "**`then` contains either events or an error \u2014 never both.**"
|
|
@@ -10,6 +10,17 @@ Event Modeling's wireframe step is a first-class part of the language. The shell
|
|
|
10
10
|
the reusable shapes inside it, the forms bound to commands, and the navigation
|
|
11
11
|
entries other modules contribute are all declared in the `.play` model.
|
|
12
12
|
|
|
13
|
+
## Locate the model
|
|
14
|
+
|
|
15
|
+
Look first in `.cratis/screenplay/` at the repository root. This is the
|
|
16
|
+
conventional home for consumer-owned `.play` source; do not invent another
|
|
17
|
+
location or search the whole repository before checking it.
|
|
18
|
+
|
|
19
|
+
`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`. Never
|
|
20
|
+
hand-copy Screenplay source between repositories. Keep Markdown that explains,
|
|
21
|
+
questions or navigates the model in the repository's documentation; the `.play`
|
|
22
|
+
source is the single flow model.
|
|
23
|
+
|
|
13
24
|
## Verified product sources
|
|
14
25
|
|
|
15
26
|
| Package | Version | Purpose |
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
"input": "Declare the application shell, a screen template and a command form.",
|
|
4
4
|
"fixtures": [],
|
|
5
5
|
"assertions": [
|
|
6
|
+
{ "kind": "skill-contains", "value": ".cratis/screenplay/" },
|
|
7
|
+
{ "kind": "skill-contains", "value": "`cratis ai install` manages `.cratis/ai/`, not `.cratis/screenplay/`" },
|
|
6
8
|
{ "kind": "skill-contains", "value": "A form is discovered, not referenced" },
|
|
7
9
|
{ "kind": "skill-contains", "value": "declares no\n`fits slot`" },
|
|
8
10
|
{ "kind": "skill-contains", "value": "override-priority order" }
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cratis-social-feed-post
|
|
3
|
+
description: Write or review a short post for a social feed such as LinkedIn, where the opening has to survive the feed's truncation, the body is plain text with no markup, and the common formatting tricks cost accessibility and reach. Use when drafting, adapting or reviewing a feed post. Do not use for documentation pages, release notes, long-form articles, or anything rendered as Markdown.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Social feed post
|
|
8
|
+
|
|
9
|
+
A feed post is not a short article. The feed shows a few lines and hides the rest behind a
|
|
10
|
+
"see more" control, so the opening is not an introduction to the point — it is the entire
|
|
11
|
+
advertisement for the post, and the decision to expand is itself a ranking signal.
|
|
12
|
+
|
|
13
|
+
Everything below assumes a plain-text feed with no markup rendering. The character and line
|
|
14
|
+
figures are unofficial approximations reported by third parties; no platform documents them,
|
|
15
|
+
and they move with interface, font size and device width. Treat them as a target zone and
|
|
16
|
+
re-check them against current official guidance rather than encoding them as durable rules.
|
|
17
|
+
|
|
18
|
+
## The fold decides what the post is judged on
|
|
19
|
+
|
|
20
|
+
On LinkedIn the cut is modelled two ways at once and lands on whichever runs out first:
|
|
21
|
+
|
|
22
|
+
- a character budget of roughly 210 on desktop and 140 on mobile, and
|
|
23
|
+
- a budget of about three rendered lines.
|
|
24
|
+
|
|
25
|
+
**A blank line spends the line budget without spending characters.** A short opening on its
|
|
26
|
+
own line is therefore cut *earlier* than the same words inside a paragraph. Putting the hook
|
|
27
|
+
on its own line is usually still right, because it is what a scroller reads first, but it is
|
|
28
|
+
a trade rather than a free improvement.
|
|
29
|
+
|
|
30
|
+
## What the opening must do
|
|
31
|
+
|
|
32
|
+
- **Finish a complete thought above the cut.** An opening severed mid-sentence has spent the
|
|
33
|
+
whole advertisement on half an idea.
|
|
34
|
+
- **Stay short on purpose.** A brief opening sentence is a hook doing its job. Do not rewrite
|
|
35
|
+
one into a longer, smoother sentence for the sake of rhythm; that removes the
|
|
36
|
+
advertisement. This is the most common way a well-meaning editing pass makes a post worse.
|
|
37
|
+
- **Earn the identifier before using it.** An opening that begins with a framework type or a
|
|
38
|
+
product name asks a scroller to care about a word they have no reason to recognize yet.
|
|
39
|
+
Name the friction first, then the mechanism.
|
|
40
|
+
- **Skip the throat-clearing.** The first line is the point, not a preamble to it.
|
|
41
|
+
|
|
42
|
+
Check the opening by reading only the first three lines and asking whether they are worth
|
|
43
|
+
expanding. If the answer depends on the fourth line, the opening is wrong.
|
|
44
|
+
|
|
45
|
+
## Never use Unicode pseudo-formatting
|
|
46
|
+
|
|
47
|
+
Third-party tools offer pseudo-bold and pseudo-italic built from Mathematical Alphanumeric
|
|
48
|
+
Symbols — the characters that look like `𝗕𝗼𝗹𝗱` and `𝘐𝘵𝘢𝘭𝘪𝘤`. Do not use them.
|
|
49
|
+
|
|
50
|
+
- **Assistive technology cannot read them.** A screen-reader user hears "mathematical bold
|
|
51
|
+
capital T, mathematical bold small h" through an entire line, or hears nothing at all.
|
|
52
|
+
- **They are not the letters they resemble.** Platform search and ranking index the actual
|
|
53
|
+
code points, so a styled keyword is no longer that keyword and the term is lost.
|
|
54
|
+
|
|
55
|
+
Emphasis in a plain-text feed comes from sentence construction, line placement and what is
|
|
56
|
+
said first. A point that needs visual weight belongs in an image with its own alt text.
|
|
57
|
+
|
|
58
|
+
## Two things that cost reach outright
|
|
59
|
+
|
|
60
|
+
- **No external link in the body.** Current ranking suppresses posts that carry one; the
|
|
61
|
+
convention is to put the link in a comment. Verify this at review rather than repeating it
|
|
62
|
+
as folklore, and never write the convention into the copy itself.
|
|
63
|
+
- **No engagement bait.** "Repost if…", "Tag someone who…", "Agree?" are treated as spam
|
|
64
|
+
signals rather than as engagement. A genuinely answerable question that follows from the
|
|
65
|
+
argument is a different thing and is welcome.
|
|
66
|
+
|
|
67
|
+
## Structure that survives a phone
|
|
68
|
+
|
|
69
|
+
- One idea per post. A feed reader will not assemble two.
|
|
70
|
+
- Short paragraphs, one to three sentences, and visibly different from each other in length.
|
|
71
|
+
A column of identically sized blocks reads as a generated template before it reads as an
|
|
72
|
+
argument.
|
|
73
|
+
- Blank lines separate paragraphs and nothing else. Each one costs line budget above the fold.
|
|
74
|
+
- No Markdown. The feed renders none of it, so `**bold**` and `# heading` reach the reader
|
|
75
|
+
as literal characters.
|
|
76
|
+
- Hashtags on the last line only, never mid-sentence.
|
|
77
|
+
- Every image needs alt text. A post whose point lives only in an unlabeled image has no
|
|
78
|
+
point for part of its audience.
|
|
79
|
+
|
|
80
|
+
## Before publishing
|
|
81
|
+
|
|
82
|
+
- The opening thought is complete above the fold on mobile as well as desktop.
|
|
83
|
+
- No pseudo-formatted characters anywhere, including the hook.
|
|
84
|
+
- No link in the body and no engagement bait in the close.
|
|
85
|
+
- Every image carries alt text, and the post still makes sense with the images removed.
|
|
86
|
+
- Every technical claim is one the underlying source actually supports, and any limitation
|
|
87
|
+
the post depends on is stated rather than implied.
|
|
88
|
+
|
|
89
|
+
## Stop conditions
|
|
90
|
+
|
|
91
|
+
Stop and ask when the account owner, the author's perspective, the evidence behind a claim,
|
|
92
|
+
or an asset's permission is unresolved. Drafting a post is not authorization to publish,
|
|
93
|
+
schedule, tag, mention or upload it.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "cratis-social-feed-post",
|
|
3
|
+
"input": "Draft a LinkedIn post about a framework feature and format it for the feed.",
|
|
4
|
+
"fixtures": [],
|
|
5
|
+
"assertions": [
|
|
6
|
+
{ "kind": "skill-contains", "value": "A blank line spends the line budget without spending characters" },
|
|
7
|
+
{ "kind": "skill-contains", "value": "Never use Unicode pseudo-formatting" },
|
|
8
|
+
{ "kind": "skill-contains", "value": "Assistive technology cannot read them" },
|
|
9
|
+
{ "kind": "skill-contains", "value": "A brief opening sentence is a hook doing its job" },
|
|
10
|
+
{ "kind": "skill-contains", "value": "No external link in the body" },
|
|
11
|
+
{ "kind": "skill-contains", "value": "No engagement bait" },
|
|
12
|
+
{ "kind": "skill-contains", "value": "unofficial approximations" }
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cratis-writing-voice-and-cadence
|
|
3
|
+
description: Find and remove the sentence constructions and structural sameness that make written material read as machine-generated, across documentation, release notes, pull request descriptions, posts and reviews, without changing any technical claim. Use when reviewing or rewriting existing prose for voice. Do not use for technical accuracy review, for original drafting, or as a reason to touch approved copy without authorization.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Writing voice and cadence
|
|
8
|
+
|
|
9
|
+
Material that is factually correct can still be unreadable in a way nobody can name. The
|
|
10
|
+
usual diagnosis is "it sounds like AI wrote it", and the usual response is to rewrite by feel,
|
|
11
|
+
which produces a second machine voice rather than a human one.
|
|
12
|
+
|
|
13
|
+
The failure is measurable, and it has two halves. The smaller half is a set of sentence
|
|
14
|
+
constructions used far past the density a person would use them. The larger half is
|
|
15
|
+
structural sameness across a whole body of material: a reader meeting the second piece
|
|
16
|
+
recognizes the format before reading a word of it.
|
|
17
|
+
|
|
18
|
+
## The constructions
|
|
19
|
+
|
|
20
|
+
None of these is wrong. One of any of them is a good sentence. What turns them into a tell is
|
|
21
|
+
recurrence.
|
|
22
|
+
|
|
23
|
+
| Construction | What it looks like |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| **Corrective tail** | "…, not a fresh count." The sentence ends by correcting itself |
|
|
26
|
+
| **Balanced semicolon** | Two clauses of equal weight either side of a semicolon |
|
|
27
|
+
| **"rather than"** | The same correction carried by a different connective |
|
|
28
|
+
| **Em-dash pivot** | The dash used to swing into a closing clause |
|
|
29
|
+
| **"That is what X is for"** | A pointer sentence standing in for an explanation |
|
|
30
|
+
|
|
31
|
+
To measure rather than guess, count them. Searching for `, not a`, `; ` between two clauses,
|
|
32
|
+
`rather than`, and an em-dash followed by a short closing clause takes a few minutes across a
|
|
33
|
+
directory and turns an argument about taste into a number. Reading a draft aloud catches all
|
|
34
|
+
of them faster than any tool.
|
|
35
|
+
|
|
36
|
+
## Structural sameness is the more damaging half
|
|
37
|
+
|
|
38
|
+
Look at ten pieces together, not one at a time:
|
|
39
|
+
|
|
40
|
+
- **Every piece the same length and shape.** If most of them are three or four paragraphs
|
|
41
|
+
with the same paragraph weights, that is a template.
|
|
42
|
+
The fix for a template is not a better template.
|
|
43
|
+
Do not adopt a target shape: vary the paragraph count, and let paragraphs differ visibly
|
|
44
|
+
in weight.
|
|
45
|
+
- **Every sentence the same length.** When sentence length barely varies within a piece, the
|
|
46
|
+
result is a monotone regardless of the words. Let it swing between four words and twenty-five.
|
|
47
|
+
- **Every piece opening the same way.** An abstract noun phrase making a declarative
|
|
48
|
+
assertion — "A screen that needs…", "A registration test can…" — is one move. Alternate it
|
|
49
|
+
with a question, a direct address, a concrete moment, or a number.
|
|
50
|
+
|
|
51
|
+
## Address somebody
|
|
52
|
+
|
|
53
|
+
- **Say "you".** Material that tells a reader what to do should address that reader.
|
|
54
|
+
- **Attributed writing should sound attributed.** Prose published under a person's name and
|
|
55
|
+
written entirely in the impersonal third person reads as documentation wearing a byline.
|
|
56
|
+
Opinion, judgement and preference belong to the named author and are theirs to give.
|
|
57
|
+
- **First person is not a licence to invent.** Opinion is allowed; invented experience,
|
|
58
|
+
anecdotes that did not happen, and claimed observations the author did not make are not.
|
|
59
|
+
Where a named author owns the material, it stays blocked until that author reviews it.
|
|
60
|
+
- **A question is allowed when the piece has earned it.** A question that follows from the
|
|
61
|
+
argument is not bait; one bolted on to harvest a response is.
|
|
62
|
+
|
|
63
|
+
## Never trade a claim for a smoother sentence
|
|
64
|
+
|
|
65
|
+
This is the part that makes a voice pass dangerous, and it is the reason to do one carefully
|
|
66
|
+
rather than quickly.
|
|
67
|
+
|
|
68
|
+
The risk is not an obvious rewrite. It is a hedge dissolving into nicer phrasing. "There is
|
|
69
|
+
no need to" becomes "without needing to", and a limit quietly widens. "Not its meaning"
|
|
70
|
+
becomes "and leaves its meaning alone", and a distinction softens. Both read better. Both
|
|
71
|
+
changed what the text asserts.
|
|
72
|
+
|
|
73
|
+
Before accepting any rewrite, confirm that:
|
|
74
|
+
|
|
75
|
+
- every identifier and every number present before is still present, and none was invented;
|
|
76
|
+
- every hedging word — not, never, only, may, unless, until — survives in substance;
|
|
77
|
+
- every stated limitation survives, including one that reads as an awkward caveat, because it
|
|
78
|
+
is a caveat and it is deliberate;
|
|
79
|
+
- the closing limitation or evidence statement is not thinned, relocated into a subordinate
|
|
80
|
+
clause, or dropped because it spoiled the ending.
|
|
81
|
+
|
|
82
|
+
A mechanical check over identifiers, numbers and hedge counts catches most of this before a
|
|
83
|
+
human reads a word, and is worth writing once for any corpus large enough to need a pass.
|
|
84
|
+
|
|
85
|
+
## Work in tranches that can be read
|
|
86
|
+
|
|
87
|
+
Rewriting is not a batch operation. Any body of material large enough to have a detectable
|
|
88
|
+
voice is too large to rewrite in one pass with judgement, and a fast pass replaces one
|
|
89
|
+
detectable format with another. Rewrite a tranche, read it, and only then continue.
|
|
90
|
+
|
|
91
|
+
Where material carries a recorded approval, a rewrite invalidates it. Recording a fresh
|
|
92
|
+
approval over copy nobody has read makes the record assert something false, after which every
|
|
93
|
+
downstream check agrees with it. Size the tranche to what its owner will actually read.
|
|
94
|
+
|
|
95
|
+
## Stop conditions
|
|
96
|
+
|
|
97
|
+
Stop when a rewrite would change what the material claims, when the named author has not
|
|
98
|
+
accepted a perspective being introduced on their behalf, or when the material is under an
|
|
99
|
+
approval that the rewrite would invalidate without authorization to refresh it.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "cratis-writing-voice-and-cadence",
|
|
3
|
+
"input": "This documentation reads like it was generated. Make it sound human without changing what it says.",
|
|
4
|
+
"fixtures": [],
|
|
5
|
+
"assertions": [
|
|
6
|
+
{ "kind": "skill-contains", "value": "Never trade a claim for a smoother sentence" },
|
|
7
|
+
{ "kind": "skill-contains", "value": "The fix for a template is not a better template" },
|
|
8
|
+
{ "kind": "skill-contains", "value": "every hedging word" },
|
|
9
|
+
{ "kind": "skill-contains", "value": "First person is not a licence to invent" },
|
|
10
|
+
{ "kind": "skill-contains", "value": "Structural sameness is the more damaging half" },
|
|
11
|
+
{ "kind": "skill-contains", "value": "Rewrite a tranche, read it, and only then continue" }
|
|
12
|
+
]
|
|
13
|
+
}
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"cratis/cli",
|
|
44
44
|
"cratis/cli/terminal-workbench",
|
|
45
45
|
"cratis/components",
|
|
46
|
+
"cratis/content",
|
|
46
47
|
"cratis/documentation",
|
|
47
48
|
"cratis/full",
|
|
48
49
|
"cratis/full/csharp",
|
|
@@ -559,10 +560,22 @@
|
|
|
559
560
|
"typescript"
|
|
560
561
|
]
|
|
561
562
|
},
|
|
563
|
+
{
|
|
564
|
+
"id": "cratis/content",
|
|
565
|
+
"availableTargets": [
|
|
566
|
+
"cratis-social-feed-post",
|
|
567
|
+
"cratis-writing-voice-and-cadence"
|
|
568
|
+
],
|
|
569
|
+
"languages": [
|
|
570
|
+
"markdown",
|
|
571
|
+
"language-agnostic"
|
|
572
|
+
]
|
|
573
|
+
},
|
|
562
574
|
{
|
|
563
575
|
"id": "cratis/documentation",
|
|
564
576
|
"availableTargets": [
|
|
565
|
-
"cratis-documentation-writing"
|
|
577
|
+
"cratis-documentation-writing",
|
|
578
|
+
"cratis-writing-voice-and-cadence"
|
|
566
579
|
],
|
|
567
580
|
"languages": [
|
|
568
581
|
"markdown",
|