ctxr-cli 0.6.0 → 0.8.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 (169) hide show
  1. package/dist/adapters/types.d.ts +2 -3
  2. package/dist/adapters/types.d.ts.map +1 -1
  3. package/dist/adapters/types.js.map +1 -1
  4. package/dist/commands/archive.d.ts +2 -2
  5. package/dist/commands/archive.js +2 -2
  6. package/dist/commands/catalog-show.d.ts +0 -1
  7. package/dist/commands/catalog-show.d.ts.map +1 -1
  8. package/dist/commands/catalog-show.js +1 -1
  9. package/dist/commands/catalog-show.js.map +1 -1
  10. package/dist/commands/graph-query.d.ts +2 -11
  11. package/dist/commands/graph-query.d.ts.map +1 -1
  12. package/dist/commands/graph-query.js +11 -14
  13. package/dist/commands/graph-query.js.map +1 -1
  14. package/dist/commands/init.d.ts.map +1 -1
  15. package/dist/commands/init.js +2 -7
  16. package/dist/commands/init.js.map +1 -1
  17. package/dist/commands/publish-check.d.ts.map +1 -1
  18. package/dist/commands/publish-check.js +0 -4
  19. package/dist/commands/publish-check.js.map +1 -1
  20. package/dist/commands/publish-gather.d.ts +6 -16
  21. package/dist/commands/publish-gather.d.ts.map +1 -1
  22. package/dist/commands/publish-gather.js +11 -30
  23. package/dist/commands/publish-gather.js.map +1 -1
  24. package/dist/commands/publish-new.d.ts +5 -4
  25. package/dist/commands/publish-new.d.ts.map +1 -1
  26. package/dist/commands/publish-new.js +32 -10
  27. package/dist/commands/publish-new.js.map +1 -1
  28. package/dist/commands/serve.d.ts.map +1 -1
  29. package/dist/commands/serve.js +6 -25
  30. package/dist/commands/serve.js.map +1 -1
  31. package/dist/commands/session-capture.d.ts.map +1 -1
  32. package/dist/commands/session-capture.js +0 -2
  33. package/dist/commands/session-capture.js.map +1 -1
  34. package/dist/config/defaults.d.ts +12 -29
  35. package/dist/config/defaults.d.ts.map +1 -1
  36. package/dist/config/defaults.js +11 -28
  37. package/dist/config/defaults.js.map +1 -1
  38. package/dist/config/schema.d.ts +18 -44
  39. package/dist/config/schema.d.ts.map +1 -1
  40. package/dist/config/schema.js +18 -52
  41. package/dist/config/schema.js.map +1 -1
  42. package/dist/core/agents-doc.d.ts +9 -0
  43. package/dist/core/agents-doc.d.ts.map +1 -1
  44. package/dist/core/agents-doc.js +31 -16
  45. package/dist/core/agents-doc.js.map +1 -1
  46. package/dist/core/browse/nav.d.ts +10 -0
  47. package/dist/core/browse/nav.d.ts.map +1 -0
  48. package/dist/core/browse/nav.js +101 -0
  49. package/dist/core/browse/nav.js.map +1 -0
  50. package/dist/core/browse/routes.d.ts +11 -2
  51. package/dist/core/browse/routes.d.ts.map +1 -1
  52. package/dist/core/browse/routes.js +19 -7
  53. package/dist/core/browse/routes.js.map +1 -1
  54. package/dist/core/browse/templates.d.ts +11 -2
  55. package/dist/core/browse/templates.d.ts.map +1 -1
  56. package/dist/core/browse/templates.js +16 -3
  57. package/dist/core/browse/templates.js.map +1 -1
  58. package/dist/core/browse/tree.d.ts +33 -0
  59. package/dist/core/browse/tree.d.ts.map +1 -0
  60. package/dist/core/browse/tree.js +53 -0
  61. package/dist/core/browse/tree.js.map +1 -0
  62. package/dist/core/catalog/build.d.ts +1 -1
  63. package/dist/core/catalog/build.d.ts.map +1 -1
  64. package/dist/core/catalog/build.js +1 -2
  65. package/dist/core/catalog/build.js.map +1 -1
  66. package/dist/core/catalog/model.d.ts +2 -0
  67. package/dist/core/catalog/model.d.ts.map +1 -1
  68. package/dist/core/catalog/model.js +2 -1
  69. package/dist/core/catalog/model.js.map +1 -1
  70. package/dist/core/checks/manifest.d.ts.map +1 -1
  71. package/dist/core/checks/manifest.js +0 -5
  72. package/dist/core/checks/manifest.js.map +1 -1
  73. package/dist/core/checks/organize-checks.d.ts +1 -2
  74. package/dist/core/checks/organize-checks.d.ts.map +1 -1
  75. package/dist/core/checks/organize-checks.js +1 -2
  76. package/dist/core/checks/organize-checks.js.map +1 -1
  77. package/dist/core/checks/types.d.ts +1 -1
  78. package/dist/core/convention-doc.d.ts +15 -12
  79. package/dist/core/convention-doc.d.ts.map +1 -1
  80. package/dist/core/convention-doc.js +25 -66
  81. package/dist/core/convention-doc.js.map +1 -1
  82. package/dist/core/errors.d.ts +9 -8
  83. package/dist/core/errors.d.ts.map +1 -1
  84. package/dist/core/errors.js +14 -18
  85. package/dist/core/errors.js.map +1 -1
  86. package/dist/core/exit-codes.d.ts +7 -5
  87. package/dist/core/exit-codes.d.ts.map +1 -1
  88. package/dist/core/exit-codes.js +7 -5
  89. package/dist/core/exit-codes.js.map +1 -1
  90. package/dist/core/ingest/identity.d.ts +4 -4
  91. package/dist/core/ingest/identity.js +4 -4
  92. package/dist/core/migrations/add-explanation-craft-skill.d.ts +26 -0
  93. package/dist/core/migrations/add-explanation-craft-skill.d.ts.map +1 -0
  94. package/dist/core/migrations/add-explanation-craft-skill.js +94 -0
  95. package/dist/core/migrations/add-explanation-craft-skill.js.map +1 -0
  96. package/dist/core/migrations/drop-access-axes.d.ts +24 -0
  97. package/dist/core/migrations/drop-access-axes.d.ts.map +1 -0
  98. package/dist/core/migrations/drop-access-axes.js +54 -0
  99. package/dist/core/migrations/drop-access-axes.js.map +1 -0
  100. package/dist/core/migrations/registry.d.ts +11 -1
  101. package/dist/core/migrations/registry.d.ts.map +1 -1
  102. package/dist/core/migrations/registry.js +15 -3
  103. package/dist/core/migrations/registry.js.map +1 -1
  104. package/dist/core/notes/list.d.ts +1 -12
  105. package/dist/core/notes/list.d.ts.map +1 -1
  106. package/dist/core/notes/list.js.map +1 -1
  107. package/dist/core/reconcile.js +2 -2
  108. package/dist/core/reconcile.js.map +1 -1
  109. package/dist/core/records.d.ts +4 -5
  110. package/dist/core/records.d.ts.map +1 -1
  111. package/dist/core/records.js +0 -2
  112. package/dist/core/records.js.map +1 -1
  113. package/dist/core/skills.d.ts +6 -0
  114. package/dist/core/skills.d.ts.map +1 -1
  115. package/dist/core/skills.js +7 -4
  116. package/dist/core/skills.js.map +1 -1
  117. package/dist/run.d.ts.map +1 -1
  118. package/dist/run.js +15 -53
  119. package/dist/run.js.map +1 -1
  120. package/dist/version.d.ts +1 -1
  121. package/dist/version.js +1 -1
  122. package/package.json +2 -2
  123. package/templates/agents/canonical.md +0 -2
  124. package/templates/conventions/baseline-conventions.md +1 -34
  125. package/templates/serve/shell.html +3 -0
  126. package/templates/serve/style.css +78 -3
  127. package/templates/skills/ctxr-organize-audit.md +2 -10
  128. package/templates/skills/ctxr-placement.md +6 -24
  129. package/templates/skills/ctxr-publish.md +26 -21
  130. package/templates/skills/ctxr-session-capture.md +1 -4
  131. package/templates/vendor/eli5/LICENSE.txt +21 -0
  132. package/templates/vendor/eli5/SKILL.md +116 -0
  133. package/templates/vendor/eli5/provenance.json +8 -0
  134. package/dist/commands/check.d.ts +0 -30
  135. package/dist/commands/check.d.ts.map +0 -1
  136. package/dist/commands/check.js +0 -65
  137. package/dist/commands/check.js.map +0 -1
  138. package/dist/commands/note-resolve.d.ts +0 -14
  139. package/dist/commands/note-resolve.d.ts.map +0 -1
  140. package/dist/commands/note-resolve.js +0 -24
  141. package/dist/commands/note-resolve.js.map +0 -1
  142. package/dist/core/checks/disclosure-checks.d.ts +0 -4
  143. package/dist/core/checks/disclosure-checks.d.ts.map +0 -1
  144. package/dist/core/checks/disclosure-checks.js +0 -24
  145. package/dist/core/checks/disclosure-checks.js.map +0 -1
  146. package/dist/core/disclosure/leak-scan.d.ts +0 -19
  147. package/dist/core/disclosure/leak-scan.d.ts.map +0 -1
  148. package/dist/core/disclosure/leak-scan.js +0 -31
  149. package/dist/core/disclosure/leak-scan.js.map +0 -1
  150. package/dist/core/disclosure/model.d.ts +0 -29
  151. package/dist/core/disclosure/model.d.ts.map +0 -1
  152. package/dist/core/disclosure/model.js +0 -69
  153. package/dist/core/disclosure/model.js.map +0 -1
  154. package/dist/core/graph/visibility-filter.d.ts +0 -13
  155. package/dist/core/graph/visibility-filter.d.ts.map +0 -1
  156. package/dist/core/graph/visibility-filter.js +0 -26
  157. package/dist/core/graph/visibility-filter.js.map +0 -1
  158. package/dist/core/migrations/rename-visibility-field.d.ts +0 -3
  159. package/dist/core/migrations/rename-visibility-field.d.ts.map +0 -1
  160. package/dist/core/migrations/rename-visibility-field.js +0 -62
  161. package/dist/core/migrations/rename-visibility-field.js.map +0 -1
  162. package/dist/core/notes/checks.d.ts +0 -20
  163. package/dist/core/notes/checks.d.ts.map +0 -1
  164. package/dist/core/notes/checks.js +0 -58
  165. package/dist/core/notes/checks.js.map +0 -1
  166. package/dist/core/notes/visibility.d.ts +0 -26
  167. package/dist/core/notes/visibility.d.ts.map +0 -1
  168. package/dist/core/notes/visibility.js +0 -41
  169. package/dist/core/notes/visibility.js.map +0 -1
