@causyne/agent 1.10.21 → 1.11.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 (55) hide show
  1. package/native-skills/media/professional-document-publishing/SKILL.md +44 -0
  2. package/native-skills/media/screenplay-and-shotlist-forge/SKILL.md +42 -0
  3. package/package.json +1 -1
  4. package/src/acp/client.js +235 -0
  5. package/src/acp/client.ts +282 -0
  6. package/src/acp/peerProfiles.js +122 -0
  7. package/src/acp/peerProfiles.ts +128 -0
  8. package/src/acp/protocol.js +54 -0
  9. package/src/acp/protocol.ts +434 -0
  10. package/src/acp/server.js +609 -0
  11. package/src/acp/server.ts +676 -0
  12. package/src/agentLoop.d.ts +43 -0
  13. package/src/agentLoop.js +142 -8
  14. package/src/commands.js +203 -0
  15. package/src/compiledSkills.js +10 -0
  16. package/src/documentEngine/antiSlopAuditor.js +156 -0
  17. package/src/documentEngine/antiSlopAuditor.ts +221 -0
  18. package/src/documentEngine/documentForge.js +443 -0
  19. package/src/documentEngine/documentForge.ts +519 -0
  20. package/src/documentEngine/screenplayFormatter.js +336 -0
  21. package/src/documentEngine/screenplayFormatter.ts +407 -0
  22. package/src/entrypoint.js +13 -0
  23. package/src/execSafe.js +10 -13
  24. package/src/execSafe.ts +25 -0
  25. package/src/modelRouter.js +56 -123
  26. package/src/modelRouter.ts +134 -0
  27. package/src/observer/advisory.js +164 -0
  28. package/src/observer/advisory.ts +171 -0
  29. package/src/observer/coldObserver.js +462 -0
  30. package/src/observer/coldObserver.ts +540 -0
  31. package/src/observer/evidence.js +435 -0
  32. package/src/observer/evidence.ts +499 -0
  33. package/src/perception.js +303 -118
  34. package/src/perception.ts +387 -0
  35. package/src/procSignal.js +15 -16
  36. package/src/procSignal.ts +31 -0
  37. package/src/promptMentions.js +170 -0
  38. package/src/promptMentions.ts +212 -0
  39. package/src/sandbox.js +1 -1
  40. package/src/textDiff.js +117 -109
  41. package/src/textDiff.ts +169 -0
  42. package/src/toolPacks.js +5 -2
  43. package/src/tools/documentForge.js +215 -0
  44. package/src/tools/documentForge.ts +265 -0
  45. package/src/tools/peerAgent.js +102 -0
  46. package/src/tools/peerAgent.ts +116 -0
  47. package/src/tools/registry.js +3 -1
  48. package/src/tui/completion.js +97 -41
  49. package/src/tui/prompt.js +17 -17
  50. package/src/uncertainty.js +93 -205
  51. package/src/uncertainty.ts +255 -0
  52. package/src/utils/paths.js +15 -18
  53. package/src/utils/paths.ts +36 -0
  54. package/src/vfeTracker.js +122 -181
  55. package/src/vfeTracker.ts +242 -0
