Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
## 2026-07-12 - Optimize renderTaskRow DOM allocations
**Learning:** Caching unattached template nodes and instantiating them via `.cloneNode(false)` reduces DOM instantiation overhead in O(N) render loops significantly.
**Action:** Apply this optimization to other hot-path rendering elements such as rows, cells, and stack containers.
## 2026-09-03 - Measure date-formatting micro-optimizations before generalizing
**Learning:** In a bounded Node/V8 microbenchmark, explicit two-digit zero-padding can be faster than `String.prototype.padStart()` for the same formatter output. That measurement does not establish browser Gantt p95, allocation/GC pressure, or a JS/native-boundary root cause.
**Action:** Preserve formatter behavior with executable UTC/local/zero-padding/invalid-date regression coverage. Apply the inline form only where representative profiling supports it, and keep buyer-visible performance claims separate from microbenchmark evidence.
19 changes: 14 additions & 5 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2684,20 +2684,29 @@ function clamp(value, min, max) {

function formatDateInput(date) {
const year = date.getUTCFullYear();
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
const day = String(date.getUTCDate()).padStart(2, '0');
const monthRaw = date.getUTCMonth() + 1;
const dayRaw = date.getUTCDate();
const month = monthRaw < 10 ? '0' + monthRaw : monthRaw;
const day = dayRaw < 10 ? '0' + dayRaw : dayRaw;
return `${year}-${month}-${day}`;
}

function formatLocalDateInput(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const monthRaw = date.getMonth() + 1;
const dayRaw = date.getDate();
const month = monthRaw < 10 ? '0' + monthRaw : monthRaw;
const day = dayRaw < 10 ? '0' + dayRaw : dayRaw;
return `${year}-${month}-${day}`;
}

function formatCompactDate(date) {
return `${date.getFullYear()}${String(date.getMonth() + 1).padStart(2, '0')}${String(date.getDate()).padStart(2, '0')}`;
const year = date.getFullYear();
const monthRaw = date.getMonth() + 1;
const dayRaw = date.getDate();
const month = monthRaw < 10 ? '0' + monthRaw : monthRaw;
const day = dayRaw < 10 ? '0' + dayRaw : dayRaw;
return `${year}${month}${day}`;
Comment thread
seonghobae marked this conversation as resolved.
}

function formatPercent(value, digits) {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
"coverage": "npm run test:coverage",
"server": "node server/server.mjs",
"test:api": "node tests/api/auth-secret.test.mjs && node tests/api/smoke.mjs && node tests/api/ratelimit.test.mjs && node tests/api/attachment-status.test.mjs && node tests/api/session-revocation.test.mjs && node tests/api/orchestrator-attribution.test.mjs",
"test:unit": "node tests/unit/opencode-config.test.mjs && node tests/unit/changelog-release-notes.test.mjs && node tests/unit/analytics.test.mjs && node tests/unit/cpm.test.mjs && node tests/unit/baseline-compare.test.mjs && node tests/unit/workload.test.mjs && node tests/unit/cost-evm.test.mjs && node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && node tests/unit/dep-types.test.mjs && node tests/unit/weekly-report.test.mjs && node tests/unit/clearfolio.test.mjs && node tests/unit/clearfolio-adapter-mock-hmac.test.mjs && node tests/unit/orchestrator.test.mjs && node tests/unit/orchestrator-coverage.test.mjs && node tests/unit/orchestrator-attribution.test.mjs && node tests/unit/sprint-stats.test.mjs && node tests/unit/burndown.test.mjs && node tests/unit/pm-analysis.test.mjs && node tests/unit/cloud-sync-security.test.mjs && node tests/unit/attachment-status.test.mjs && node tests/unit/clearfolio-status-signal.test.mjs && node tests/unit/coverage-script-contract.test.mjs && node tests/unit/toast-accessibility.test.mjs",
"test:unit": "node tests/unit/opencode-config.test.mjs && node tests/unit/changelog-release-notes.test.mjs && node tests/unit/analytics.test.mjs && node tests/unit/cpm.test.mjs && node tests/unit/baseline-compare.test.mjs && node tests/unit/workload.test.mjs && node tests/unit/cost-evm.test.mjs && node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && node tests/unit/dep-types.test.mjs && node tests/unit/weekly-report.test.mjs && node tests/unit/clearfolio.test.mjs && node tests/unit/clearfolio-adapter-mock-hmac.test.mjs && node tests/unit/orchestrator.test.mjs && node tests/unit/orchestrator-coverage.test.mjs && node tests/unit/orchestrator-attribution.test.mjs && node tests/unit/sprint-stats.test.mjs && node tests/unit/burndown.test.mjs && node tests/unit/pm-analysis.test.mjs && node tests/unit/cloud-sync-security.test.mjs && node tests/unit/attachment-status.test.mjs && node tests/unit/clearfolio-status-signal.test.mjs && node tests/unit/coverage-script-contract.test.mjs && node tests/unit/toast-accessibility.test.mjs && node tests/unit/date-formatters.test.mjs",
"test:coverage": "c8 --all --include=app.js --include=cloud-sync.js --include=scripts/ci/static_coverage_evidence.mjs --include=server/attachment_status.mjs --include=server/app.mjs --include=server/auth.mjs --include=server/clearfolio.mjs --include=server/orchestrator.mjs --reporter=json --reporter=json-summary npm run test:coverage:cases",
"test:coverage:cases": "node tests/unit/coverage-script-contract.test.mjs && node tests/unit/attachment-status.test.mjs && node tests/unit/clearfolio-status-signal.test.mjs && node tests/unit/clearfolio-adapter-mock-hmac.test.mjs && node tests/unit/orchestrator.test.mjs && node tests/unit/orchestrator-coverage.test.mjs && node tests/unit/orchestrator-attribution.test.mjs && node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && npm run test:api",
"test:coverage:cases": "node tests/unit/coverage-script-contract.test.mjs && node tests/unit/attachment-status.test.mjs && node tests/unit/clearfolio-status-signal.test.mjs && node tests/unit/clearfolio-adapter-mock-hmac.test.mjs && node tests/unit/orchestrator.test.mjs && node tests/unit/orchestrator-coverage.test.mjs && node tests/unit/orchestrator-attribution.test.mjs && node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && node tests/unit/date-formatters.test.mjs && npm run test:api",
"test:e2e": "playwright test",
"test:e2e:headed": "playwright test --headed",
"test:e2e:cloud": "playwright install chromium && playwright test tests/e2e/cloud.spec.js tests/e2e/toast-accessibility.spec.js",
Expand Down
56 changes: 56 additions & 0 deletions tests/unit/date-formatters.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import vm from 'node:vm';

const appPath = resolve('app.js');
const appSource = readFileSync(appPath, 'utf8');

function loadFunction(name) {
const marker = `function ${name}(`;
const start = appSource.indexOf(marker);
assert.notEqual(start, -1, `${name} must remain defined in app.js`);

let depth = 0;
let opened = false;
let end = -1;
for (let index = appSource.indexOf('{', start); index < appSource.length; index += 1) {
if (appSource[index] === '{') {
depth += 1;
opened = true;
} else if (appSource[index] === '}') {
depth -= 1;
if (opened && depth === 0) {
end = index + 1;
break;
}
}
}
assert.notEqual(end, -1, `${name} must have a complete function body`);

const source = appSource.slice(start, end);
const lineOffset = appSource.slice(0, start).split('\n').length - 1;
return new vm.Script(`(${source})`, {
filename: appPath,
lineOffset,
}).runInThisContext();
}

const formatDateInput = loadFunction('formatDateInput');
const formatLocalDateInput = loadFunction('formatLocalDateInput');
const formatCompactDate = loadFunction('formatCompactDate');

assert.equal(formatDateInput(new Date(Date.UTC(2026, 0, 5))), '2026-01-05');
assert.equal(formatDateInput(new Date(Date.UTC(2026, 10, 15))), '2026-11-15');

assert.equal(formatLocalDateInput(new Date(2026, 0, 5, 12, 0, 0)), '2026-01-05');
assert.equal(formatLocalDateInput(new Date(2026, 10, 15, 12, 0, 0)), '2026-11-15');
assert.equal(formatCompactDate(new Date(2026, 0, 5, 12, 0, 0)), '20260105');
assert.equal(formatCompactDate(new Date(2026, 10, 15, 12, 0, 0)), '20261115');

const invalid = new Date(Number.NaN);
assert.equal(formatDateInput(invalid), 'NaN-NaN-NaN');
assert.equal(formatLocalDateInput(invalid), 'NaN-NaN-NaN');
assert.equal(formatCompactDate(invalid), 'NaNNaNNaN');

console.log('date formatter tests passed');
Loading