pi-harness-runtime 1.1.415 → 1.1.416
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/connection-runtime/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/durable-review/package.json +1 -1
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-sink/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/logging/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/permission-mode/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/relay/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/dist/sanitize.d.ts +5 -0
- package/packages/skills/dist/sanitize.d.ts.map +1 -1
- package/packages/skills/dist/sanitize.js +37 -12
- package/packages/skills/dist/sanitize.js.map +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/skills/src/sanitize.ts +37 -12
- package/packages/skills/test/sanitize.test.ts +43 -0
- package/packages/skills/test/vector-schema.test.ts +15 -2
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/telegram/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tooling-preference/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/two-phase-review/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/voice-api/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/wiki/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
- package/scripts/sync-to-qdrant.ts +18 -37
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/provider-router",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.416",
|
|
4
4
|
"description": "Enhanced Provider Router for pi-harness-runtime — intelligent routing with capabilities, costs, and quotas",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/provider-router.js",
|
|
@@ -22,6 +22,11 @@ export declare function sanitizeText(text: string): string;
|
|
|
22
22
|
*
|
|
23
23
|
* The name is the identity of the point, so it has to be the same for
|
|
24
24
|
* every writer: the map first, then the pattern rules.
|
|
25
|
+
*
|
|
26
|
+
* The result is a skill name - lower case, words separated by a dash -
|
|
27
|
+
* because the name of a point is also the id of the skill that a search
|
|
28
|
+
* returns. The replacements of the rules carry a space and brackets,
|
|
29
|
+
* which no skill name may hold.
|
|
25
30
|
*/
|
|
26
31
|
export declare function skillPointName(name: string): string;
|
|
27
32
|
//# sourceMappingURL=sanitize.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAwDH;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAInD"}
|
|
@@ -15,21 +15,25 @@
|
|
|
15
15
|
*
|
|
16
16
|
* The list is about the names of the clients and the projects of the
|
|
17
17
|
* users of the harness - not about the skills themselves.
|
|
18
|
+
*
|
|
19
|
+
* The patterns match a plain fragment, without a word boundary. A client
|
|
20
|
+
* name rarely stands alone: it appears inside a directory name
|
|
21
|
+
* (`th_digisoft_erp_chart.json`), inside a Python module (`inpac_pharma`)
|
|
22
|
+
* or in a sentence ("integrated with Paperclip"). A word boundary would
|
|
23
|
+
* miss all of them - and `_` is a word character, so a boundary never
|
|
24
|
+
* follows an underscore.
|
|
18
25
|
*/
|
|
19
26
|
const SANITIZATION_RULES = [
|
|
20
27
|
// Client company names (case-insensitive)
|
|
21
|
-
{ pattern:
|
|
22
|
-
{ pattern:
|
|
23
|
-
{ pattern:
|
|
24
|
-
{ pattern:
|
|
28
|
+
{ pattern: /inpac/gi, replacement: "[Client A]" },
|
|
29
|
+
{ pattern: /m-capital/gi, replacement: "[Client A]" },
|
|
30
|
+
{ pattern: /mcapital/gi, replacement: "[Client A]" },
|
|
31
|
+
{ pattern: /digisoft/gi, replacement: "[Client B]" },
|
|
25
32
|
// Project/app specific names
|
|
26
|
-
{ pattern:
|
|
27
|
-
{ pattern:
|
|
28
|
-
{ pattern:
|
|
29
|
-
{ pattern:
|
|
30
|
-
{ pattern: /\binpac_\b/gi, replacement: "[Client A]_" },
|
|
31
|
-
{ pattern: /\bpaperclip_\b/gi, replacement: "[Client D]_" },
|
|
32
|
-
{ pattern: /\bopenclaw_\b/gi, replacement: "[Client F]_" },
|
|
33
|
+
{ pattern: /gse-insurance/gi, replacement: "[Insurance Project]" },
|
|
34
|
+
{ pattern: /tbs-import/gi, replacement: "[Import Project]" },
|
|
35
|
+
{ pattern: /paperclip/gi, replacement: "[Client D]" },
|
|
36
|
+
{ pattern: /openclaw/gi, replacement: "[Client F]" },
|
|
33
37
|
// Generic replacements
|
|
34
38
|
{ pattern: /Company Name/gi, replacement: "[Client Name]" },
|
|
35
39
|
{ pattern: /your company/gi, replacement: "[Client]" },
|
|
@@ -68,8 +72,29 @@ export function sanitizeText(text) {
|
|
|
68
72
|
*
|
|
69
73
|
* The name is the identity of the point, so it has to be the same for
|
|
70
74
|
* every writer: the map first, then the pattern rules.
|
|
75
|
+
*
|
|
76
|
+
* The result is a skill name - lower case, words separated by a dash -
|
|
77
|
+
* because the name of a point is also the id of the skill that a search
|
|
78
|
+
* returns. The replacements of the rules carry a space and brackets,
|
|
79
|
+
* which no skill name may hold.
|
|
71
80
|
*/
|
|
72
81
|
export function skillPointName(name) {
|
|
73
|
-
|
|
82
|
+
const mapped = SKILL_NAME_MAP[name];
|
|
83
|
+
if (mapped)
|
|
84
|
+
return mapped;
|
|
85
|
+
return kebabName(sanitizeText(name));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Bring a name into the shape of a skill name.
|
|
89
|
+
*
|
|
90
|
+
* The name of a skill is lower case and its words are separated by a
|
|
91
|
+
* dash: `^[a-z0-9]+(-[a-z0-9]+)*$`.
|
|
92
|
+
*/
|
|
93
|
+
function kebabName(name) {
|
|
94
|
+
return name
|
|
95
|
+
.toLowerCase()
|
|
96
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
97
|
+
.replace(/-{2,}/g, "-")
|
|
98
|
+
.replace(/^-+|-+$/g, "");
|
|
74
99
|
}
|
|
75
100
|
//# sourceMappingURL=sanitize.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH;;;;;;;;;;;;GAYG;AACH,MAAM,kBAAkB,GAAuB;IAC7C,0CAA0C;IAC1C,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE;IACjD,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE;IACrD,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE;IACpD,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE;IAEpD,6BAA6B;IAC7B,EAAE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,qBAAqB,EAAE;IAClE,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,kBAAkB,EAAE;IAC5D,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE;IACrD,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE;IAEpD,uBAAuB;IACvB,EAAE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,eAAe,EAAE;IAC3D,EAAE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE;IACtD,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE;IACpD,EAAE,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,oBAAoB,EAAE;CACpE,CAAC;AAEF;;;;;GAKG;AACH,MAAM,cAAc,GAA2B;IAC9C,iCAAiC,EAAE,+BAA+B;IAClE,4BAA4B,EAAE,+BAA+B;IAC7D,4BAA4B,EAAE,+BAA+B;IAC7D,4BAA4B,EAAE,+BAA+B;IAC7D,0BAA0B,EAAE,0BAA0B;IACtD,WAAW,EAAE,cAAc;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACxC,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE,CAAC;QACvC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,OAAO,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,SAAS,SAAS,CAAC,IAAY;IAC9B,OAAO,IAAI;SACT,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -22,22 +22,26 @@ interface SanitizationRule {
|
|
|
22
22
|
*
|
|
23
23
|
* The list is about the names of the clients and the projects of the
|
|
24
24
|
* users of the harness - not about the skills themselves.
|
|
25
|
+
*
|
|
26
|
+
* The patterns match a plain fragment, without a word boundary. A client
|
|
27
|
+
* name rarely stands alone: it appears inside a directory name
|
|
28
|
+
* (`th_digisoft_erp_chart.json`), inside a Python module (`inpac_pharma`)
|
|
29
|
+
* or in a sentence ("integrated with Paperclip"). A word boundary would
|
|
30
|
+
* miss all of them - and `_` is a word character, so a boundary never
|
|
31
|
+
* follows an underscore.
|
|
25
32
|
*/
|
|
26
33
|
const SANITIZATION_RULES: SanitizationRule[] = [
|
|
27
34
|
// Client company names (case-insensitive)
|
|
28
|
-
{ pattern:
|
|
29
|
-
{ pattern:
|
|
30
|
-
{ pattern:
|
|
31
|
-
{ pattern:
|
|
35
|
+
{ pattern: /inpac/gi, replacement: "[Client A]" },
|
|
36
|
+
{ pattern: /m-capital/gi, replacement: "[Client A]" },
|
|
37
|
+
{ pattern: /mcapital/gi, replacement: "[Client A]" },
|
|
38
|
+
{ pattern: /digisoft/gi, replacement: "[Client B]" },
|
|
32
39
|
|
|
33
40
|
// Project/app specific names
|
|
34
|
-
{ pattern:
|
|
35
|
-
{ pattern:
|
|
36
|
-
{ pattern:
|
|
37
|
-
{ pattern:
|
|
38
|
-
{ pattern: /\binpac_\b/gi, replacement: "[Client A]_" },
|
|
39
|
-
{ pattern: /\bpaperclip_\b/gi, replacement: "[Client D]_" },
|
|
40
|
-
{ pattern: /\bopenclaw_\b/gi, replacement: "[Client F]_" },
|
|
41
|
+
{ pattern: /gse-insurance/gi, replacement: "[Insurance Project]" },
|
|
42
|
+
{ pattern: /tbs-import/gi, replacement: "[Import Project]" },
|
|
43
|
+
{ pattern: /paperclip/gi, replacement: "[Client D]" },
|
|
44
|
+
{ pattern: /openclaw/gi, replacement: "[Client F]" },
|
|
41
45
|
|
|
42
46
|
// Generic replacements
|
|
43
47
|
{ pattern: /Company Name/gi, replacement: "[Client Name]" },
|
|
@@ -80,7 +84,28 @@ export function sanitizeText(text: string): string {
|
|
|
80
84
|
*
|
|
81
85
|
* The name is the identity of the point, so it has to be the same for
|
|
82
86
|
* every writer: the map first, then the pattern rules.
|
|
87
|
+
*
|
|
88
|
+
* The result is a skill name - lower case, words separated by a dash -
|
|
89
|
+
* because the name of a point is also the id of the skill that a search
|
|
90
|
+
* returns. The replacements of the rules carry a space and brackets,
|
|
91
|
+
* which no skill name may hold.
|
|
83
92
|
*/
|
|
84
93
|
export function skillPointName(name: string): string {
|
|
85
|
-
|
|
94
|
+
const mapped = SKILL_NAME_MAP[name];
|
|
95
|
+
if (mapped) return mapped;
|
|
96
|
+
return kebabName(sanitizeText(name));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Bring a name into the shape of a skill name.
|
|
101
|
+
*
|
|
102
|
+
* The name of a skill is lower case and its words are separated by a
|
|
103
|
+
* dash: `^[a-z0-9]+(-[a-z0-9]+)*$`.
|
|
104
|
+
*/
|
|
105
|
+
function kebabName(name: string): string {
|
|
106
|
+
return name
|
|
107
|
+
.toLowerCase()
|
|
108
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
109
|
+
.replace(/-{2,}/g, "-")
|
|
110
|
+
.replace(/^-+|-+$/g, "");
|
|
86
111
|
}
|
|
@@ -32,6 +32,26 @@ describe("the sanitization of a text", () => {
|
|
|
32
32
|
expect(sanitizeText("your company")).toBe("[Client]");
|
|
33
33
|
expect(sanitizeText("our client")).toBe("[Client]");
|
|
34
34
|
});
|
|
35
|
+
|
|
36
|
+
test("a client name inside an identifier is replaced", () => {
|
|
37
|
+
// The name of a client rarely stands alone. A word boundary would
|
|
38
|
+
// miss every one of these - and an underscore is a word character,
|
|
39
|
+
// so a boundary never follows one.
|
|
40
|
+
expect(sanitizeText("inpac_pharma")).toBe("[Client A]_pharma");
|
|
41
|
+
expect(sanitizeText("th_digisoft_erp_chart.json")).toBe(
|
|
42
|
+
"th_[Client B]_erp_chart.json",
|
|
43
|
+
);
|
|
44
|
+
expect(sanitizeText("apps/inpac_pharma/setup")).toBe(
|
|
45
|
+
"apps/[Client A]_pharma/setup",
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("a client name in a sentence is replaced", () => {
|
|
50
|
+
expect(sanitizeText("integrated with Paperclip")).toBe(
|
|
51
|
+
"integrated with [Client D]",
|
|
52
|
+
);
|
|
53
|
+
expect(sanitizeText("OpenClaw secrets")).toBe("[Client F] secrets");
|
|
54
|
+
});
|
|
35
55
|
});
|
|
36
56
|
|
|
37
57
|
describe("the name of a skill in the shared collection", () => {
|
|
@@ -59,6 +79,29 @@ describe("the name of a skill in the shared collection", () => {
|
|
|
59
79
|
expect(skillPointName(name)).not.toMatch(/inpac|gse-insurance|tbs-import/i);
|
|
60
80
|
}
|
|
61
81
|
});
|
|
82
|
+
|
|
83
|
+
test("the name is a valid skill name", () => {
|
|
84
|
+
// The name of a point is the id of the skill that a search returns,
|
|
85
|
+
// so it has to be a name that a skill may carry.
|
|
86
|
+
const NAME = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
87
|
+
for (const name of [
|
|
88
|
+
"inpac-pe-approval-workflow",
|
|
89
|
+
"openclaw-channel",
|
|
90
|
+
"gse-insurance-step5-slot-filter",
|
|
91
|
+
"tbs-import-clearance-lcv",
|
|
92
|
+
"whispertool",
|
|
93
|
+
"code-review",
|
|
94
|
+
]) {
|
|
95
|
+
expect(skillPointName(name)).toMatch(NAME);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("a name that needs no sanitization stays the same", () => {
|
|
100
|
+
expect(skillPointName("code-review")).toBe("code-review");
|
|
101
|
+
expect(skillPointName("frappe-doctype-field-order")).toBe(
|
|
102
|
+
"frappe-doctype-field-order",
|
|
103
|
+
);
|
|
104
|
+
});
|
|
62
105
|
});
|
|
63
106
|
|
|
64
107
|
describe("the payload of a point is sanitized", () => {
|
|
@@ -138,8 +138,21 @@ describe("the identity of a skill point", () => {
|
|
|
138
138
|
body: "b",
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
// The title is treated like the name: it is sanitized and it is
|
|
142
|
+
// brought into the shape of a skill name.
|
|
143
|
+
expect(withTitle.text).toContain("a-human-title");
|
|
144
|
+
expect(withoutTitle.text).not.toContain("a-human-title");
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("a title that is the name is not repeated in the text", () => {
|
|
148
|
+
const payload = skillPointPayload({
|
|
149
|
+
name: "a-skill",
|
|
150
|
+
title: "a-skill",
|
|
151
|
+
description: "d",
|
|
152
|
+
body: "b",
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
expect(payload.text.match(/a-skill/g)?.length).toBe(1);
|
|
143
156
|
});
|
|
144
157
|
});
|
|
145
158
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/two-phase-review",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.416",
|
|
4
4
|
"description": "pi-harness-runtime — two-phase implementation and review workflow (queue review signals, gate the phase, scope the diff)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|