fix(youtrack): drop greeting, mention and timezone config; fix work-item date - #151
Merged
Merged
Conversation
…tem date YouTrack stays an optional tracker adapter, but core no longer builds a hard-coded Spanish greeting or @mentions a named person, and the wizard no longer asks every user for a timezone that nothing read. - youtrack: remove youTrackGreeting and its port; context() no longer emits or depends on a greeting, so a greeting problem cannot block reading an issue. - youtrack: compute work-item dates with Date.UTC. Date.parse of a local "T00:00:00" shifted the day back when the process ran east of UTC. The day comes from the process timezone, or from an optional youtrack.json `timezone`; there is no hard-coded default zone. Invalid YYYY-MM-DD input now errors instead of producing NaN. - config/wizard/setup/conversion: remove the global `timezone` field and the timezone wizard step; old config.json files that still carry it load and the key is ignored. - init/scaffold/OpenCode init_apply: neutral youtrack.json drafts (no organization URL, issue IDs, mention, greetings or timezone); drop the default_mention/timezone arguments and the WORKFLOW_YT_MENTION and WORKFLOW_YT_TIMEZONE overrides. - issue-update template: neutral "# Update" header and "Project: X" line; wording stays editable via the config templates directory. - docs: README/AGENTS/workit-cli README; replace dev-machine paths in docs/adaptive-workit/plan.md with placeholders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…draft test - Add a Given/When/Then scan over packages/ that fails if a hard-coded greeting, @mention key or default timezone comes back. - Run the buildDraft test in a temporary config dir so a user's own templates/issue-update.md override cannot leak into the assertion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…timezone Review follow-ups for #151. - No organization defaults: the token-create link has no fallback host (createUrl null plus an error naming youtrack.json when baseUrl is missing); the meetings normalizer no longer falls back to a built-in issue and asks for meetingIssue instead; meeting work-item text comes from the entry's workItemText, then youtrack.json meetingWorkItemText, then the neutral "Meetings". Existing configs that set them keep working. - Greeting leftovers: delete the greeting template (core + cli assets), drop "greeting" from TemplateName and the greeting param / {{greetingSection}} from buildDraft and the bundled template. Unknown placeholders in user templates now render empty. - Numeric dateMs: localDate is the UTC calendar day of the epoch, so it round-trips with the YYYY-MM-DD path. - Effective timezone is visible: youTrackWorkDateMs returns timezoneSource, context() returns workTimezone {timezone, source}, and resolved youtrack.update/meeting/time descriptors carry workDate. - Replace the hand-picked string blocklist with a source scan for concrete *.youtrack.cloud hosts and literal issue-id fallbacks. - Docs: README and AGENTS.md describe the youtrack.json-only settings and the surfaced timezone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
workDate was inside descriptorPayload.resolved, which externalActionDescriptor hashes, so the same request and dateMs produced a different descriptor under a different process timezone. An action approved in one process (e.g. TZ=America/Santiago) then failed with "approved external action target changed before execution" in another (TZ=UTC), and actions approved before the field existed could never match. - Move workDate to a display-only ResolvedExternalAction.workDate beside descriptorPayload; `workit action --preview` reports it. - Tests (subprocesses with TZ set): the descriptor is identical across Santiago/Tokyo/UTC and has no workDate; a youtrack.time approved under Santiago executes under UTC; an old-shape youtrack.update (no workDate) still matches. All three fail on the previous commit. - Tighten the org-specifics guard: 2+ char project keys, standard identifiers (UTF-8, SHA-256, ...) excluded, issue ids in issue fields (`meetingIssue: "ABC-12"`) and hard-coded IANA region zones flagged; hit and non-hit cases are tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve conflicts with #152 (dead-code removal) and #149: keep main's deletions of initStatusData/toolkitStatusData and writeTemplate/ listTemplates (and their tests) together with this branch's YouTrack, timezone, greeting and workDate changes. The draft-template test now writes its override via templatePath. Remove youTrackVerifyToken, which lost its last caller with initStatusData. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
🎉 This PR is included in version 2.1.3 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
BrainerVirus
added a commit
that referenced
this pull request
Oct 3, 2026
Conflicts resolved keeping both intents: - package.json: config-driven lint/format scripts and pinned tooling from this branch; #152's knip reachability step and #155's test tiers (`test` = unit, `test:packaging`) and `check` from main; ink devDependency from main. - ci.yml: the new fast/test/portability layout; the Linux test job runs both tiers, which covers #155's `remaining` job (codex, mcp, opencode-v2, acceptance) and every other directory. - Source/test files main rewrote or deleted (#149, #151, #152, #155): main's version taken; lint fixes are re-applied in a follow-up commit. - bun.lock regenerated with bun 1.4.1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BrainerVirus
added a commit
that referenced
this pull request
Oct 3, 2026
Safe autofixes (toSorted, unnecessary assertions) plus manual no-shadow renames and typed sort keys on code that arrived with #149/#151/#152/#155. The boolean-compare, type-conversion, template-expression and map-spread rules stay off, so no strict comparison or coercion was rewritten (checked: no removed `=== true`/`!== true`/`=== false`/`!== false`, String(), Boolean() or new Object.assign in the diff). The confirmation-gate test drops its migrateLegacyDocs case: #152 deleted docs-migration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BrainerVirus
added a commit
that referenced
this pull request
Oct 3, 2026
…, dependency bumps) (#153) * build(deps): bump zod, MCP SDK, OpenCode SDK, Oxc tooling, knip, release plugins - zod 4.5.4 -> 4.6.5 (core, mcp) - @modelcontextprotocol/sdk 1.30.0 -> 1.32.0 - @opencode-ai/plugin 1.18.30 -> 1.18.34 (support-matrix current + CI env; the 1.18.30 floor is unchanged) - oxlint 1.81.0 -> 1.86.0, oxfmt 0.66.0 -> 0.71.0, knip 6.35.1 -> 6.39.0 - @semantic-release/npm 13.2.0, @semantic-release/github 12.0.10 - conventional-changelog-conventionalcommits 8.0.0 -> 9.3.1: 10.x needs conventional-changelog-writer@9, but @semantic-release/release-notes-generator 14.1.1 (latest) still ships writer@8 and fails at render time; 9.3.1 renders identical notes. knip 6.39 now reports the `npm exec -c workit-cursor-session-start` call in the packed-runtime test as an unlisted binary; it is the workit-cursor bin installed into a temp project, so it is ignored like glab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(lint): config-driven oxlint (correctness/suspicious/perf, type-aware) and oxfmt - Add .oxlintrc.json: correctness=error, suspicious+perf=warn with denyWarnings, explicit eslint/typescript/unicorn/oxc plugins, and type-aware rules through oxlint-tsgolint 7.0.2003 (bundles typescript-go, works with TS 7; whole repo lints in ~2 s). - Add .oxfmtrc.json. Lint and format now walk the repo root and skip gitignored paths plus ignorePatterns, so package.json no longer repeats the path list four times, and previously unchecked scripts/ and packages/*/scripts are covered. - Fix findings instead of silencing them: sort/reverse -> toSorted/ toReversed (tsconfig target ES2023), no-shadow renames (e.g. locals that shadowed the `path` module), filter()[0] -> find/findLast, unbound runtime methods wrapped, needless awaits/assertions/conversions removed, `${array}` -> join(","). - Rules turned off carry a justification in the config: no-await-in-loop (ordered subprocess/lock steps), consistent-function-scoping (style), no-unsafe-type-assertion (~1k JSON-boundary casts, ratchet later), no-base-to-string (tsgolint ignores checkUnknown), consistent-return (tsc already enforces it); in tests, await-thenable (bun-types type `.resolves/.rejects` as void) and unbound-method (monkeypatch restore). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(hooks): add opt-in lefthook pre-commit and commitlint commit-msg hooks pre-commit formats (oxfmt, re-staged) and lints (oxlint, type-aware) only the staged files in parallel: ~0.8 s measured. commit-msg runs commitlint with the conventional config (~0.5 s), since semantic-release and analyze-release-scope read Conventional Commits. Install is opt-in via `bun run hooks:install` and `no_auto_install` is set, because git hooks are shared by every worktree of a clone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(ci): pin react-doctor 0.9.14 as a devDependency and delete probe workflows `npx -y react-doctor@latest` resolved a new version on every run, and since 0.9.x it prints "React Doctor is not installed in this project" and exits 0 when react-doctor is not a dependency, so the CI gate scanned nothing. As a pinned devDependency it runs the real scan (~2 s; warnings only, no errors). sync-token-probe.yml was a dispatch-only check to delete "once the token is stable"; the last probe passed on 2026-08-28 and the v2.1.0 manifest-sync PR (#147) was opened with RELEASE_SYNC_TOKEN. windows-inner-suite-probe.yml runs test/workit-core/handoff.test.ts and sdd.test.ts, which no longer exist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(ci): one fast parallel job, every test suite, SHA-pinned actions, CI-gated release CI: - `fast` job: one install, then lint (type-aware), format, knip, typecheck, react-doctor, actionlint and zizmor run concurrently (~5 s locally). Typecheck ran in 6 jobs and lint/format hid in a job named `shared`. - `test` job runs a plain `bun test` on Linux after one build, so test/workit-codex, test/workit-mcp, test/opencode-v2 and test/acceptance (never run in CI before) are covered, and new directories cannot escape. - `portability`: core + artifacts on macOS/Windows with one build each. The separate candidate job duplicated test/artifacts/phase-0-candidate. - Builds drop from 5 to 3 (one per OS); typecheck from 6 to 1. - Actions pinned to commit SHAs, persist-credentials: false, permissions default to none per job; actionlint and zizmor (offline) are clean. - PR runs cancel superseded runs; main runs are grouped per commit. Release: - release.yml is now a reusable workflow called by the `release` job in ci.yml with needs: [fast, test, portability], so a commit only publishes after its own CI passed. Secrets are passed explicitly (no inherit). - concurrency group with cancel-in-progress: false, so two merges cannot race on tags. - semantic-release runs from the pinned devDependency (`bun run release`) instead of an unpinned `npx`. - npm provenance: id-token: write plus NPM_CONFIG_PROVENANCE=true; npm still authenticates with NPM_TOKEN. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(lint): restore strict confirmation gates and non-mutating maps loosened by autofix The type-aware autofixes trusted declared types at untyped JSON/env/host boundaries: - no-unnecessary-boolean-literal-compare rewrote `confirmed !== true` to truthiness in requireConfirmed (OpenCode init apply), migrateLegacyDocs and YouTrack postUpdate, so `confirmed: "false"`, "no" or 1 passed the gate. - no-unnecessary-type-conversion / -template-expression dropped String(), Boolean() and `${}` coercions (hostingApiHostMatches returned undefined instead of false). - the no-map-spread suggestion turned `({ ...entry, ... })` inside map() into Object.assign(entry, ...), mutating the source decisions/fixtures. Every rewritten `=== true`/`!== true`/`=== false`/`!== false` comparison and coercion is restored as it was on main (46 lines plus vcs-config and the four Object.assign sites). The four rules are turned off with the reason in .oxlintrc.json. Regression tests: confirmation gates reject "false", "no", "true", 1 and {} (all three fail against the loosened code). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(ci): validate the Cursor marketplace before building and gate the release candidate pre-merge The CA-21 marketplace check must run on a clean checkout, so it now runs before `bun run build`. The test job also runs `verify:release-candidate` (the same pack-only gate release.yml runs before publishing, ~1.5 s locally), so a broken candidate fails the PR instead of the release. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(hooks): keep lefthook's postinstall from installing hooks on dependency install The npm package's postinstall runs `lefthook install`, which ignores no_auto_install and would write into the .git/hooks shared by every worktree. bun already blocks it (lefthook is not in trustedDependencies); pnpm (`pnpm.neverBuiltDependencies`) and yarn (`dependenciesMeta.built: false`) are now opted out explicitly, and npm cannot install this workspace at all (EUNSUPPORTEDPROTOCOL on workspace:*, verified). A project-config test keeps lefthook untrusted and hooks opt-in via `bun run hooks:install`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(lint): restore the locale and YouTrack date String() coercions Two coercions dropped by no-unnecessary-type-conversion were missed by the earlier restore (multi-line on main): config locale validation and the YouTrack logTime date argument now match main exactly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(lint): apply lint fixes to code merged from main Safe autofixes (toSorted, unnecessary assertions) plus manual no-shadow renames and typed sort keys on code that arrived with #149/#151/#152/#155. The boolean-compare, type-conversion, template-expression and map-spread rules stay off, so no strict comparison or coercion was rewritten (checked: no removed `=== true`/`!== true`/`=== false`/`!== false`, String(), Boolean() or new Object.assign in the diff). The confirmation-gate test drops its migrateLegacyDocs case: #152 deleted docs-migration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What it does
Slice S7 from
docs/workit-next/plan.md: tooling, CI and release refresh. Five focused commits:build(deps): zod 4.5.4 → 4.6.5,@modelcontextprotocol/sdk1.30.0 → 1.32.0,@opencode-ai/plugin1.18.30 → 1.18.34 (the support-matrixcurrentand CI env move with it; the 1.18.30 floor stays), oxlint 1.86.0, oxfmt 0.71.0, knip 6.39.0,@semantic-release/npm13.2.0 and/github12.0.10. All pins stay exact.conventional-changelog-conventionalcommitsgoes to 9.3.1, not 10.x. 10.x needsconventional-changelog-writer@9.@semantic-release/release-notes-generator14.1.1 (the latest) still ships writer@8, so 10.x fails with a "Missing helper" error at render time. I checked this by rendering notes through the generator: 9.3.1 produces the same output as 8.0.0.schema-depth.test.tspasses on zod 4.6.5 with no changes.chore(lint): adds.oxlintrc.jsonand.oxfmtrc.json, which now hold the list of paths to lint and format. The scripts are justoxlint,oxlint --fix,oxfmtandoxfmt --check. This drops the 4× duplicated path list and addsscripts/andpackages/*/scripts, which were not checked before.denyWarningson.oxlint-tsgolint7.0.2003. It bundles typescript-go, so it works with TS 7, and the whole repo lints in about 2 s.sort/reverse→toSorted/toReversed(tsconfig target is now ES2023)no-shadowrenames, including locals that shadowed thepathmodulefilter()[0]→find/findLastno-await-in-loop,consistent-function-scoping,no-unsafe-type-assertion(about 1k casts at JSON boundaries; to tighten later),no-base-to-string(tsgolint does not honorcheckUnknownyet) andconsistent-return. In tests only:await-thenable(bun-types types.resolves/.rejectsas void) andunbound-method.chore(hooks): lefthook, opt-in withbun run hooks:install.no_auto_install: trueis set because hooks are shared by every worktree of a clone.chore(ci): react-doctor is now a pinned devDependency (0.9.14). The two obsolete probe workflows are deleted (details under CI notes).chore(ci): CI restructure and a release that waits for CI (see below).CI and release
fast checks: one install, then lint, format, knip, typecheck, react-doctor, actionlint and zizmor run in parallel inside one step. Each gate prints its own log section with its exit code and duration.test (ubuntu-latest): one build, then a plainbun test. Every test directory runs. I confirmed thattest/workit-codex,test/workit-mcp,test/opencode-v2andtest/acceptancewere not in any CI job before.test (macos-latest)/test (windows-latest):test/workit-coreandtest/artifacts, same as before.candidatejob is gone: it repeatedphase-0-candidate, whichtest/artifactsalready runs.artifactsjob'sref: head_refcheckout is no longer needed: the phase-9 test already handles a detached HEAD.persist-credentials: falseeverywhere.permissions: {}at the top level, with only what each job needs added per job.release.yml):releasejob in ci.yml. That job only runs afterfast,testandportabilitypass for the same commit on main.inherit.cancel-in-progress: false, so two merges cannot race on tags.bun run release, which uses the pinned semantic-release devDependency instead of an unpinnednpxdownload.id-token: writeplusNPM_CONFIG_PROVENANCE=true.npm publishstill authenticates withNPM_TOKEN; provenance only adds the OIDC attestation. The repo is public and every package'srepository.urlmatches it.Measured (local, Node 24.20.0, bun 1.4.1)
oxlintwith types, whole repo, run alonebun testThe 2 local failures are environmental:
bun testpicks up the sibling worktree../s0-docs, which has nonode_modules. This also fails onmainin this layout.metadata.locktimeout under full-suite load. It passes when its file runs alone (3/3). This is the lock contention that S1 fixes.Also:
actionlintreports nothing, and zizmor 1.30.1 (--offline) reports no findings. One finding is ignored on purpose: zizmor suggests the$/self-repository syntax, which actionlint 1.7.12 rejects. The ignore comment explains this.CI notes / action needed
check (workit-core) (…),check (workit-opencode),check (workit-cursor),check (workit-cli),check (shared)). Those jobs no longer exist, so this PR and the automated manifest-sync PRs will wait on checks that never report. Before merging, change the required checks tofast checks,test (ubuntu-latest),test (macos-latest),test (windows-latest). I did not change repository settings.npx react-doctor@latestprints "React Doctor is not installed in this project" and exits 0. As a pinned devDependency it now runs the real scan. It currently reports warnings only, no errors.bun run check(not plainbun test) putsnode_modules/.binfirst on PATH. That bin folder contains thenpmthat@semantic-release/npmpulls in, so 2 packed-CLI tests fail to resolve the npm CLI when run that way. This already happens onmain. CI callsbun testdirectly, so it is not affected. Follow-up for the test helpers.sync-token-probe.yml: its own note said to delete it once the token was stable. The last probe passed on 2026-08-28, and RELEASE_SYNC_TOKEN opened manifest-sync PR chore(release): sync manifests to v2.1.0 #147.windows-inner-suite-probe.yml: it runshandoff.test.tsandsdd.test.ts, which no longer exist.Quality gates
Checklist
@openclaw/fs-safeare not bumped.Review follow-ups (ac3307f)
baseUrlnow givescreateUrl: nulland an error that namesyoutrack.json.meetingIssue, meetings mode asks for one instead of using a built-in issue.workItemText, elsemeetingWorkItemTextinyoutrack.json, elseMeetings.greeting.mdtemplate and the"greeting"template name are gone.buildDraftno longer takesgreetingand the bundled template no longer has{{greetingSection}}. A user template that still has that placeholder, or any other unknown one, renders it as empty.dateMs.localDateis now the UTC calendar day of the epoch, so it round-trips (tested in 5 timezones).youTrackWorkDateMsreturnstimezoneSource.context()returnsworkTimezone: { timezone, source }.youtrack.update,youtrack.meetingandyoutrack.timeactions includeworkDate: { localDate, timezone, timezoneSource }. Since 000327b this sits beside the approval descriptor, not inside it (see the next section).*.youtrack.cloudhost (example.hosts are allowed) or any quoted issue-id literal used as a??/||fallback inpackages/*/src.bun teston Node 24.20.0: 1570 pass, 9 fail.origin/mainon this machine: 5 Pi/Codex packed-launcher tests and AR-14.cursor-install-invariantsandexternal-action: 35 pass, 0 fail).packages/workit-opencode/src/tools/youtrack.tsandtools/templates.tswere not edited. They still compile without a shim.normalizeContextalso accepts the legacy{ data }envelope those tools use.Second review follow-up (000327b)
workDatemoved out of the hashed descriptor. In ac3307f it sat insidedescriptorPayload.resolved, whichexternalActionDescriptorhashes. So an action approved under one process timezone did not match when it ran under another. Old approvals could never match either. It is nowResolvedExternalAction.workDate, next to the descriptor and display only.workit action --previewshows it.youtrack-descriptor-tz.test.ts. Each phase runs in its own process withTZset.workDate.youtrack.timeaction approved under Santiago runs under UTC and succeeds.youtrack.updatein the old shape (noworkDate) still matches.approved external action target changed before executionand pass now.UTF-8andSHA-256are excluded.meetingIssue: "ABC-12") are now flagged.timezone:value are flagged.bun test: 1577 pass, 6 fail. The 6 are the same environment-dependent tests that also fail onorigin/mainon this machine (5 Pi/Codex packed-launcher tests and AR-14).🤖 Generated with Claude Code