@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.
- package/native-skills/media/professional-document-publishing/SKILL.md +44 -0
- package/native-skills/media/screenplay-and-shotlist-forge/SKILL.md +42 -0
- package/package.json +1 -1
- package/src/acp/client.js +235 -0
- package/src/acp/client.ts +282 -0
- package/src/acp/peerProfiles.js +122 -0
- package/src/acp/peerProfiles.ts +128 -0
- package/src/acp/protocol.js +54 -0
- package/src/acp/protocol.ts +434 -0
- package/src/acp/server.js +609 -0
- package/src/acp/server.ts +676 -0
- package/src/agentLoop.d.ts +43 -0
- package/src/agentLoop.js +142 -8
- package/src/commands.js +203 -0
- package/src/compiledSkills.js +10 -0
- package/src/documentEngine/antiSlopAuditor.js +156 -0
- package/src/documentEngine/antiSlopAuditor.ts +221 -0
- package/src/documentEngine/documentForge.js +443 -0
- package/src/documentEngine/documentForge.ts +519 -0
- package/src/documentEngine/screenplayFormatter.js +336 -0
- package/src/documentEngine/screenplayFormatter.ts +407 -0
- package/src/entrypoint.js +13 -0
- package/src/execSafe.js +10 -13
- package/src/execSafe.ts +25 -0
- package/src/modelRouter.js +56 -123
- package/src/modelRouter.ts +134 -0
- package/src/observer/advisory.js +164 -0
- package/src/observer/advisory.ts +171 -0
- package/src/observer/coldObserver.js +462 -0
- package/src/observer/coldObserver.ts +540 -0
- package/src/observer/evidence.js +435 -0
- package/src/observer/evidence.ts +499 -0
- package/src/perception.js +303 -118
- package/src/perception.ts +387 -0
- package/src/procSignal.js +15 -16
- package/src/procSignal.ts +31 -0
- package/src/promptMentions.js +170 -0
- package/src/promptMentions.ts +212 -0
- package/src/sandbox.js +1 -1
- package/src/textDiff.js +117 -109
- package/src/textDiff.ts +169 -0
- package/src/toolPacks.js +5 -2
- package/src/tools/documentForge.js +215 -0
- package/src/tools/documentForge.ts +265 -0
- package/src/tools/peerAgent.js +102 -0
- package/src/tools/peerAgent.ts +116 -0
- package/src/tools/registry.js +3 -1
- package/src/tui/completion.js +97 -41
- package/src/tui/prompt.js +17 -17
- package/src/uncertainty.js +93 -205
- package/src/uncertainty.ts +255 -0
- package/src/utils/paths.js +15 -18
- package/src/utils/paths.ts +36 -0
- package/src/vfeTracker.js +122 -181
- 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
|
+
}
|