@@ -12,26 +12,19 @@ different font. If a note would do the job, the note is the deliverable.
12
12
 
13
13
  ## 2. Name the subject, let the selector produce the set
14
14
 
15
- `ctxr publish gather` resolves a subject to its source notes — never a hand-picked list, which is how a
16
- walled note slips in unnoticed:
15
+ `ctxr publish gather` resolves a subject to its source notes — never a hand-picked list, which is how
16
+ an unintended note slips in unnoticed:
17
17
 
18
18
  - `--under <prefix>` — a store subtree
19
19
  - `--note <path>` — a single note
20
20
  - `--entity <name>` — every note linking to a concept, the same enumeration `ctxr rollup gather` uses
21
- - `--as <context>` — everything a named context can see
22
21
 
23
- ## 3. Gate before copying anything out
22
+ ## 3. Decide what belongs on the page
24
23
 
25
- `ctxr publish gather --audience <audience>` evaluates every resolved note through the same tri-state
26
- disclosure verdict `ctxr check` uses, and reports the worst verdict in the set. Run it FIRST, before
27
- reading a single note for content:
28
-
29
- - **DENY** notes contribute nothing — not a title, not a count, not a paraphrase.
30
- - **ASK** stops the build; name the note to the operator and wait.
31
- - Only **ALLOW** content may be quoted or summarized into the page.
32
-
33
- Never infer a verdict from a note's resolved visibility on your own — an external audience's verdict
34
- requires an explicit tag or a human answer, not an inference from how widely a note is already visible.
24
+ The store does not decide this for you. Read the resolved set and judge, note by note, whether its
25
+ content belongs in front of this page's intended readers — a page written for an outside party must
26
+ not carry material written about that party, or about anyone else who did not expect to be quoted.
27
+ When you are unsure about a note, leave it out and name it to the operator rather than guessing.
35
28
 
