infinity-harness 2.0.2 → 2.0.4
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/CHANGELOG.md +25 -0
- package/package.json +1 -1
- package/src/core/skills.ts +18 -17
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,31 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
|
|
5
5
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [2.0.4] — 2026-08-23
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **A domain skill now has to be pulled in by the task's own vocabulary.** Run against a real project
|
|
12
|
+
the matcher offered `cli-design` for *"serialise plan writes so two workers cannot race on the
|
|
13
|
+
lock"* — because the goal above it read "ship the payments rewrite behind a flag", and `flags` is
|
|
14
|
+
on that skill's tag list. One incidental word is not vocabulary. A `domain` or `meta` skill must
|
|
15
|
+
now clear the bar on tag hits alone; the phase ranks it but never qualifies it. `process` skills
|
|
16
|
+
are unchanged — belonging to the phase is the whole point of them.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## [2.0.3] — 2026-08-23
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **`npm test` failed in any project that had actually been used.** The surface guard added in 2.0.2
|
|
25
|
+
walked the filesystem for documents to check, so it also read the files the harness *writes* —
|
|
26
|
+
`harness/session-handoff.md`, `harness/.run-prompt.md` — which are git-ignored scratch carrying
|
|
27
|
+
whatever commands were current when they were generated. It now asks git what the repository
|
|
28
|
+
ships. A test that fails because you ran the tool is a test people turn off.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
7
32
|
## [2.0.2] — 2026-08-23
|
|
8
33
|
|
|
9
34
|
Everything here is one bug: the package told people to run commands it does not have. 2.0.1 fixed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "infinity-harness",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "A pi agent extension that runs a gated build pipeline unattended \u2014 enforces phases, validates with deterministic gates, and keeps working for hours or days without losing the plan.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
package/src/core/skills.ts
CHANGED
|
@@ -330,25 +330,26 @@ export function matchSkills(skills: SkillMeta[], options: MatchOptions = {}): Sk
|
|
|
330
330
|
if (hit && !hits.includes(t)) hits.push(t);
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
333
|
+
// `meta` is on every meta skill's tag list, so counting it like any other
|
|
334
|
+
// hit would surface all of them constantly. They have to be asked for.
|
|
335
|
+
const counted = skill.kind === "meta" ? hits.filter((h) => h !== "meta") : hits;
|
|
336
|
+
const tagScore = TAG_WEIGHT * Math.min(counted.length, MAX_TAG_HITS);
|
|
337
|
+
|
|
338
|
+
// A domain skill has to be pulled in by the task's own vocabulary, and one
|
|
339
|
+
// incidental word is not vocabulary. "Ship the payments rewrite behind a
|
|
340
|
+
// flag" should not summon the CLI-design skill because `flags` is on its
|
|
341
|
+
// tag list. The phase ranks a domain skill; it never qualifies one.
|
|
342
|
+
if (skill.kind !== "process" && tagScore < MIN_SCORE) continue;
|
|
343
|
+
|
|
344
|
+
score += tagScore;
|
|
345
|
+
if (counted.length) {
|
|
346
|
+
reasons.push(`matches ${counted.slice(0, MAX_TAG_HITS).map((h) => `"${h}"`).join(", ")}`);
|
|
338
347
|
}
|
|
339
348
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
// so counting it like any other hit would surface all four constantly.
|
|
345
|
-
const real = hits.filter((h) => h !== "meta");
|
|
346
|
-
if (real.length === 0) continue;
|
|
347
|
-
score += TAG_WEIGHT * Math.min(real.length, MAX_TAG_HITS);
|
|
348
|
-
}
|
|
349
|
-
if (hits.length) {
|
|
350
|
-
const shown = hits.filter((h) => h !== "meta" || skill.kind !== "meta").slice(0, MAX_TAG_HITS);
|
|
351
|
-
if (shown.length) reasons.push(`matches ${shown.map((h) => `"${h}"`).join(", ")}`);
|
|
349
|
+
const position = phase ? skill.phases.indexOf(phase) : -1;
|
|
350
|
+
if (position >= 0 && (skill.kind === "process" || counted.length > 0)) {
|
|
351
|
+
score += Math.max(1, PHASE_WEIGHT - position);
|
|
352
|
+
reasons.unshift(`${phase} phase`);
|
|
352
353
|
}
|
|
353
354
|
|
|
354
355
|
// Naming the skill in the task means it, and outranks any guess.
|