crewly 1.20.184 → 1.20.186

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 (184) hide show
  1. package/config/constants.ts +83 -0
  2. package/config/index.ts +2 -0
  3. package/config/oss-boundary-allowlist.json +10 -0
  4. package/config/skills/agent/core/ask-owner/SKILL.md +5 -2
  5. package/config/skills/agent/core/complete-task/execute.sh +4 -12
  6. package/config/skills/agent/core/complete-task/execute.test.sh +11 -0
  7. package/config/skills/agent/core/report-status/SKILL.md +1 -1
  8. package/config/skills/agent/core/report-status/execute.sh +5 -10
  9. package/dist/backend/backend/src/constants.d.ts +50 -0
  10. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  11. package/dist/backend/backend/src/constants.js +45 -1
  12. package/dist/backend/backend/src/constants.js.map +1 -1
  13. package/dist/backend/backend/src/controllers/decisions/decisions.controller.d.ts +11 -1
  14. package/dist/backend/backend/src/controllers/decisions/decisions.controller.d.ts.map +1 -1
  15. package/dist/backend/backend/src/controllers/decisions/decisions.controller.js +38 -0
  16. package/dist/backend/backend/src/controllers/decisions/decisions.controller.js.map +1 -1
  17. package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
  18. package/dist/backend/backend/src/controllers/google/google.controller.js +3 -2
  19. package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
  20. package/dist/backend/backend/src/controllers/request/open-items.controller.d.ts +9 -0
  21. package/dist/backend/backend/src/controllers/request/open-items.controller.d.ts.map +1 -1
  22. package/dist/backend/backend/src/controllers/request/open-items.controller.js +29 -1
  23. package/dist/backend/backend/src/controllers/request/open-items.controller.js.map +1 -1
  24. package/dist/backend/backend/src/controllers/request/request.routes.d.ts +1 -0
  25. package/dist/backend/backend/src/controllers/request/request.routes.d.ts.map +1 -1
  26. package/dist/backend/backend/src/controllers/request/request.routes.js +4 -1
  27. package/dist/backend/backend/src/controllers/request/request.routes.js.map +1 -1
  28. package/dist/backend/backend/src/controllers/standing/standing.controller.d.ts +5 -2
  29. package/dist/backend/backend/src/controllers/standing/standing.controller.d.ts.map +1 -1
  30. package/dist/backend/backend/src/controllers/standing/standing.controller.js +3 -1
  31. package/dist/backend/backend/src/controllers/standing/standing.controller.js.map +1 -1
  32. package/dist/backend/backend/src/index.d.ts.map +1 -1
  33. package/dist/backend/backend/src/index.js +15 -1
  34. package/dist/backend/backend/src/index.js.map +1 -1
  35. package/dist/backend/backend/src/scripts/check-oss-boundary.d.ts +217 -0
  36. package/dist/backend/backend/src/scripts/check-oss-boundary.d.ts.map +1 -0
  37. package/dist/backend/backend/src/scripts/check-oss-boundary.js +490 -0
  38. package/dist/backend/backend/src/scripts/check-oss-boundary.js.map +1 -0
  39. package/dist/backend/backend/src/services/ai/prompt-modules/standing-answers.module.d.ts +3 -1
  40. package/dist/backend/backend/src/services/ai/prompt-modules/standing-answers.module.d.ts.map +1 -1
  41. package/dist/backend/backend/src/services/ai/prompt-modules/standing-answers.module.js +15 -4
  42. package/dist/backend/backend/src/services/ai/prompt-modules/standing-answers.module.js.map +1 -1
  43. package/dist/backend/backend/src/services/decisions/decision-card.d.ts +31 -4
  44. package/dist/backend/backend/src/services/decisions/decision-card.d.ts.map +1 -1
  45. package/dist/backend/backend/src/services/decisions/decision-card.js +60 -2
  46. package/dist/backend/backend/src/services/decisions/decision-card.js.map +1 -1
  47. package/dist/backend/backend/src/services/decisions/decision-skip-command.d.ts +56 -0
  48. package/dist/backend/backend/src/services/decisions/decision-skip-command.d.ts.map +1 -0
  49. package/dist/backend/backend/src/services/decisions/decision-skip-command.js +108 -0
  50. package/dist/backend/backend/src/services/decisions/decision-skip-command.js.map +1 -0
  51. package/dist/backend/backend/src/services/decisions/decision.service.d.ts +114 -2
  52. package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  53. package/dist/backend/backend/src/services/decisions/decision.service.js +224 -12
  54. package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
  55. package/dist/backend/backend/src/services/decisions/decision.wiring.d.ts +8 -0
  56. package/dist/backend/backend/src/services/decisions/decision.wiring.d.ts.map +1 -1
  57. package/dist/backend/backend/src/services/decisions/decision.wiring.js +25 -0
  58. package/dist/backend/backend/src/services/decisions/decision.wiring.js.map +1 -1
  59. package/dist/backend/backend/src/services/memory/agent-memory.service.d.ts +19 -0
  60. package/dist/backend/backend/src/services/memory/agent-memory.service.d.ts.map +1 -1
  61. package/dist/backend/backend/src/services/memory/agent-memory.service.js +48 -0
  62. package/dist/backend/backend/src/services/memory/agent-memory.service.js.map +1 -1
  63. package/dist/backend/backend/src/services/memory/memory.service.d.ts.map +1 -1
  64. package/dist/backend/backend/src/services/memory/memory.service.js +20 -0
  65. package/dist/backend/backend/src/services/memory/memory.service.js.map +1 -1
  66. package/dist/backend/backend/src/services/memory/project-memory.service.d.ts +40 -0
  67. package/dist/backend/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
  68. package/dist/backend/backend/src/services/memory/project-memory.service.js +101 -0
  69. package/dist/backend/backend/src/services/memory/project-memory.service.js.map +1 -1
  70. package/dist/backend/backend/src/services/memory/role-knowledge-eligibility.d.ts +1 -1
  71. package/dist/backend/backend/src/services/memory/role-knowledge-eligibility.d.ts.map +1 -1
  72. package/dist/backend/backend/src/services/memory/role-knowledge-eligibility.js.map +1 -1
  73. package/dist/backend/backend/src/services/memory/standing-answers.service.d.ts +61 -1
  74. package/dist/backend/backend/src/services/memory/standing-answers.service.d.ts.map +1 -1
  75. package/dist/backend/backend/src/services/memory/standing-answers.service.js +71 -3
  76. package/dist/backend/backend/src/services/memory/standing-answers.service.js.map +1 -1
  77. package/dist/backend/backend/src/services/memory/standing-refresh.service.d.ts +7 -4
  78. package/dist/backend/backend/src/services/memory/standing-refresh.service.d.ts.map +1 -1
  79. package/dist/backend/backend/src/services/memory/standing-refresh.service.js +18 -9
  80. package/dist/backend/backend/src/services/memory/standing-refresh.service.js.map +1 -1
  81. package/dist/backend/backend/src/services/memory/task-log-filter.d.ts +27 -0
  82. package/dist/backend/backend/src/services/memory/task-log-filter.d.ts.map +1 -0
  83. package/dist/backend/backend/src/services/memory/task-log-filter.js +56 -0
  84. package/dist/backend/backend/src/services/memory/task-log-filter.js.map +1 -0
  85. package/dist/backend/backend/src/services/open-items/open-items-backfill.d.ts +26 -1
  86. package/dist/backend/backend/src/services/open-items/open-items-backfill.d.ts.map +1 -1
  87. package/dist/backend/backend/src/services/open-items/open-items-backfill.js +59 -3
  88. package/dist/backend/backend/src/services/open-items/open-items-backfill.js.map +1 -1
  89. package/dist/backend/backend/src/services/open-items/open-items.service.d.ts +37 -2
  90. package/dist/backend/backend/src/services/open-items/open-items.service.d.ts.map +1 -1
  91. package/dist/backend/backend/src/services/open-items/open-items.service.js +101 -6
  92. package/dist/backend/backend/src/services/open-items/open-items.service.js.map +1 -1
  93. package/dist/backend/backend/src/services/open-items/open-items.wiring.d.ts.map +1 -1
  94. package/dist/backend/backend/src/services/open-items/open-items.wiring.js +13 -0
  95. package/dist/backend/backend/src/services/open-items/open-items.wiring.js.map +1 -1
  96. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +13 -0
  97. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  98. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +34 -11
  99. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  100. package/dist/backend/backend/src/services/wiki/wiki-process.service.d.ts.map +1 -1
  101. package/dist/backend/backend/src/services/wiki/wiki-process.service.js +4 -2
  102. package/dist/backend/backend/src/services/wiki/wiki-process.service.js.map +1 -1
  103. package/dist/backend/backend/src/services/wiki/wiki-queue.service.d.ts +103 -1
  104. package/dist/backend/backend/src/services/wiki/wiki-queue.service.d.ts.map +1 -1
  105. package/dist/backend/backend/src/services/wiki/wiki-queue.service.js +171 -20
  106. package/dist/backend/backend/src/services/wiki/wiki-queue.service.js.map +1 -1
  107. package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.d.ts +60 -0
  108. package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.d.ts.map +1 -1
  109. package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.js +121 -7
  110. package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.js.map +1 -1
  111. package/dist/backend/backend/src/types/decision.types.d.ts +20 -3
  112. package/dist/backend/backend/src/types/decision.types.d.ts.map +1 -1
  113. package/dist/backend/backend/src/types/v2/open-item.types.d.ts +4 -1
  114. package/dist/backend/backend/src/types/v2/open-item.types.d.ts.map +1 -1
  115. package/dist/backend/backend/src/types/v2/open-item.types.js.map +1 -1
  116. package/dist/backend/build-info.json +2 -2
  117. package/dist/backend/config/constants.d.ts +73 -0
  118. package/dist/backend/config/constants.d.ts.map +1 -1
  119. package/dist/backend/config/constants.js +80 -0
  120. package/dist/backend/config/constants.js.map +1 -1
  121. package/dist/backend/config/index.d.ts +10 -2
  122. package/dist/backend/config/index.d.ts.map +1 -1
  123. package/dist/backend/config/index.js +2 -2
  124. package/dist/backend/config/index.js.map +1 -1
  125. package/dist/cli/backend/src/constants.d.ts +50 -0
  126. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  127. package/dist/cli/backend/src/constants.js +45 -1
  128. package/dist/cli/backend/src/constants.js.map +1 -1
  129. package/dist/cli/backend/src/services/ai/prompt-modules/standing-answers.module.d.ts +3 -1
  130. package/dist/cli/backend/src/services/ai/prompt-modules/standing-answers.module.d.ts.map +1 -1
  131. package/dist/cli/backend/src/services/ai/prompt-modules/standing-answers.module.js +15 -4
  132. package/dist/cli/backend/src/services/ai/prompt-modules/standing-answers.module.js.map +1 -1
  133. package/dist/cli/backend/src/services/decisions/decision-card.d.ts +31 -4
  134. package/dist/cli/backend/src/services/decisions/decision-card.d.ts.map +1 -1
  135. package/dist/cli/backend/src/services/decisions/decision-card.js +60 -2
  136. package/dist/cli/backend/src/services/decisions/decision-card.js.map +1 -1
  137. package/dist/cli/backend/src/services/decisions/decision.service.d.ts +114 -2
  138. package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  139. package/dist/cli/backend/src/services/decisions/decision.service.js +224 -12
  140. package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -1
  141. package/dist/cli/backend/src/services/memory/agent-memory.service.d.ts +19 -0
  142. package/dist/cli/backend/src/services/memory/agent-memory.service.d.ts.map +1 -1
  143. package/dist/cli/backend/src/services/memory/agent-memory.service.js +48 -0
  144. package/dist/cli/backend/src/services/memory/agent-memory.service.js.map +1 -1
  145. package/dist/cli/backend/src/services/memory/memory.service.d.ts.map +1 -1
  146. package/dist/cli/backend/src/services/memory/memory.service.js +20 -0
  147. package/dist/cli/backend/src/services/memory/memory.service.js.map +1 -1
  148. package/dist/cli/backend/src/services/memory/project-memory.service.d.ts +40 -0
  149. package/dist/cli/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
  150. package/dist/cli/backend/src/services/memory/project-memory.service.js +101 -0
  151. package/dist/cli/backend/src/services/memory/project-memory.service.js.map +1 -1
  152. package/dist/cli/backend/src/services/memory/role-knowledge-eligibility.d.ts +1 -1
  153. package/dist/cli/backend/src/services/memory/role-knowledge-eligibility.d.ts.map +1 -1
  154. package/dist/cli/backend/src/services/memory/role-knowledge-eligibility.js.map +1 -1
  155. package/dist/cli/backend/src/services/memory/standing-answers.service.d.ts +61 -1
  156. package/dist/cli/backend/src/services/memory/standing-answers.service.d.ts.map +1 -1
  157. package/dist/cli/backend/src/services/memory/standing-answers.service.js +71 -3
  158. package/dist/cli/backend/src/services/memory/standing-answers.service.js.map +1 -1
  159. package/dist/cli/backend/src/services/memory/task-log-filter.d.ts +27 -0
  160. package/dist/cli/backend/src/services/memory/task-log-filter.d.ts.map +1 -0
  161. package/dist/cli/backend/src/services/memory/task-log-filter.js +56 -0
  162. package/dist/cli/backend/src/services/memory/task-log-filter.js.map +1 -0
  163. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts +13 -0
  164. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  165. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +34 -11
  166. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  167. package/dist/cli/backend/src/types/decision.types.d.ts +20 -3
  168. package/dist/cli/backend/src/types/decision.types.d.ts.map +1 -1
  169. package/dist/cli/backend/src/types/v2/open-item.types.d.ts +4 -1
  170. package/dist/cli/backend/src/types/v2/open-item.types.d.ts.map +1 -1
  171. package/dist/cli/backend/src/types/v2/open-item.types.js.map +1 -1
  172. package/dist/cli/config/constants.d.ts +73 -0
  173. package/dist/cli/config/constants.d.ts.map +1 -1
  174. package/dist/cli/config/constants.js +80 -0
  175. package/dist/cli/config/constants.js.map +1 -1
  176. package/dist/cli/config/index.d.ts +10 -2
  177. package/dist/cli/config/index.d.ts.map +1 -1
  178. package/dist/cli/config/index.js +2 -2
  179. package/dist/cli/config/index.js.map +1 -1
  180. package/frontend/dist/assets/{index-a6cb8533.js → index-1ee8a9a2.js} +273 -273
  181. package/frontend/dist/assets/index-a79c7852.css +42 -0
  182. package/frontend/dist/index.html +2 -2
  183. package/package.json +2 -1
  184. package/frontend/dist/assets/index-04d192f8.css +0 -42