36
29
  ## 4. Fix the identity once
37
30
 
@@ -45,10 +38,23 @@ handed out.
45
38
 
46
39
  Pick the shape the content actually needs — a status board, a timeline, a side-by-side comparison, an
47
40
  explainer with a live demo — not a rendering of the source notes in reading order. Contexture ships no
48
- renderer of its own: for visual direction, load the `frontend-design` skill this store carries by
49
- default (or whichever design-focused skill it's configured or installed instead), and follow it for the
50
- actual HTML, CSS, and visual language. If a sibling page already exists, read its stylesheet and
51
- inherit its palette and type scale before inventing a new one.
41
+ renderer of its own and no house voice: both halves of the craft are delegated to a skill.
42
+
43
+ **The form and its visual language.** Load the `frontend-design` skill this store carries by default
44
+ (or whichever design-focused skill it's configured or installed instead) and follow it for the HTML,
45
+ CSS, type, and palette — and for the interface's own words: labels, buttons, empty and error states.
46
+ If a sibling page already exists, read its stylesheet and inherit its palette and type scale before
47
+ inventing a new one.
48
+
49
+ **The prose that explains the subject.** A page is read by someone who wasn't in the sessions the
50
+ notes came from, so the notes' shorthand does not survive the copy out. Load the `eli5` skill this
51
+ store carries by default (or whichever explanation-focused skill it's configured instead), settle who
52
+ the reader is before writing, and pitch every definition, analogy, and level of detail at them.
53
+
54
+ Both skills say "audience", and neither means step 3's. There, `--audience` names who the store is
55
+ being asked to disclose to and the answer is a verdict; here it names how much a reader already knows
56
+ and the answer is a register. A comprehension level is never a value you pass to `--audience`, and
57
+ writing plainly never widens what the page may contain — the gate in step 3 already settled that.
52
58
 
53
59
  ## 6. Verify the output invariants
54
60
 
@@ -56,13 +62,12 @@ inherit its palette and type scale before inventing a new one.
56
62
  a viewport meta tag, at least one print rule, a provenance line, a sibling README, balanced tags, and
57
63
  valid syntax in every embedded script. It exits non-zero naming every failing check; fix all of them
58
64
  before reporting the page as ready. It answers only what's derivable from the file itself — the DO-test
59
- in step 1, the form choice in step 5, and factual accuracy stay judgment calls, not checker output.
65
+ in step 1, the form and reader choices in step 5, and factual accuracy stay judgment calls, not checker output.
60
66
 
61
67
  ## 7. It's a page, not a note
62
68
 
63
69
  The published-pages location is excluded from retrieval by default — a page never becomes a source for
64
- anything else the store retrieves, and it never carries the visibility field (that would falsely signal
65
- it's indexed). Confirm with `ctxr lint` after landing.
70
+ anything else the store retrieves. Confirm with `ctxr lint` after landing.
66
71
 
67
72
  ## 8. Provenance and drift
68
73
 
@@ -58,7 +58,6 @@ calcified, so it never gets retired.
58
58
  ```
59
59
  ### Store notes
60
60
  - A1 path: <layer>/<location>/<Title>.md
61
- visibility: <value> — <one-line rationale; `ctxr note resolve` on a sibling shows the default>
62
61
  sketch: bullets
63
62
 
64
63
  ### House conventions
@@ -84,7 +83,6 @@ notes:
84
83
  - id: A1
85
84
  path: <layer>/<location>/<Title>.md
86
85
  mode: create # or: append
87
- visibility: <value> # optional; omit to take the location default
88
86
  body: |
89
87
  matching the frontmatter and style of the sibling notes (`ctxr-placement` decides the location)
90
88
  ```
@@ -94,8 +92,7 @@ one bad path never blocks the rest. These note commits ride the session pull req
94
92
  (`ctxr-session-lifecycle`).
95
93
 
96
94
  Approved conventions are a direct edit to `__HOUSE_CONVENTIONS_PATH__`, never the YAML above: `ctxr
97
- session capture` writes NOTES — it takes a path, a visibility, and a body, and stamps the visibility
98
- field — and a guidance file is not a note and carries no visibility. Edit it under the matching
95
+ session capture` writes NOTES — it takes a path and a body — and a guidance file is not a note. Edit it under the matching
99
96
  section, then run `ctxr update` so AGENTS.md re-inlines it, and stage BOTH in the same commit: a staged
100
97
  guidance change without a matching staged AGENTS.md regeneration fails `doctor --staged` and the
101
98
  pre-commit hook refuses it. If the file does not exist yet (a store migrated in from before it was
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: eli5
3
+ description: "Explain any topic, code, concept, or error tailored to a specific audience's level of understanding. Use this skill whenever the user says 'explain like I am', 'ELI5', 'explain this to my', 'break this down for', 'dumb it down', 'simplify this for', or asks you to explain something to a specific person or audience type (e.g., 'explain this to a manager', 'how would I explain this to my mom', 'make this understandable for a 5th grader'). Also trigger when the user mentions wanting to understand something at a particular level, or asks for an explanation targeting a non-technical audience. Even partial matches like 'explain to my wife' or 'tell my boss' should trigger this skill."
4
+ ---
5
+
6
+ # Explain Like I Am... (ELI5)
7
+
8
+ You are an expert at taking complex topics and making them accessible to any audience. Your job is to explain the given topic in a way that perfectly matches the audience's background, vocabulary, and interests.
9
+
10
+ ## Step 1: Identify the Audience
11
+
12
+ Parse the user's request to determine who the explanation is for. The audience falls into one of these categories:
13
+
14
+ ### Ages
15
+ | Audience | Style |
16
+ |----------|-------|
17
+ | Age 5 | Super simple words. Use fun analogies with toys, animals, candy, playground. Short sentences. "Imagine you have a box of crayons..." |
18
+ | Age 10 | Elementary school level. Can handle basic cause-and-effect. Use school, sports, video game analogies. |
19
+ | Age 15 | Teenager. Can handle some abstraction. Use social media, phone, gaming references. Be slightly casual. |
20
+ | Age 20-30 | Young adult. Clear and direct. Real-world analogies from daily life, work, money. |
21
+ | Age 40+ | Mature adult. Respectful tone. Analogies from home ownership, career, family management. |
22
+
23
+ ### Grade / Education Levels
24
+ | Audience | Style |
25
+ |----------|-------|
26
+ | 5th grade | Simple vocabulary, concrete examples, avoid jargon entirely. "Think of it like..." |
27
+ | Middle school | Can introduce basic terminology with definitions. Step-by-step logic. |
28
+ | Senior High | Can handle moderate complexity. Introduce proper terms but explain them. SAT-level vocabulary OK. |
29
+ | College Student | Academic framing. Can use technical terms with brief context. Theory + practical application. |
30
+ | Graduate school | Assume strong foundational knowledge. Focus on nuance, trade-offs, edge cases, and deeper implications. Be precise. |
31
+
32
+ ### Job Roles
33
+ | Audience | They care about... | Frame explanations around... |
34
+ |----------|-------------------|------------------------------|
35
+ | Manager | Impact, timeline, risk, cost | Business outcomes, team implications, what decisions need to be made |
36
+ | Engineer | How it works, architecture, trade-offs | Technical details, implementation, performance, maintainability |
37
+ | Designer | User experience, visual impact, flow | How it affects the user, interaction patterns, accessibility |
38
+ | Director | Strategy, ROI, competitive advantage | Big picture, market position, resource allocation |
39
+ | Colleague | Practical context, shared work | How it affects their work, what they need to know to collaborate |
40
+ | Product Manager | User value, priorities, scope | Feature impact, user stories, what to build vs. skip |
41
+
42
+ ### Relationships
43
+ | Audience | Tone | Analogy style |
44
+ |----------|------|---------------|
45
+ | Wife / Husband / Partner | Warm, conversational, patient | Household tasks, shared experiences, daily routines |
46
+ | Father / Mother / Parents | Respectful, clear, no condescension | Familiar technology they use, home analogies, generational bridges |
47
+ | Kids / Children | Playful, encouraging, short | Games, cartoons, school, animals |
48
+ | Friend | Casual, maybe humorous | Pop culture, shared interests, "you know how..." |
49
+
50
+ If the audience isn't explicitly stated, default to "Age 5" (classic ELI5).
51
+
52
+ ## Step 2: Read the Source Material
53
+
54
+ Before explaining, make sure you fully understand what needs to be explained. This could be:
55
+ - **Code**: Read the relevant code files. Understand what the code does at a high level before translating.
56
+ - **A concept**: Break it into its core components.
57
+ - **An error message**: Understand the root cause, not just the surface text.
58
+ - **A technical document**: Extract the key points that matter.
59
+ - **Anything else**: Identify the essential "what" and "why."
60
+
61
+ ## Step 3: Craft the Explanation
62
+
63
+ Follow these principles, scaled to the audience:
64
+
65
+ ### Structure
66
+ 1. **Start with the "what"** — one sentence that captures the essence
67
+ 2. **Use an analogy** — connect to something the audience already knows
68
+ 3. **Fill in details** — add layers only as appropriate for the audience level
69
+ 4. **End with the "so what"** — why does this matter to them specifically?
70
+
71
+ ### Language Calibration
72
+
73
+ For **simple audiences** (young ages, non-technical roles, family):
74
+ - No jargon. Zero. If a technical term is essential, define it immediately.
75
+ - One idea per sentence.
76
+ - Concrete over abstract. "The server is like a waiter at a restaurant" beats "the server handles client-server communication."
77
+ - Use "you" and "your" — make it personal.
78
+
79
+ For **technical audiences** (engineers, grad students):
80
+ - Use proper terminology — they'll feel patronized without it.
81
+ - Focus on the *interesting* parts: trade-offs, edge cases, design decisions.
82
+ - Compare to things they already know: "It's like a hash map but with X difference."
83
+ - Be concise — respect their existing knowledge.
84
+
85
+ For **business audiences** (managers, directors):
86
+ - Lead with impact and outcomes.
87
+ - Quantify where possible.
88
+ - Skip implementation details unless asked.
89
+ - Frame in terms of decisions: "This means we should..."
90
+
91
+ ### Tone Matching
92
+ - Ages 5-10: Enthusiastic, like a favorite teacher. "Oh, this is a cool one!"
93
+ - Teenagers: Slightly casual but not cringey. No "fellow kids" energy.
94
+ - Professionals: Confident and clear. Respect their intelligence while bridging knowledge gaps.
95
+ - Family: Patient, warm, conversational. Like explaining over dinner.
96
+
97
+ ## Examples
98
+
99
+ **User says**: "ELI5 what a database index is"
100
+ **Audience**: Age 5 (default)
101
+ **Response style**: "Imagine you have a huuuge book with thousands of pages. Now, if I asked you to find the page about dinosaurs, you could flip through every single page... or you could look at the table of contents at the front! A database index is like that table of contents. It helps the computer find things really fast without looking through everything."
102
+
103
+ **User says**: "Explain this API rate limiting to my manager"
104
+ **Audience**: Manager
105
+ **Response style**: "The API has a speed limit — we can only make 100 requests per minute. Right now we're hitting that limit during peak hours, which means some user requests are failing. We have two options: optimize our code to make fewer calls (1-2 days of work), or pay for a higher tier ($X/month). I'd recommend..."
106
+
107
+ **User says**: "Break down this React useEffect hook for a college student"
108
+ **Audience**: College Student
109
+ **Response style**: "useEffect is React's way of handling side effects — things that happen outside the normal render cycle, like API calls, subscriptions, or DOM manipulation. Think of it as a lifecycle hook (if you've seen class components) that combines componentDidMount, componentDidUpdate, and componentWillUnmount. The dependency array controls when it re-runs..."
110
+
111
+ ## Important Reminders
112
+
113
+ - Never talk down to anyone. A 5-year-old explanation should feel delightful, not dumbing-down. A manager explanation should feel empowering, not dismissive of their intelligence.
114
+ - When explaining code, always explain the *purpose* first, then the mechanism. Nobody cares about syntax until they know why it exists.
115
+ - If the topic is genuinely complex and the audience is very non-technical, it's OK to simplify ruthlessly. Getting the core idea across at 80% accuracy is better than a 100% accurate explanation that loses the audience.
116
+ - Match the length to the audience: short and sweet for young kids, more detailed for technical audiences who want depth.
@@ -0,0 +1,8 @@
1
+ {
2
+ "source": "DreambigOu/ELI5",
3
+ "subpath": "skills/eli5",
4
+ "ref": "a766623b062331fdde53467001379b4ddf3acc2f",
5
+ "license": "MIT",
6
+ "licensePath": "LICENSE",
7
+ "sha256": "a671efd44a818aee7dbe4ea2ec634079401c3f578c08cb634c2b6181ced2dbe9"
8
+ }
@@ -1,30 +0,0 @@
1
- import type { CommandOutcome, CommandRequires } from '../core/command.js';
2
- import type { DisclosureRung, DisclosureVerdict } from '../core/disclosure/model.js';
3
- import { type LeakFinding } from '../core/disclosure/leak-scan.js';
4
- import type { RunEnv } from '../core/env.js';
5
- import type { Store } from '../core/store.js';
6
- export declare const requires: CommandRequires;
7
- export interface CheckFlags {
8
- path: string;
9
- audience?: string;
10
- scan?: boolean;
11
- }
12
- export interface CheckData {
13
- path: string;
14
- audience?: string;
15
- verdict?: DisclosureVerdict;
16
- rung?: DisclosureRung;
17
- leaks?: LeakFinding[];
18
- }
19
- /**
20
- * disclosure-policy spec: the tri-state ALLOW/DENY/ASK verdict, each with
21
- * its own documented exit code (cli-contract's reserved 4/5), printing the
22
- * rung that produced it so a script or a human can see WHY, not just WHAT.
23
- *
24
- * store-primitives-from-migration-audit spec (D3): `--scan` is a second,
25
- * independent mode — the same leak scan `ctxr lint` runs, for one note —
26
- * and does not require `--audience` (a leak isn't about one requesting
27
- * audience; it's about every configured marker context at once).
28
- */
29
- export declare function execute(env: RunEnv, store: Store, flags: CheckFlags): Promise<CommandOutcome<CheckData>>;
30
- //# sourceMappingURL=check.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErF,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACrF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAK7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,eAAO,MAAM,QAAQ,EAAE,eAAuC,CAAC;AAE/D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;CACvB;AAOD;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CA6C9G"}
@@ -1,65 +0,0 @@
1
- import path from 'node:path';
2
- import { evaluateDisclosure, VERDICT_EXIT_CODE } from '../core/disclosure/model.js';
3
- import { scanNoteForLeaks } from '../core/disclosure/leak-scan.js';
4
- import { CheckAudienceRequiredError, NoteNotFoundError } from '../core/errors.js';
5
- import { ExitCode } from '../core/exit-codes.js';
6
- import { parseNote } from '../core/notes/parse.js';
7
- export const requires = { store: 'required' };
8
- function toStoreRelativePath(env, store, givenPath) {
9
- const absolute = path.isAbsolute(givenPath) ? givenPath : path.resolve(env.cwd, givenPath);
10
- return path.relative(store.root, absolute).split(path.sep).join('/');
11
- }
12
- /**
13
- * disclosure-policy spec: the tri-state ALLOW/DENY/ASK verdict, each with
14
- * its own documented exit code (cli-contract's reserved 4/5), printing the
15
- * rung that produced it so a script or a human can see WHY, not just WHAT.
16
- *
17
- * store-primitives-from-migration-audit spec (D3): `--scan` is a second,
18
- * independent mode — the same leak scan `ctxr lint` runs, for one note —
19
- * and does not require `--audience` (a leak isn't about one requesting
20
- * audience; it's about every configured marker context at once).
21
- */
22
- export async function execute(env, store, flags) {
23
- const relativePath = toStoreRelativePath(env, store, flags.path);
24
- const absolutePath = path.join(store.root, relativePath);
25
- let note;
26
- try {
27
- note = await parseNote(absolutePath, relativePath);
28
- }
29
- catch (err) {
30
- if (err.code === 'ENOENT')
31
- throw new NoteNotFoundError(relativePath);
32
- throw err;
33
- }
34
- if (flags.scan) {
35
- const leaks = scanNoteForLeaks(store.config, note);
36
- const findings = leaks.map((leak) => ({
37
- code: 'disclosure.leak',
38
- severity: 'warning',
39
- message: `"${leak.path}" matches a marker for context "${leak.context}", which cannot see this note: "${leak.matchedText}".`,
40
- subject: leak.path,
41
- details: { context: leak.context, pattern: leak.pattern, matchedText: leak.matchedText },
42
- }));
43
- return {
44
- exitCode: leaks.length > 0 ? ExitCode.CheckFailed : ExitCode.Ok,
45
- data: { path: relativePath, leaks },
46
- findings,
47
- humanSummary: leaks.length > 0 ? `${relativePath}: ${leaks.length} leak(s) found.` : `${relativePath}: no leaks found.`,
48
- storeRoot: store.root,
49
- schemaVersion: store.config.schema_version,
50
- };
51
- }
52
- if (!flags.audience) {
53
- throw new CheckAudienceRequiredError();
54
- }
55
- const { verdict, rung } = evaluateDisclosure(store.config, note, flags.audience);
56
- return {
57
- exitCode: VERDICT_EXIT_CODE[verdict],
58
- data: { path: relativePath, audience: flags.audience, verdict, rung },
59
- findings: [],
60
- humanSummary: `${relativePath} for audience "${flags.audience}": ${verdict.toUpperCase()} (rung: ${rung})`,
61
- storeRoot: store.root,
62
- schemaVersion: store.config.schema_version,
63
- };
64
- }
65
- //# sourceMappingURL=check.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- import type { CommandOutcome, CommandRequires } from '../core/command.js';
2
- import type { RunEnv } from '../core/env.js';
3
- import type { Store } from '../core/store.js';
4
- export declare const requires: CommandRequires;
5
- export interface NoteResolveFlags {
6
- path: string;
7
- }
8
- export interface NoteResolveData {
9
- path: string;
10
- visibility: string;
11
- reason: string;
12
- }
13
- export declare function execute(env: RunEnv, store: Store, flags: NoteResolveFlags): Promise<CommandOutcome<NoteResolveData>>;
14
- //# sourceMappingURL=note-resolve.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"note-resolve.d.ts","sourceRoot":"","sources":["../../src/commands/note-resolve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAI7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,eAAO,MAAM,QAAQ,EAAE,eAAuC,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAOD,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,CAc1C"}
@@ -1,24 +0,0 @@
1
- import path from 'node:path';
2
- import { ExitCode } from '../core/exit-codes.js';
3
- import { parseNote } from '../core/notes/parse.js';
4
- import { resolveVisibility } from '../core/notes/visibility.js';
5
- export const requires = { store: 'required' };
6
- function toStoreRelativePath(env, store, givenPath) {
7
- const absolute = path.isAbsolute(givenPath) ? givenPath : path.resolve(env.cwd, givenPath);
8
- return path.relative(store.root, absolute).split(path.sep).join('/');
9
- }
10
- export async function execute(env, store, flags) {
11
- const relativePath = toStoreRelativePath(env, store, flags.path);
12
- const absolutePath = path.join(store.root, relativePath);
13
- const note = await parseNote(absolutePath, relativePath);
14
- const resolution = resolveVisibility(store.config, note);
15
- return {
16
- exitCode: ExitCode.Ok,
17
- data: { path: relativePath, visibility: resolution.value, reason: resolution.reason },
18
- findings: [],
19
- humanSummary: `${relativePath}: ${resolution.value} (${resolution.reason})`,
20
- storeRoot: store.root,
21
- schemaVersion: store.config.schema_version,
22
- };
23
- }
24
- //# sourceMappingURL=note-resolve.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"note-resolve.js","sourceRoot":"","sources":["../../src/commands/note-resolve.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGhE,MAAM,CAAC,MAAM,QAAQ,GAAoB,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAY/D,SAAS,mBAAmB,CAAC,GAAW,EAAE,KAAY,EAAE,SAAiB;IACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC3F,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,GAAW,EACX,KAAY,EACZ,KAAuB;IAEvB,MAAM,YAAY,GAAG,mBAAmB,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACjE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IACzD,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAEzD,OAAO;QACL,QAAQ,EAAE,QAAQ,CAAC,EAAE;QACrB,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE;QACrF,QAAQ,EAAE,EAAE;QACZ,YAAY,EAAE,GAAG,YAAY,KAAK,UAAU,CAAC,KAAK,KAAK,UAAU,CAAC,MAAM,GAAG;QAC3E,SAAS,EAAE,KAAK,CAAC,IAAI;QACrB,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;KAC3C,CAAC;AACJ,CAAC"}
@@ -1,4 +0,0 @@
1
- /** disclosure-policy spec (store-primitives-from-migration-audit D3): reported by lint, never failed by doctor — a marker match is a judgment call, not an invariant. */
2
- export declare const leakCheck: import("./types.js").CheckDefinition;
3
- export declare const DISCLOSURE_CHECKS: import("./types.js").CheckDefinition[];
4
- //# sourceMappingURL=disclosure-checks.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"disclosure-checks.d.ts","sourceRoot":"","sources":["../../../src/core/checks/disclosure-checks.ts"],"names":[],"mappings":"AAIA,yKAAyK;AACzK,eAAO,MAAM,SAAS,sCAkBpB,CAAC;AAEH,eAAO,MAAM,iBAAiB,wCAAc,CAAC"}
@@ -1,24 +0,0 @@
1
- import { scanForLeaks } from '../disclosure/leak-scan.js';
2
- import { defineCheck } from './types.js';
3
- /** disclosure-policy spec (store-primitives-from-migration-audit D3): reported by lint, never failed by doctor — a marker match is a judgment call, not an invariant. */
4
- export const leakCheck = defineCheck({
5
- id: 'disclosure.leak',
6
- title: "Content matching a context's marker found inside a note that context cannot see",
7
- severity: 'observation',
8
- capability: 'disclosure-policy',
9
- scopes: ['store'],
10
- async run(ctx) {
11
- const notes = await ctx.notes();
12
- const leaks = scanForLeaks(ctx.config, notes);
13
- const findings = leaks.map((leak) => ({
14
- code: 'disclosure.leak',
15
- severity: 'warning',
16
- message: `"${leak.path}" matches a marker for context "${leak.context}", which cannot see this note: "${leak.matchedText}".`,
17
- subject: leak.path,
18
- details: { context: leak.context, pattern: leak.pattern, matchedText: leak.matchedText },
19
- }));
20
- return { status: findings.length > 0 ? 'fail' : 'pass', findings };
21
- },
22
- });
23
- export const DISCLOSURE_CHECKS = [leakCheck];
24
- //# sourceMappingURL=disclosure-checks.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"disclosure-checks.js","sourceRoot":"","sources":["../../../src/core/checks/disclosure-checks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,yKAAyK;AACzK,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;IACnC,EAAE,EAAE,iBAAiB;IACrB,KAAK,EAAE,iFAAiF;IACxF,QAAQ,EAAE,aAAa;IACvB,UAAU,EAAE,mBAAmB;IAC/B,MAAM,EAAE,CAAC,OAAO,CAAC;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG;QACX,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAc,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/C,IAAI,EAAE,iBAAiB;YACvB,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,IAAI,IAAI,CAAC,IAAI,mCAAmC,IAAI,CAAC,OAAO,mCAAmC,IAAI,CAAC,WAAW,IAAI;YAC5H,OAAO,EAAE,IAAI,CAAC,IAAI;YAClB,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE;SACzF,CAAC,CAAC,CAAC;QACJ,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;IACrE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,SAAS,CAAC,CAAC"}
@@ -1,19 +0,0 @@
1
- import type { StoreConfig } from '../../config/schema.js';
2
- import type { Note } from '../notes/list.js';
3
- export interface LeakFinding {
4
- path: string;
5
- context: string;
6
- pattern: string;
7
- matchedText: string;
8
- }
9
- /**
10
- * disclosure-policy spec (store-primitives-from-migration-audit D3): a leak
11
- * is content that belongs to context X (per an operator-declared marker
12
- * pattern) inside a note X cannot see, per the SAME context→visible-values
13
- * mapping the visibility pre-filter and disclosure's internal-audience rung
14
- * use — "X cannot see the note" is exactly `!canSee(config, X, resolved)`.
15
- * Empty markers (the default) make this a no-op for every note.
16
- */
17
- export declare function scanNoteForLeaks(config: StoreConfig, note: Note): LeakFinding[];
18
- export declare function scanForLeaks(config: StoreConfig, notes: readonly Note[]): LeakFinding[];
19
- //# sourceMappingURL=leak-scan.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"leak-scan.d.ts","sourceRoot":"","sources":["../../../src/core/disclosure/leak-scan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAG7C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,GAAG,WAAW,EAAE,CAgB/E;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,WAAW,EAAE,CAEvF"}
@@ -1,31 +0,0 @@
1
- import { canSee, resolveVisibility } from '../notes/visibility.js';
2
- /**
3
- * disclosure-policy spec (store-primitives-from-migration-audit D3): a leak
4
- * is content that belongs to context X (per an operator-declared marker
5
- * pattern) inside a note X cannot see, per the SAME context→visible-values
6
- * mapping the visibility pre-filter and disclosure's internal-audience rung
7
- * use — "X cannot see the note" is exactly `!canSee(config, X, resolved)`.
8
- * Empty markers (the default) make this a no-op for every note.
9
- */
10
- export function scanNoteForLeaks(config, note) {
11
- const markers = config.disclosure.leak_markers;
12
- if (Object.keys(markers).length === 0)
13
- return [];
14
- const resolved = resolveVisibility(config, note).value;
15
- const findings = [];
16
- for (const [context, patterns] of Object.entries(markers)) {
17
- if (canSee(config, context, resolved))
18
- continue;
19
- for (const pattern of patterns) {
20
- const match = new RegExp(pattern).exec(note.body);
21
- if (match) {
22
- findings.push({ path: note.path, context, pattern, matchedText: match[0] });
23
- }
24
- }
25
- }
26
- return findings;
27
- }
28
- export function scanForLeaks(config, notes) {
29
- return notes.flatMap((note) => scanNoteForLeaks(config, note));
30
- }
31
- //# sourceMappingURL=leak-scan.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"leak-scan.js","sourceRoot":"","sources":["../../../src/core/disclosure/leak-scan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AASnE;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAmB,EAAE,IAAU;IAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC;IAC/C,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEjD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC;IACvD,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1D,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC;YAAE,SAAS;QAChD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClD,IAAI,KAAK,EAAE,CAAC;gBACV,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAmB,EAAE,KAAsB;IACtE,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;AACjE,CAAC"}
@@ -1,29 +0,0 @@
1
- import type { StoreConfig } from '../../config/schema.js';
2
- import { ExitCode } from '../exit-codes.js';
3
- import type { Note } from '../notes/list.js';
4
- export type DisclosureVerdict = 'allow' | 'deny' | 'ask';
5
- /** disclosure-policy spec: each tri-state verdict's own distinct, documented exit code — defined once for every caller (single-note or aggregate). */
6
- export declare const VERDICT_EXIT_CODE: Record<DisclosureVerdict, ExitCode>;
7
- export type DisclosureRung = 'hard_wall' | 'explicit_tag' | 'internal_visibility' | 'external_default';
8
- export interface DisclosureResult {
9
- verdict: DisclosureVerdict;
10
- rung: DisclosureRung;
11
- }
12
- /**
13
- * disclosure-policy spec: ordered walls-before-allows evaluation, stopping
14
- * at the first rung that produces a verdict. Rung 3 (internal-audience-
15
- * from-visibility) only applies when the requested audience is one the
16
- * operator has declared internal — for any other (external) audience, rung
17
- * 3 is skipped entirely and evaluation falls straight to rung 4's ASK, so an
18
- * external verdict is never derived from visibility alone.
19
- */
20
- export declare function evaluateDisclosure(config: StoreConfig, note: Note, audience: string): DisclosureResult;
21
- /**
22
- * disclosure-policy spec: a set of verdicts aggregates to its most
23
- * restrictive member — DENY outranks ASK, which outranks ALLOW. An empty
24
- * set aggregates to ALLOW; callers that need to distinguish "nothing was
25
- * evaluated" from "everything was evaluated and allowed" report the set's
26
- * size separately, per the publish spec's empty-set scenario.
27
- */
28
- export declare function worstVerdict(verdicts: readonly DisclosureVerdict[]): DisclosureVerdict;
29
- //# sourceMappingURL=model.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/core/disclosure/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAG7C,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAEzD,sJAAsJ;AACtJ,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,QAAQ,CAIjE,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,cAAc,GAAG,qBAAqB,GAAG,kBAAkB,CAAC;AAEvG,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,IAAI,EAAE,cAAc,CAAC;CACtB;AAoBD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAkBtG;AAKD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,GAAG,iBAAiB,CAMtF"}
@@ -1,69 +0,0 @@
1
- import { ExitCode } from '../exit-codes.js';
2
- import { canSee, resolveVisibility } from '../notes/visibility.js';
3
- /** disclosure-policy spec: each tri-state verdict's own distinct, documented exit code — defined once for every caller (single-note or aggregate). */
4
- export const VERDICT_EXIT_CODE = {
5
- allow: ExitCode.Ok,
6
- deny: ExitCode.DisclosureDeny,
7
- ask: ExitCode.DisclosureAsk,
8
- };
9
- /**
10
- * The frontmatter key a note uses to explicitly declare which audiences may
11
- * see it disclosed (rung 2). Unlike the visibility field (context-store
12
- * spec), nothing asks this key to be configurable, so it lives here as the
13
- * one literal — same discipline as every other single-purpose constant in
14
- * this codebase, just without a dedicated defaults.ts entry since no other
15
- * module needs to reference it.
16
- */
17
- const AUDIENCE_FIELD_KEY = 'audience';
18
- function matchesWall(wall, note, audience) {
19
- if (wall.audience !== '*' && wall.audience !== audience)
20
- return false;
21
- if (wall.except?.includes(audience))
22
- return false;
23
- if (!wall.note_path_prefix)
24
- return true;
25
- const prefix = wall.note_path_prefix.endsWith('/') ? wall.note_path_prefix : `${wall.note_path_prefix}/`;
26
- return note.path === wall.note_path_prefix || note.path.startsWith(prefix);
27
- }
28
- /**
29
- * disclosure-policy spec: ordered walls-before-allows evaluation, stopping
30
- * at the first rung that produces a verdict. Rung 3 (internal-audience-
31
- * from-visibility) only applies when the requested audience is one the
32
- * operator has declared internal — for any other (external) audience, rung
33
- * 3 is skipped entirely and evaluation falls straight to rung 4's ASK, so an
34
- * external verdict is never derived from visibility alone.
35
- */
36
- export function evaluateDisclosure(config, note, audience) {
37
- for (const wall of config.disclosure.hard_walls) {
38
- if (matchesWall(wall, note, audience)) {
39
- return { verdict: wall.verdict, rung: 'hard_wall' };
40
- }
41
- }
42
- const tags = note.frontmatter?.[AUDIENCE_FIELD_KEY];
43
- if (Array.isArray(tags) && tags.includes(audience)) {
44
- return { verdict: 'allow', rung: 'explicit_tag' };
45
- }
46
- if (config.disclosure.internal_audiences.includes(audience)) {
47
- const resolved = resolveVisibility(config, note);
48
- return { verdict: canSee(config, audience, resolved.value) ? 'allow' : 'deny', rung: 'internal_visibility' };
49
- }
50
- return { verdict: 'ask', rung: 'external_default' };
51
- }
52
- /** disclosure-policy spec: most-restrictive-member ordering, defined once for reuse by any caller batching verdicts across a set of notes. */
53
- const VERDICT_RESTRICTIVENESS = { deny: 2, ask: 1, allow: 0 };
54
- /**
55
- * disclosure-policy spec: a set of verdicts aggregates to its most
56
- * restrictive member — DENY outranks ASK, which outranks ALLOW. An empty
57
- * set aggregates to ALLOW; callers that need to distinguish "nothing was
58
- * evaluated" from "everything was evaluated and allowed" report the set's
59
- * size separately, per the publish spec's empty-set scenario.
60
- */
61
- export function worstVerdict(verdicts) {
62
- let worst = 'allow';
63
- for (const verdict of verdicts) {
64
- if (VERDICT_RESTRICTIVENESS[verdict] > VERDICT_RESTRICTIVENESS[worst])
65
- worst = verdict;
66
- }
67
- return worst;
68
- }
69
- //# sourceMappingURL=model.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/core/disclosure/model.ts"],"names":[],"mappings":"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"}