leerness 1.36.302 → 1.36.303
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 +6 -0
- package/README.md +4 -4
- package/bin/leerness.js +1 -1
- package/package.json +1 -1
- package/scripts/ci-shard-probe.js +15 -0
- package/scripts/ci-shard.js +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.36.303 - 2026-10-15
|
|
4
|
+
|
|
5
|
+
- Fixed (tests): `scripts/ci-shard.js` passed its own `LEERNESS_CI_SHARD_TIMES` to the leaves it runs, so `scripts/ci-shard-probe.js`, which runs the runner itself, overwrote the outer run's times file in the middle of a local full run (found in a full run for this release; the outer runner rewrote the file at its end, so the stored times were right). Leaves no longer see the variable, the way `e2eShard` already hides its own. CI does not set it. A new probe case fails on the 1.36.302 runner (13/14) and passes now (14/14) (T-0364).
|
|
6
|
+
- Not shipped: T-0357, removing the temp folders a test made after it ends with exit code 0, was planned for this release in a simplified form. Its four review rounds found 16 more problems in the exit-time decision and in which folders it records (6, 6, 2 and 2; the first 14 fixed, each with a test that fails on the reviewed code). By the owner's decision before the fourth round, this release ships only the change above, and T-0357 continues separately.
|
|
7
|
+
- Not changed: `contract verify` still counts exports written inside comments and strings. This was investigated and deferred on purpose in 1.36.18 (a comment masker without a parser deleted real code in review, which blocks valid contracts); T-0361 is on hold until a real parser is an option.
|
|
8
|
+
|
|
3
9
|
## 1.36.302 - 2026-10-14
|
|
4
10
|
|
|
5
11
|
- Fixed (tests): store-values-probe's two `skill publish` tests failed when a run crossed UTC midnight (T-0358; seen once in a Linux Docker node:20 run during the 1.36.299 release).
|
package/README.md
CHANGED
|
@@ -195,7 +195,7 @@ MIT
|
|
|
195
195
|
<!-- leerness:project-readme:start -->
|
|
196
196
|
## Leerness Project Harness
|
|
197
197
|
|
|
198
|
-
이 프로젝트는 Leerness v1.36.
|
|
198
|
+
이 프로젝트는 Leerness v1.36.303 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
|
|
199
199
|
|
|
200
200
|
### 정체성 — AI 에이전트 운영 레이어 (UR-0030)
|
|
201
201
|
|
|
@@ -249,7 +249,7 @@ leerness memory restore decision <date|title>
|
|
|
249
249
|
|
|
250
250
|
### MCP server (외부 AI 통합)
|
|
251
251
|
|
|
252
|
-
Leerness v1.36.
|
|
252
|
+
Leerness v1.36.303는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code · Cursor · Codex CLI 등 외부 AI에 **102개 도구**를 노출:
|
|
253
253
|
|
|
254
254
|
```jsonc
|
|
255
255
|
// 카테고리별
|
|
@@ -270,7 +270,7 @@ Leerness v1.36.302는 stdio JSON-RPC MCP server를 내장합니다 — Claude Co
|
|
|
270
270
|
`<<autonomous-loop-dynamic>>` 신호만 보내면 AI가:
|
|
271
271
|
1) 다음 라운드 후보 선정 → 2) 코드 변경 → 3) 회귀 테스트 갱신 → 4) 전체 e2e 스위트 통과 → 5) npm publish + git tag → 6) main push → 7) session close → 8) 다음 라운드 예약.
|
|
272
272
|
|
|
273
|
-
현재 사용 중인 하네스 버전: **1.36.
|
|
273
|
+
현재 사용 중인 하네스 버전: **1.36.303**. 공개 릴리스 여부는 공개 저장소의 태그와 배포 기록에서 별도로 확인합니다.
|
|
274
274
|
|
|
275
275
|
### 성능 가이드
|
|
276
276
|
|
|
@@ -308,7 +308,7 @@ leerness release pack --close --auto-main-push
|
|
|
308
308
|
- `.leerness/session-handoff.md`: 다음 세션 인수인계 (자동 작성)
|
|
309
309
|
- `.leerness/lessons.md` / `decisions.md` / `rules.md`: 영구 메모리 (5 surface)
|
|
310
310
|
|
|
311
|
-
Last synced by Leerness v1.36.
|
|
311
|
+
Last synced by Leerness v1.36.303: 2026-09-30
|
|
312
312
|
<!-- leerness:project-readme:end -->
|
|
313
313
|
GitHub 로그인 계정 확인용 서버 어댑터: [설정·연결·승인과의 구분](docs/github-login.md). 실제 앱 등록/브라우저 세션 연결과 대상별 승인은 후속입니다.
|
|
314
314
|
|
package/bin/leerness.js
CHANGED
|
@@ -115,7 +115,7 @@ const {
|
|
|
115
115
|
migrateLegacyWorkspace,
|
|
116
116
|
} = require('../lib/workspace-dir');
|
|
117
117
|
|
|
118
|
-
const VERSION = '1.36.
|
|
118
|
+
const VERSION = '1.36.303';
|
|
119
119
|
|
|
120
120
|
// MCP lifecycle 주소 표식은 현재 CLI 호출 한 번에만 유효하다. CLI bootstrap에서 즉시 env에서
|
|
121
121
|
// 떼어 두어 `--no-record`/hook처럼 presence 기록 함수에 도달하지 않는 경로도 후속 child에 유출하지 않는다.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.36.
|
|
3
|
+
"version": "1.36.303",
|
|
4
4
|
"description": "The AI-coding operations layer that makes \"done\" require evidence — persistent memory, evidence-gated completion checks, and clean handoffs for any AI agent (Claude Code, Codex, Cursor). State lives as plain files in your repo. CLI + MCP, 0 runtime dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|
|
@@ -136,6 +136,21 @@ try {
|
|
|
136
136
|
assert.deepStrictEqual(s1.results.map(r => r.key), ['node ./a.js', 'node ./d.js']);
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
+
check('runNpm keeps LEERNESS_CI_SHARD_TIMES to itself: leaves do not see it, the runner still writes its times', () => {
|
|
140
|
+
// 1.36.303: the full run's times file was overwritten mid-run by this probe's own runNpm, which inherited the
|
|
141
|
+
// variable from the outer runner through the leaf environment.
|
|
142
|
+
const dir = path.join(arena, 'times-env');
|
|
143
|
+
fs.mkdirSync(dir);
|
|
144
|
+
const seen = path.join(dir, 'seen.txt'), times = path.join(dir, 'times.json');
|
|
145
|
+
fs.writeFileSync(path.join(dir, 'e.js'), `require('fs').writeFileSync(${JSON.stringify(seen)}, Object.keys(process.env).filter(k => k.toUpperCase() === 'LEERNESS_CI_SHARD_TIMES').length ? 'set' : 'unset');\n`);
|
|
146
|
+
const env = { ...process.env, GITHUB_ACTIONS: '', LEERNESS_CI_SHARD_TIMES: times };
|
|
147
|
+
const r = cs.runNpm('suite', { index: 1, count: 1 }, { root: dir, scripts: { suite: 'node ./e.js' }, weights: { e2e: {}, npm: {} }, stdio: 'ignore', env, log: () => {} });
|
|
148
|
+
assert.deepStrictEqual(r.failed, []);
|
|
149
|
+
assert.strictEqual(fs.readFileSync(seen, 'utf8'), 'unset', 'a leaf saw the runner\'s times variable');
|
|
150
|
+
assert.deepStrictEqual(Object.keys(JSON.parse(fs.readFileSync(times, 'utf8'))), ['node ./e.js'], 'the runner did not write its own times');
|
|
151
|
+
assert.strictEqual(env.LEERNESS_CI_SHARD_TIMES, times, 'the caller\'s environment object was changed');
|
|
152
|
+
});
|
|
153
|
+
|
|
139
154
|
const CREATE = names => `const e2eShard = require('./ci-shard').e2eShard(__filename, [${names.map(n => `'${n}'`).join(', ')}]);`;
|
|
140
155
|
const START = '// e2e-shard: cases start here';
|
|
141
156
|
|
package/scripts/ci-shard.js
CHANGED
|
@@ -137,12 +137,15 @@ function runNpm(name, spec, opts = {}) {
|
|
|
137
137
|
const mine = leaves.filter(l => l.shard === spec.index);
|
|
138
138
|
const log = opts.log || (line => process.stdout.write(line + '\n'));
|
|
139
139
|
const grouped = env.GITHUB_ACTIONS === 'true';
|
|
140
|
+
// Leaves do not see this runner's times file: a leaf that runs runNpm itself (ci-shard-probe.js) would overwrite it.
|
|
141
|
+
const leafEnv = { ...env };
|
|
142
|
+
for (const k of Object.keys(leafEnv)) if (k.toUpperCase() === 'LEERNESS_CI_SHARD_TIMES') delete leafEnv[k];
|
|
140
143
|
log(`ci-shard: ${name} shard ${spec.index}/${spec.count} runs ${mine.length} of ${leaves.length} leaves`);
|
|
141
144
|
const results = [];
|
|
142
145
|
for (const leaf of mine) {
|
|
143
146
|
if (grouped) log(`::group::${leaf.key}`);
|
|
144
147
|
const started = Date.now();
|
|
145
|
-
const r = cp.spawnSync(process.execPath, [path.resolve(root, leaf.file), ...leaf.args], { cwd: root, stdio: opts.stdio || 'inherit', env });
|
|
148
|
+
const r = cp.spawnSync(process.execPath, [path.resolve(root, leaf.file), ...leaf.args], { cwd: root, stdio: opts.stdio || 'inherit', env: leafEnv });
|
|
146
149
|
const seconds = (Date.now() - started) / 1000;
|
|
147
150
|
const ok = r.status === 0 && !r.signal && !r.error;
|
|
148
151
|
results.push({ key: leaf.key, ok, seconds, status: r.status, signal: r.signal || null, error: r.error ? String(r.error.code || r.error.message) : null });
|