@@ -0,0 +1,490 @@
1
+ /**
2
+ * OSS/Pro boundary check (issue #809).
3
+ *
4
+ * CLAUDE.md Critical Rule 10 says premium/paid content never lives in the OSS
5
+ * repo. This module turns that prose into a check that fails when:
6
+ *
7
+ * 1. `paid-tier` — a JSON file under `config/templates/` declares
8
+ * `requiredTier` of `pro` or `enterprise` (at any depth);
9
+ * 2. `pro-template-field` — a JSON template under `config/templates/`
10
+ * defines a Pro-only top-level field (`workflows`,
11
+ * `verificationPipeline`, `qualityGates`);
12
+ * 3. `premium-path` — a file path under `config/` has a segment starting
13
+ * with `pro-` or containing `premium` (so `prompt`, `process-` and
14
+ * `improve-` are not matched);
15
+ * 4. `pro-import` — an OSS source file imports or requires `crewly-pro` or
16
+ * `@crewly/pro` (only real import/require specifiers count, never
17
+ * comments or prose).
18
+ *
19
+ * Exceptions live in `config/oss-boundary-allowlist.json`, one entry per
20
+ * path with the rule it is exempt from and a one-line reason.
21
+ *
22
+ * Run locally or in CI with `npm run check:oss-boundary`; the jest suite also
23
+ * runs it against the real tree (see `check-oss-boundary.test.ts`).
24
+ *
25
+ * @module backend/scripts/check-oss-boundary
26
+ */
27
+ import { existsSync, readFileSync, readdirSync } from 'fs';
28
+ import { extname, join, relative, sep } from 'path';
29
+ import { OSS_BOUNDARY_CONSTANTS, PROCESS_EXIT_CODES } from '../../../config/index.js';
30
+ const RULE_VALUES = Object.values(OSS_BOUNDARY_CONSTANTS.RULES);
31
+ /**
32
+ * Type guard for a rule identifier read from untrusted JSON.
33
+ *
34
+ * @param value - Candidate value
35
+ * @returns true when the value names one of the four rules
36
+ */
37
+ export function isOssBoundaryRule(value) {
38
+ return typeof value === 'string' && RULE_VALUES.includes(value);
39
+ }
40
+ /**
41
+ * Converts a path relative to the repo root into `/`-separated form so
42
+ * reports and allowlist entries look the same on every platform.
43
+ *
44
+ * @param repoRoot - Absolute repository root
45
+ * @param absolutePath - Absolute path inside the repository
46
+ * @returns The repository-relative POSIX path
47
+ */
48
+ function toRepoPath(repoRoot, absolutePath) {
49
+ return relative(repoRoot, absolutePath).split(sep).join('/');
50
+ }
51
+ /**
52
+ * Recursively lists every file below a directory, skipping `node_modules`,
53
+ * `dist` and `.git`. A missing directory yields no files.
54
+ *
55
+ * @param dir - Absolute directory to walk
56
+ * @returns Absolute file paths, sorted for stable output
57
+ */
58
+ export function listFiles(dir) {
59
+ if (!existsSync(dir)) {
60
+ return [];
61
+ }
62
+ const skipped = OSS_BOUNDARY_CONSTANTS.SKIPPED_DIRS;
63
+ const files = [];
64
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
65
+ const full = join(dir, entry.name);
66
+ if (entry.isDirectory()) {
67
+ if (!skipped.includes(entry.name)) {
68
+ files.push(...listFiles(full));
69
+ }
70
+ }
71
+ else if (entry.isFile()) {
72
+ files.push(full);
73
+ }
74
+ }
75
+ return files.sort();
76
+ }
77
+ /**
78
+ * Parses a JSON template file.
79
+ *
80
+ * @param file - Absolute path of the JSON file
81
+ * @param repoPath - Repository-relative path, used in the error message
82
+ * @returns The parsed value
83
+ * @throws Error when the file is not valid JSON — a broken template must not
84
+ * silently slip past the check
85
+ */
86
+ function readJson(file, repoPath) {
87
+ try {
88
+ return JSON.parse(readFileSync(file, 'utf8'));
89
+ }
90
+ catch (err) {
91
+ const message = err instanceof Error ? err.message : String(err);
92
+ throw new Error(`check-oss-boundary: ${repoPath} is not valid JSON (${message})`);
93
+ }
94
+ }
95
+ /**
96
+ * Narrows an unknown value to a plain JSON object.
97
+ *
98
+ * @param value - Candidate value
99
+ * @returns true when the value is a non-null, non-array object
100
+ */
101
+ function isJsonObject(value) {
102
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
103
+ }
104
+ /**
105
+ * Finds every paid `requiredTier` declaration anywhere inside a JSON value.
106
+ *
107
+ * @param value - Parsed JSON
108
+ * @param pointer - JSON pointer of `value` (empty for the document root)
109
+ * @returns Human-readable descriptions of each paid-tier declaration
110
+ */
111
+ export function findPaidTierDeclarations(value, pointer = '') {
112
+ const paidTiers = OSS_BOUNDARY_CONSTANTS.PAID_TIERS;
113
+ const found = [];
114
+ if (Array.isArray(value)) {
115
+ value.forEach((item, index) => found.push(...findPaidTierDeclarations(item, `${pointer}/${index}`)));
116
+ }
117
+ else if (isJsonObject(value)) {
118
+ for (const [key, child] of Object.entries(value)) {
119
+ const childPointer = `${pointer}/${key}`;
120
+ if (key === OSS_BOUNDARY_CONSTANTS.TIER_FIELD &&
121
+ typeof child === 'string' &&
122
+ paidTiers.includes(child.toLowerCase())) {
123
+ found.push(`${childPointer} is "${child}"`);
124
+ }
125
+ found.push(...findPaidTierDeclarations(child, childPointer));
126
+ }
127
+ }
128
+ return found;
129
+ }
130
+ /**
131
+ * Lists the Pro-only fields a template defines at its top level.
132
+ *
133
+ * @param value - Parsed template JSON
134
+ * @returns Names of the Pro-only fields present
135
+ */
136
+ export function findProOnlyTemplateFields(value) {
137
+ if (!isJsonObject(value)) {
138
+ return [];
139
+ }
140
+ return OSS_BOUNDARY_CONSTANTS.PRO_ONLY_TEMPLATE_FIELDS.filter((field) => field in value);
141
+ }
142
+ /**
143
+ * Returns the path segments that look like Pro or premium content: a segment
144
+ * that starts with `pro-` or contains `premium` (case-insensitive). Whole
145
+ * segments are tested so names like `prompt`, `process-` or `improve-` never
146
+ * match.
147
+ *
148
+ * @param repoPath - `/`-separated path
149
+ * @returns The offending segments, empty when the path is clean
150
+ */
151
+ export function findPremiumSegments(repoPath) {
152
+ return repoPath.split('/').filter((segment) => {
153
+ const lower = segment.toLowerCase();
154
+ return (lower.startsWith(OSS_BOUNDARY_CONSTANTS.PRO_SEGMENT_PREFIX) ||
155
+ lower.includes(OSS_BOUNDARY_CONSTANTS.PREMIUM_SEGMENT_MARKER));
156
+ });
157
+ }
158
+ /**
159
+ * Blanks out comments in JS/TS source while keeping string literals, so
160
+ * import specifiers can be matched without tripping on commented-out code
161
+ * or prose. Quoted strings end at a newline, which bounds the damage a
162
+ * regex literal containing a quote can do.
163
+ *
164
+ * @param source - Source text
165
+ * @returns The source with every comment replaced by spaces
166
+ */
167
+ export function stripComments(source) {
168
+ let out = '';
169
+ let i = 0;
170
+ while (i < source.length) {
171
+ const ch = source[i];
172
+ const next = source[i + 1];
173
+ if (ch === '/' && next === '/') {
174
+ while (i < source.length && source[i] !== '\n') {
175
+ out += ' ';
176
+ i++;
177
+ }
178
+ }
179
+ else if (ch === '/' && next === '*') {
180
+ const end = source.indexOf('*/', i + 2);
181
+ const stop = end === -1 ? source.length : end + 2;
182
+ out += source.slice(i, stop).replace(/[^\n]/g, ' ');
183
+ i = stop;
184
+ }
185
+ else if (ch === '"' || ch === "'" || ch === '`') {
186
+ let j = i + 1;
187
+ while (j < source.length && source[j] !== ch && (ch === '`' || source[j] !== '\n')) {
188
+ j += source[j] === '\\' ? 2 : 1;
189
+ }
190
+ const stop = Math.min(j + 1, source.length);
191
+ out += source.slice(i, stop);
192
+ i = stop;
193
+ }
194
+ else {
195
+ out += ch;
196
+ i++;
197
+ }
198
+ }
199
+ return out;
200
+ }
201
+ /** Patterns whose first capture group is a module specifier */
202
+ const SPECIFIER_PATTERNS = [
203
+ // import x from '…' / export { x } from '…' / import type { T } from '…'
204
+ /\bfrom\s*(['"])([^'"\n]+)\1/g,
205
+ // import '…' (side-effect import)
206
+ /\bimport\s*(['"])([^'"\n]+)\1/g,
207
+ // import('…') (dynamic import) and require('…')
208
+ /\b(?:import|require)\s*\(\s*(['"`])([^'"`\n]+)\1\s*\)/g,
209
+ ];
210
+ /**
211
+ * Extracts the module specifiers a source file imports or requires.
212
+ *
213
+ * @param source - JS/TS source text
214
+ * @returns Every specifier found, in order of appearance per pattern
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * extractImportSpecifiers("import a from 'x'; const b = require('y');"); // ['x', 'y']
219
+ * ```
220
+ */
221
+ export function extractImportSpecifiers(source) {
222
+ const code = stripComments(source);
223
+ const specifiers = [];
224
+ for (const pattern of SPECIFIER_PATTERNS) {
225
+ for (const match of code.matchAll(pattern)) {
226
+ specifiers.push(match[2]);
227
+ }
228
+ }
229
+ return specifiers;
230
+ }
231
+ /**
232
+ * Tells whether a specifier names a forbidden Pro package or one of its
233
+ * subpaths (e.g. `crewly-pro/dist/x`). Look-alikes such as `crewly-protocol`
234
+ * do not match.
235
+ *
236
+ * @param specifier - Module specifier
237
+ * @returns The forbidden package name, or null
238
+ */
239
+ export function forbiddenPackageFor(specifier) {
240
+ for (const pkg of OSS_BOUNDARY_CONSTANTS.FORBIDDEN_IMPORT_PACKAGES) {
241
+ if (specifier === pkg || specifier.startsWith(`${pkg}/`)) {
242
+ return pkg;
243
+ }
244
+ }
245
+ return null;
246
+ }
247
+ /**
248
+ * Rules 1 and 2: scans JSON under `config/templates/`.
249
+ *
250
+ * @param repoRoot - Absolute repository root
251
+ * @returns Paid-tier and Pro-only-field violations
252
+ * @throws Error when a template file is not valid JSON
253
+ */
254
+ export function checkTemplates(repoRoot) {
255
+ const violations = [];
256
+ const files = listFiles(join(repoRoot, OSS_BOUNDARY_CONSTANTS.TEMPLATES_DIR)).filter((file) => extname(file) === OSS_BOUNDARY_CONSTANTS.JSON_EXTENSION);
257
+ for (const file of files) {
258
+ const repoPath = toRepoPath(repoRoot, file);
259
+ const json = readJson(file, repoPath);
260
+ for (const declaration of findPaidTierDeclarations(json)) {
261
+ violations.push({
262
+ rule: OSS_BOUNDARY_CONSTANTS.RULES.PAID_TIER,
263
+ path: repoPath,
264
+ detail: `paid tier declared: ${declaration}`,
265
+ });
266
+ }
267
+ for (const field of findProOnlyTemplateFields(json)) {
268
+ violations.push({
269
+ rule: OSS_BOUNDARY_CONSTANTS.RULES.PRO_TEMPLATE_FIELD,
270
+ path: repoPath,
271
+ detail: `Pro-only template field "${field}"`,
272
+ });
273
+ }
274
+ }
275
+ return violations;
276
+ }
277
+ /**
278
+ * Rule 3: scans every file path under `config/` for Pro/premium segments.
279
+ *
280
+ * @param repoRoot - Absolute repository root
281
+ * @returns Premium-path violations
282
+ */
283
+ export function checkConfigPaths(repoRoot) {
284
+ const violations = [];
285
+ for (const file of listFiles(join(repoRoot, OSS_BOUNDARY_CONSTANTS.CONFIG_DIR))) {
286
+ const repoPath = toRepoPath(repoRoot, file);
287
+ const segments = findPremiumSegments(repoPath);
288
+ if (segments.length > 0) {
289
+ violations.push({
290
+ rule: OSS_BOUNDARY_CONSTANTS.RULES.PREMIUM_PATH,
291
+ path: repoPath,
292
+ detail: `premium-looking path segment(s): ${segments.join(', ')}`,
293
+ });
294
+ }
295
+ }
296
+ return violations;
297
+ }
298
+ /**
299
+ * Lists the source roots rule 4 scans: the fixed roots plus each workspace
300
+ * package's `src` directory.
301
+ *
302
+ * @param repoRoot - Absolute repository root
303
+ * @returns Absolute directories (some may not exist; those scan as empty)
304
+ */
305
+ export function sourceRoots(repoRoot) {
306
+ const roots = OSS_BOUNDARY_CONSTANTS.SOURCE_ROOTS.map((root) => join(repoRoot, root));
307
+ const packagesDir = join(repoRoot, OSS_BOUNDARY_CONSTANTS.PACKAGES_DIR);
308
+ if (existsSync(packagesDir)) {
309
+ for (const entry of readdirSync(packagesDir, { withFileTypes: true })) {
310
+ if (entry.isDirectory()) {
311
+ roots.push(join(packagesDir, entry.name, OSS_BOUNDARY_CONSTANTS.PACKAGE_SOURCE_SUBDIR));
312
+ }
313
+ }
314
+ }
315
+ return roots;
316
+ }
317
+ /**
318
+ * Rule 4: scans OSS source for imports of the Pro package.
319
+ *
320
+ * @param repoRoot - Absolute repository root
321
+ * @returns Pro-import violations
322
+ */
323
+ export function checkSourceImports(repoRoot) {
324
+ const extensions = OSS_BOUNDARY_CONSTANTS.SOURCE_EXTENSIONS;
325
+ const violations = [];
326
+ for (const root of sourceRoots(repoRoot)) {
327
+ for (const file of listFiles(root).filter((f) => extensions.includes(extname(f)))) {
328
+ for (const specifier of extractImportSpecifiers(readFileSync(file, 'utf8'))) {
329
+ const pkg = forbiddenPackageFor(specifier);
330
+ if (pkg !== null) {
331
+ violations.push({
332
+ rule: OSS_BOUNDARY_CONSTANTS.RULES.PRO_IMPORT,
333
+ path: toRepoPath(repoRoot, file),
334
+ detail: `imports "${specifier}" (${pkg} is the paid extension; OSS must not depend on it)`,
335
+ });
336
+ }
337
+ }
338
+ }
339
+ }
340
+ return violations;
341
+ }
342
+ /**
343
+ * Validates the parsed allowlist document.
344
+ *
345
+ * @param value - Parsed allowlist JSON
346
+ * @param source - Where it came from, for error messages
347
+ * @returns The validated entries
348
+ * @throws Error when the document is not `{ "entries": [...] }` or an entry
349
+ * lacks a known rule, a path or a non-empty one-line reason
350
+ */
351
+ export function parseAllowlist(value, source) {
352
+ if (!isJsonObject(value) || !Array.isArray(value.entries)) {
353
+ throw new Error(`check-oss-boundary: ${source} must be an object with an "entries" array`);
354
+ }
355
+ return value.entries.map((entry, index) => {
356
+ const where = `${source} entries[${index}]`;
357
+ if (!isJsonObject(entry)) {
358
+ throw new Error(`check-oss-boundary: ${where} must be an object`);
359
+ }
360
+ const { rule, path, reason } = entry;
361
+ if (!isOssBoundaryRule(rule)) {
362
+ throw new Error(`check-oss-boundary: ${where} has unknown rule ${JSON.stringify(rule)}; expected one of ${RULE_VALUES.join(', ')}`);
363
+ }
364
+ if (typeof path !== 'string' || path.trim() === '') {
365
+ throw new Error(`check-oss-boundary: ${where} needs a non-empty "path"`);
366
+ }
367
+ if (typeof reason !== 'string' || reason.trim() === '' || reason.includes('\n')) {
368
+ throw new Error(`check-oss-boundary: ${where} needs a one-line, non-empty "reason"`);
369
+ }
370
+ return { rule, path, reason };
371
+ });
372
+ }
373
+ /**
374
+ * Loads the allowlist from the repository. A missing file means no
375
+ * exceptions.
376
+ *
377
+ * @param repoRoot - Absolute repository root
378
+ * @returns The validated entries
379
+ * @throws Error when the file exists but is malformed
380
+ */
381
+ export function loadAllowlist(repoRoot) {
382
+ const file = join(repoRoot, OSS_BOUNDARY_CONSTANTS.ALLOWLIST_FILE);
383
+ if (!existsSync(file)) {
384
+ return [];
385
+ }
386
+ return parseAllowlist(readJson(file, OSS_BOUNDARY_CONSTANTS.ALLOWLIST_FILE), OSS_BOUNDARY_CONSTANTS.ALLOWLIST_FILE);
387
+ }
388
+ /**
389
+ * Tells whether an allowlist entry excuses a violation: same rule, and the
390
+ * path matches exactly or sits below an entry path ending in `/`.
391
+ *
392
+ * @param entry - Allowlist entry
393
+ * @param violation - Violation to test
394
+ * @returns true when the entry covers the violation
395
+ */
396
+ export function allowlistCovers(entry, violation) {
397
+ if (entry.rule !== violation.rule) {
398
+ return false;
399
+ }
400
+ return entry.path.endsWith('/') ? violation.path.startsWith(entry.path) : entry.path === violation.path;
401
+ }
402
+ /**
403
+ * Runs all four rules against a repository and applies the allowlist.
404
+ *
405
+ * @param repoRoot - Absolute repository root
406
+ * @param allowlist - Exceptions; defaults to the repository's allowlist file
407
+ * @returns Unexcused violations, excused ones and stale allowlist entries
408
+ * @throws Error when a template or the allowlist is malformed JSON
409
+ *
410
+ * @example
411
+ * ```typescript
412
+ * const report = checkOssBoundary(process.cwd());
413
+ * if (report.violations.length > 0) process.exit(1);
414
+ * ```
415
+ */
416
+ export function checkOssBoundary(repoRoot, allowlist = loadAllowlist(repoRoot)) {
417
+ const all = [...checkTemplates(repoRoot), ...checkConfigPaths(repoRoot), ...checkSourceImports(repoRoot)];
418
+ const used = new Set();
419
+ const violations = [];
420
+ const allowed = [];
421
+ for (const violation of all) {
422
+ const entry = allowlist.find((candidate) => allowlistCovers(candidate, violation));
423
+ if (entry) {
424
+ used.add(entry);
425
+ allowed.push(violation);
426
+ }
427
+ else {
428
+ violations.push(violation);
429
+ }
430
+ }
431
+ return {
432
+ violations,
433
+ allowed,
434
+ unusedAllowlistEntries: allowlist.filter((entry) => !used.has(entry)),
435
+ };
436
+ }
437
+ /**
438
+ * Renders a report for the terminal / CI log.
439
+ *
440
+ * @param report - Result of {@link checkOssBoundary}
441
+ * @returns Multi-line text; starts with "OK" or "FAIL"
442
+ */
443
+ export function formatReport(report) {
444
+ const lines = [];
445
+ if (report.violations.length === 0) {
446
+ lines.push(`OK: OSS/Pro boundary holds (${report.allowed.length} allowlisted exception(s)).`);
447
+ }
448
+ else {
449
+ lines.push(`FAIL: ${report.violations.length} OSS/Pro boundary violation(s) — premium content belongs in crewly-pro (CLAUDE.md rule 10, #809):`);
450
+ for (const v of report.violations) {
451
+ lines.push(` [${v.rule}] ${v.path}: ${v.detail}`);
452
+ }
453
+ lines.push(`Move the content to crewly-pro, or add an entry with a one-line reason to ${OSS_BOUNDARY_CONSTANTS.ALLOWLIST_FILE}.`);
454
+ }
455
+ for (const entry of report.unusedAllowlistEntries) {
456
+ lines.push(` note: allowlist entry [${entry.rule}] ${entry.path} matched nothing — remove it once the owner confirms.`);
457
+ }
458
+ return lines.join('\n');
459
+ }
460
+ /**
461
+ * CLI entry: checks the repository and reports.
462
+ *
463
+ * @param repoRoot - Absolute repository root
464
+ * @param log - Sink for the passing report
465
+ * @param error - Sink for the failing report or a malformed-input error
466
+ * @returns Process exit code: success when no unexcused violations
467
+ */
468
+ export function runCli(repoRoot, log = (m) => console.log(m), error = (m) => console.error(m)) {
469
+ try {
470
+ const report = checkOssBoundary(repoRoot);
471
+ const text = formatReport(report);
472
+ if (report.violations.length > 0) {
473
+ error(text);
474
+ return PROCESS_EXIT_CODES.ERROR;
475
+ }
476
+ log(text);
477
+ return PROCESS_EXIT_CODES.SUCCESS;
478
+ }
479
+ catch (err) {
480
+ error(err instanceof Error ? err.message : String(err));
481
+ return PROCESS_EXIT_CODES.ERROR;
482
+ }
483
+ }
484
+ /* c8 ignore start — CLI entry, exercised by `npm run check:oss-boundary` */
485
+ const invokedDirectly = process.argv[1] !== undefined && /check-oss-boundary\.(ts|js)$/.test(process.argv[1]);
486
+ if (invokedDirectly) {
487
+ process.exitCode = runCli(process.cwd());
488
+ }
489
+ /* c8 ignore stop */
490
+ //# sourceMappingURL=check-oss-boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-oss-boundary.js","sourceRoot":"","sources":["../../../../../backend/src/scripts/check-oss-boundary.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,9 @@ export declare const STANDING_ANSWERS_HEADING = "## Standing Answers";
7
7
  *
8
8
  * Pages with no sections are skipped. The agent page comes first (what I
9
9
  * owe), then project pages. A stale page is labelled with how many newer
10
- * memories it has not absorbed. Each page body is capped at
10
+ * memories it has not absorbed, and a section whose cited entries were
11
+ * deleted or are no longer in force is marked **BASIS INVALIDATED** with
12
+ * those citations named (#914). Each page body is capped at
11
13
  * `PROMPT_PAGE_MAX_CHARS`; pages that would push the section past
12
14
  * `PROMPT_MAX_CHARS` are named in a "not shown" line instead. The result is
13
15
  * never longer than `PROMPT_MAX_CHARS`. Secrets are masked on the way out
@@ -1 +1 @@
1
- {"version":3,"file":"standing-answers.module.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/ai/prompt-modules/standing-answers.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE1E,OAAO,EACN,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,MAAM,0CAA0C,CAAC;AAIlD,gDAAgD;AAChD,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,EACvC,QAAQ,GAAE,MAAoD,GAC5D,MAAM,CAkCR;AAsBD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,qBAAsB,YAAW,YAAY;IAW7C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAVpC,IAAI,SAAsB;IAC1B,QAAQ,SAAO;IACf,SAAS,SAA8D;IACvE,WAAW,UAAQ;IAEnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC;;OAEG;gBAC0B,OAAO,GAAE,sBAAqD;IAI3F;;;;;OAKG;IACH,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO;IAI5C;;;;;OAKG;IACG,KAAK,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;CAuBlD"}
1
+ {"version":3,"file":"standing-answers.module.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/ai/prompt-modules/standing-answers.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE1E,OAAO,EACN,sBAAsB,EAEtB,KAAK,kBAAkB,EACvB,MAAM,0CAA0C,CAAC;AAIlD,gDAAgD;AAChD,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,EACvC,QAAQ,GAAE,MAAoD,GAC5D,MAAM,CAkCR;AA8BD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,qBAAsB,YAAW,YAAY;IAW7C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAVpC,IAAI,SAAsB;IAC1B,QAAQ,SAAO;IACf,SAAS,SAA8D;IACvE,WAAW,UAAQ;IAEnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC;;OAEG;gBAC0B,OAAO,GAAE,sBAAqD;IAI3F;;;;;OAKG;IACH,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO;IAI5C;;;;;OAKG;IACG,KAAK,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;CAwBlD"}
@@ -1,5 +1,5 @@
1
1
  import { STANDING_ANSWERS_CONSTANTS } from '../../../constants.js';
2
- import { StandingAnswersService, } from '../../memory/standing-answers.service.js';
2
+ import { StandingAnswersService, formatInvalidCites, } from '../../memory/standing-answers.service.js';
3
3
  import { redactSensitive } from '../../wiki/wiki-redaction.js';
4
4
  import { LoggerService } from '../../core/logger.service.js';
5
5
  /** Heading of the section this module emits. */
@@ -9,7 +9,9 @@ export const STANDING_ANSWERS_HEADING = '## Standing Answers';
9
9
  *
10
10
  * Pages with no sections are skipped. The agent page comes first (what I
11
11
  * owe), then project pages. A stale page is labelled with how many newer
12
- * memories it has not absorbed. Each page body is capped at
12
+ * memories it has not absorbed, and a section whose cited entries were
13
+ * deleted or are no longer in force is marked **BASIS INVALIDATED** with
14
+ * those citations named (#914). Each page body is capped at
13
15
  * `PROMPT_PAGE_MAX_CHARS`; pages that would push the section past
14
16
  * `PROMPT_MAX_CHARS` are named in a "not shown" line instead. The result is
15
17
  * never longer than `PROMPT_MAX_CHARS`. Secrets are masked on the way out
@@ -33,7 +35,7 @@ export function renderStandingAnswers(statuses, maxChars = STANDING_ANSWERS_CONS
33
35
  const header = [
34
36
  STANDING_ANSWERS_HEADING,
35
37
  '',
36
- 'Settled answers kept current from memory. Use them before calling recall; a page marked **STALE** has not absorbed the newest memories, so recall for anything recent.',
38
+ 'Settled answers kept current from memory. Use them before calling recall; a page marked **STALE** has not absorbed the newest memories, so recall for anything recent; a section marked **BASIS INVALIDATED** cites memories that were since retracted.',
37
39
  ].join('\n');
38
40
  const blocks = [];
39
41
  const notShown = [];
@@ -66,7 +68,15 @@ function renderPage(status) {
66
68
  const freshness = status.stale
67
69
  ? `**STALE** — ${status.newerEntries} newer memor${status.newerEntries === 1 ? 'y' : 'ies'} since this page was refreshed (${refreshed}); treat it as possibly outdated.`
68
70
  : `_${status.def.scope} · refreshed ${refreshed}_`;
69
- let body = page.sections.map((s) => `#### ${s.heading}\n${s.body}`).join('\n\n');
71
+ let body = page.sections
72
+ .map((s) => {
73
+ const hit = status.invalidatedSections.find((i) => i.heading === s.heading);
74
+ const mark = hit
75
+ ? `\n**BASIS INVALIDATED** — cited source no longer valid: ${formatInvalidCites(hit.invalidCites)}; do not rely on this section, recall instead.`
76
+ : '';
77
+ return `#### ${s.heading}${mark}\n${s.body}`;
78
+ })
79
+ .join('\n\n');
70
80
  body = redactSensitive(body);
71
81
  const cap = STANDING_ANSWERS_CONSTANTS.PROMPT_PAGE_MAX_CHARS;
72
82
  if (body.length > cap) {
@@ -130,6 +140,7 @@ export class StandingAnswersModule {
130
140
  pagesExamined: statuses.length,
131
141
  pagesWithContent: statuses.filter((s) => (s.page?.sections.length ?? 0) > 0).length,
132
142
  stale: statuses.filter((s) => s.page && s.stale).map((s) => s.def.id),
143
+ basisInvalidated: statuses.filter((s) => s.invalidatedSections.length > 0).map((s) => s.def.id),
133
144
  chars: md.length,
134
145
  });
135
146
  return md;
@@ -1 +1 @@
1
- {"version":3,"file":"standing-answers.module.js","sourceRoot":"","sources":["../../../../../../../backend/src/services/ai/prompt-modules/standing-answers.module.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"standing-answers.module.js","sourceRoot":"","sources":["../../../../../../../backend/src/services/ai/prompt-modules/standing-answers.module.ts"],"names":[],"mappings":"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"}