@@ -0,0 +1,156 @@
1
+ /*
2
+ * Copyright (c) 2026 Causyne.
3
+ * SPDX-License-Identifier: BUSL-1.1
4
+ *
5
+ * Anti-AI Slop & Humanization Compliance Auditor.
6
+ * Enforces authentic human cadence, strict hyphenation rules, and zero ungrounded placeholders.
7
+ */
8
+ const BANNED_LONG_DASHES = /[—–]/g;
9
+ const AI_SLOP_CLICHES_ID = [
10
+ /\bsangatlah\b/i,
11
+ /\btak terbantahkan\b/i,
12
+ /\brevolusioner\b/i,
13
+ /\bgame[- ]?changer\b/i,
14
+ /\bdi era yang serba\b/i,
15
+ /\bmari kita\b/i,
16
+ /\btidak dapat dipungkiri\b/i,
17
+ /\bperlu diingat bahwa\b/i,
18
+ /\bdalam lanskap modern\b/i,
19
+ /\bmerupakan sebuah bukti nyata\b/i
20
+ ];
21
+ const AI_SLOP_CLICHES_EN = [
22
+ /\bdelve(?:s|d|ing)?\b/i,
23
+ /\bcrucial(?:ly)?\b/i,
24
+ /\btestament\b/i,
25
+ /\btapestry\b/i,
26
+ /\bgame[- ]?changer\b/i,
27
+ /\brevolutionize(?:d|s|ing)?\b/i,
28
+ /\bin conclusion\b/i,
29
+ /\bit is important to remember\b/i,
30
+ /\bbeacon\b/i,
31
+ /\bfoster(?:s|ing)?\b/i,
32
+ /\bunderscore(?:s|d|ing)?\b/i,
33
+ /\bspearhead(?:ed|ing)?\b/i,
34
+ /\brealm\b/i,
35
+ /\bparamount\b/i,
36
+ /\bholistic approach\b/i
37
+ ];
38
+ const PLACEHOLDER_BRACKETS = [
39
+ /\[(?:insert|masukkan|isi|tbd|todo|placeholder|nama|tanggal|lokasi)[^\]]*\]/i,
40
+ /<(?:insert|masukkan|isi|tbd|todo|placeholder)[^>]*>/i
41
+ ];
42
+ /**
43
+ * Scan raw text or HTML content for AI slop, long em-dashes, and placeholder tokens.
44
+ */
45
+ export function auditTextContent(content, options = {}) {
46
+ const findings = [];
47
+ const lines = (content || '').split(/\r?\n/);
48
+ const lang = options.language || 'both';
49
+ const strictDashes = options.strictDashes !== false;
50
+ lines.forEach((line, idx) => {
51
+ const lineNum = idx + 1;
52
+ // 1. Long em-dash check (enforce short hyphen -)
53
+ if (strictDashes) {
54
+ const dashMatches = line.match(BANNED_LONG_DASHES);
55
+ if (dashMatches) {
56
+ findings.push({
57
+ rule: 'no_long_em_dash',
58
+ severity: 'error',
59
+ match: dashMatches[0] || '—',
60
+ line: lineNum,
61
+ message: 'Found long em-dash (—/–). Use standard short hyphen (-) to preserve natural human typing rhythm.'
62
+ });
63
+ }
64
+ }
65
+ // 2. Placeholder checks
66
+ for (const pat of PLACEHOLDER_BRACKETS) {
67
+ const m = line.match(pat);
68
+ if (m) {
69
+ findings.push({
70
+ rule: 'no_ungrounded_placeholders',
71
+ severity: 'error',
72
+ match: m[0],
73
+ line: lineNum,
74
+ message: `Found ungrounded template placeholder "${m[0]}". Must be replaced with verified real data.`
75
+ });
76
+ }
77
+ }
78
+ // 3. AI Slop Cliches (ID)
79
+ if (lang === 'id' || lang === 'both') {
80
+ for (const pat of AI_SLOP_CLICHES_ID) {
81
+ const m = line.match(pat);
82
+ if (m) {
83
+ findings.push({
84
+ rule: 'anti_ai_slop_phrase_id',
85
+ severity: 'warning',
86
+ match: m[0],
87
+ line: lineNum,
88
+ message: `Found formulaic AI phrase "${m[0]}". Rewrite in authentic, direct human voice.`
89
+ });
90
+ }
91
+ }
92
+ }
93
+ // 4. AI Slop Cliches (EN)
94
+ if (lang === 'en' || lang === 'both') {
95
+ for (const pat of AI_SLOP_CLICHES_EN) {
96
+ const m = line.match(pat);
97
+ if (m) {
98
+ findings.push({
99
+ rule: 'anti_ai_slop_phrase_en',
100
+ severity: 'warning',
101
+ match: m[0],
102
+ line: lineNum,
103
+ message: `Found generic AI trope "${m[0]}". Replace with concrete, factual language.`
104
+ });
105
+ }
106
+ }
107
+ }
108
+ });
109
+ return {
110
+ clean: findings.filter((f) => f.severity === 'error').length === 0,
111
+ findings
112
+ };
113
+ }
114
+ /**
115
+ * Audit arithmetic integrity across line items, category subtotals, and gross-up taxes.
116
+ */
117
+ export function auditBudgetArithmetic(spec) {
118
+ const itemErrors = [];
119
+ const categoryErrors = [];
120
+ let grandTotal = 0;
121
+ for (const cat of spec.categories) {
122
+ let catComputedSubtotal = 0;
123
+ for (const item of cat.items) {
124
+ const expectedItemTotal = item.volume * item.frequency * item.unitPrice;
125
+ if (Math.round(expectedItemTotal) !== Math.round(item.total)) {
126
+ itemErrors.push(`Item "${item.name}" math mismatch: ${item.volume} * ${item.frequency} * ${item.unitPrice} = ${expectedItemTotal}, but recorded total is ${item.total}`);
127
+ }
128
+ catComputedSubtotal += item.total;
129
+ }
130
+ if (cat.subtotal !== undefined && Math.round(cat.subtotal) !== Math.round(catComputedSubtotal)) {
131
+ categoryErrors.push(`Category "${cat.name}" subtotal mismatch: items sum to ${catComputedSubtotal}, but recorded subtotal is ${cat.subtotal}`);
132
+ }
133
+ grandTotal += catComputedSubtotal;
134
+ }
135
+ let grossCalculated;
136
+ let taxCalculated;
137
+ let differenceFromTarget;
138
+ if (spec.grossUpTaxRate !== undefined) {
139
+ const divisor = 1 - spec.grossUpTaxRate;
140
+ grossCalculated = Math.round(grandTotal / divisor);
141
+ taxCalculated = grossCalculated - grandTotal;
142
+ if (spec.targetGross !== undefined) {
143
+ differenceFromTarget = grossCalculated - spec.targetGross;
144
+ }
145
+ }
146
+ const valid = itemErrors.length === 0 && categoryErrors.length === 0 && (differenceFromTarget === undefined || differenceFromTarget === 0);
147
+ return {
148
+ valid,
149
+ itemErrors,
150
+ categoryErrors,
151
+ totalCalculated: grandTotal,
152
+ grossCalculated,
153
+ taxCalculated,
154
+ differenceFromTarget
155
+ };
156
+ }
@@ -0,0 +1,221 @@
1
+ /*
2
+ * Copyright (c) 2026 Causyne.
3
+ * SPDX-License-Identifier: BUSL-1.1
4
+ *
5
+ * Anti-AI Slop & Humanization Compliance Auditor.
6
+ * Enforces authentic human cadence, strict hyphenation rules, and zero ungrounded placeholders.
7
+ */
8
+
9
+ export interface SlopAuditFinding {
10
+ rule: string;
11
+ severity: 'error' | 'warning';
12
+ match: string;
13
+ line?: number;
14
+ message: string;
15
+ }
16
+
17
+ export interface ArithmeticItem {
18
+ name: string;
19
+ volume: number;
20
+ frequency: number;
21
+ unitPrice: number;
22
+ total: number;
23
+ }
24
+
25
+ export interface ArithmeticCategory {
26
+ code: string;
27
+ name: string;
28
+ items: ArithmeticItem[];
29
+ subtotal?: number;
30
+ }
31
+
32
+ export interface ArithmeticBudgetSpec {
33
+ categories: ArithmeticCategory[];
34
+ grossUpTaxRate?: number; // e.g. 0.025 for 2.5% PPh 21
35
+ targetGross?: number;
36
+ }
37
+
38
+ const BANNED_LONG_DASHES = /[—–]/g;
39
+
40
+ const AI_SLOP_CLICHES_ID = [
41
+ /\bsangatlah\b/i,
42
+ /\btak terbantahkan\b/i,
43
+ /\brevolusioner\b/i,
44
+ /\bgame[- ]?changer\b/i,
45
+ /\bdi era yang serba\b/i,
46
+ /\bmari kita\b/i,
47
+ /\btidak dapat dipungkiri\b/i,
48
+ /\bperlu diingat bahwa\b/i,
49
+ /\bdalam lanskap modern\b/i,
50
+ /\bmerupakan sebuah bukti nyata\b/i
51
+ ];
52
+
53
+ const AI_SLOP_CLICHES_EN = [
54
+ /\bdelve(?:s|d|ing)?\b/i,
55
+ /\bcrucial(?:ly)?\b/i,
56
+ /\btestament\b/i,
57
+ /\btapestry\b/i,
58
+ /\bgame[- ]?changer\b/i,
59
+ /\brevolutionize(?:d|s|ing)?\b/i,
60
+ /\bin conclusion\b/i,
61
+ /\bit is important to remember\b/i,
62
+ /\bbeacon\b/i,
63
+ /\bfoster(?:s|ing)?\b/i,
64
+ /\bunderscore(?:s|d|ing)?\b/i,
65
+ /\bspearhead(?:ed|ing)?\b/i,
66
+ /\brealm\b/i,
67
+ /\bparamount\b/i,
68
+ /\bholistic approach\b/i
69
+ ];
70
+
71
+ const PLACEHOLDER_BRACKETS = [
72
+ /\[(?:insert|masukkan|isi|tbd|todo|placeholder|nama|tanggal|lokasi)[^\]]*\]/i,
73
+ /<(?:insert|masukkan|isi|tbd|todo|placeholder)[^>]*>/i
74
+ ];
75
+
76
+ /**
77
+ * Scan raw text or HTML content for AI slop, long em-dashes, and placeholder tokens.
78
+ */
79
+ export function auditTextContent(content: string, options: { language?: 'id' | 'en' | 'both'; strictDashes?: boolean } = {}): {
80
+ clean: boolean;
81
+ findings: SlopAuditFinding[];
82
+ } {
83
+ const findings: SlopAuditFinding[] = [];
84
+ const lines = (content || '').split(/\r?\n/);
85
+ const lang = options.language || 'both';
86
+ const strictDashes = options.strictDashes !== false;
87
+
88
+ lines.forEach((line, idx) => {
89
+ const lineNum = idx + 1;
90
+
91
+ // 1. Long em-dash check (enforce short hyphen -)
92
+ if (strictDashes) {
93
+ const dashMatches = line.match(BANNED_LONG_DASHES);
94
+ if (dashMatches) {
95
+ findings.push({
96
+ rule: 'no_long_em_dash',
97
+ severity: 'error',
98
+ match: dashMatches[0] || '—',
99
+ line: lineNum,
100
+ message: 'Found long em-dash (—/–). Use standard short hyphen (-) to preserve natural human typing rhythm.'
101
+ });
102
+ }
103
+ }
104
+
105
+ // 2. Placeholder checks
106
+ for (const pat of PLACEHOLDER_BRACKETS) {
107
+ const m = line.match(pat);
108
+ if (m) {
109
+ findings.push({
110
+ rule: 'no_ungrounded_placeholders',
111
+ severity: 'error',
112
+ match: m[0],
113
+ line: lineNum,
114
+ message: `Found ungrounded template placeholder "${m[0]}". Must be replaced with verified real data.`
115
+ });
116
+ }
117
+ }
118
+
119
+ // 3. AI Slop Cliches (ID)
120
+ if (lang === 'id' || lang === 'both') {
121
+ for (const pat of AI_SLOP_CLICHES_ID) {
122
+ const m = line.match(pat);
123
+ if (m) {
124
+ findings.push({
125
+ rule: 'anti_ai_slop_phrase_id',
126
+ severity: 'warning',
127
+ match: m[0],
128
+ line: lineNum,
129
+ message: `Found formulaic AI phrase "${m[0]}". Rewrite in authentic, direct human voice.`
130
+ });
131
+ }
132
+ }
133
+ }
134
+
135
+ // 4. AI Slop Cliches (EN)
136
+ if (lang === 'en' || lang === 'both') {
137
+ for (const pat of AI_SLOP_CLICHES_EN) {
138
+ const m = line.match(pat);
139
+ if (m) {
140
+ findings.push({
141
+ rule: 'anti_ai_slop_phrase_en',
142
+ severity: 'warning',
143
+ match: m[0],
144
+ line: lineNum,
145
+ message: `Found generic AI trope "${m[0]}". Replace with concrete, factual language.`
146
+ });
147
+ }
148
+ }
149
+ }
150
+ });
151
+
152
+ return {
153
+ clean: findings.filter((f) => f.severity === 'error').length === 0,
154
+ findings
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Audit arithmetic integrity across line items, category subtotals, and gross-up taxes.
160
+ */
161
+ export function auditBudgetArithmetic(spec: ArithmeticBudgetSpec): {
162
+ valid: boolean;
163
+ itemErrors: string[];
164
+ categoryErrors: string[];
165
+ totalCalculated: number;
166
+ grossCalculated?: number | undefined;
167
+ taxCalculated?: number | undefined;
168
+ differenceFromTarget?: number | undefined;
169
+ } {
170
+ const itemErrors: string[] = [];
171
+ const categoryErrors: string[] = [];
172
+ let grandTotal = 0;
173
+
174
+ for (const cat of spec.categories) {
175
+ let catComputedSubtotal = 0;
176
+
177
+ for (const item of cat.items) {
178
+ const expectedItemTotal = item.volume * item.frequency * item.unitPrice;
179
+ if (Math.round(expectedItemTotal) !== Math.round(item.total)) {
180
+ itemErrors.push(
181
+ `Item "${item.name}" math mismatch: ${item.volume} * ${item.frequency} * ${item.unitPrice} = ${expectedItemTotal}, but recorded total is ${item.total}`
182
+ );
183
+ }
184
+ catComputedSubtotal += item.total;
185
+ }
186
+
187
+ if (cat.subtotal !== undefined && Math.round(cat.subtotal) !== Math.round(catComputedSubtotal)) {
188
+ categoryErrors.push(
189
+ `Category "${cat.name}" subtotal mismatch: items sum to ${catComputedSubtotal}, but recorded subtotal is ${cat.subtotal}`
190
+ );
191
+ }
192
+
193
+ grandTotal += catComputedSubtotal;
194
+ }
195
+
196
+ let grossCalculated: number | undefined;
197
+ let taxCalculated: number | undefined;
198
+ let differenceFromTarget: number | undefined;
199
+
200
+ if (spec.grossUpTaxRate !== undefined) {
201
+ const divisor = 1 - spec.grossUpTaxRate;
202
+ grossCalculated = Math.round(grandTotal / divisor);
203
+ taxCalculated = grossCalculated - grandTotal;
204
+
205
+ if (spec.targetGross !== undefined) {
206
+ differenceFromTarget = grossCalculated - spec.targetGross;
207
+ }
208
+ }
209
+
210
+ const valid = itemErrors.length === 0 && categoryErrors.length === 0 && (differenceFromTarget === undefined || differenceFromTarget === 0);
211
+
212
+ return {
213
+ valid,
214
+ itemErrors,
215
+ categoryErrors,
216
+ totalCalculated: grandTotal,
217
+ grossCalculated,
218
+ taxCalculated,
219
+ differenceFromTarget
220
+ };
221
+ }