* fix(#3311): milestone lock makes parallel-phase state conflicts visible Two sessions running different phases in one working tree silently clobbered STATE.md's single un-scoped ## Current Position slot: byte-level serialization already existed (STATE.md.lock since #464), but nothing ever surfaced that two sessions claimed two different phases, and state.advance-plan — which takes no phase argument — kept advancing whatever plan the just-clobbered position named. Adds the maintainer-chosen milestone lock (issue #3311 comment): an advisory .planning/milestone.lock claim keyed by phase + session id (session identity via getWorkstreamSessionKey: env-first, then controlling TTY). begin-phase claims (inside the STATE.md lock), advance-plan detects a claim/position mismatch and heartbeats a matching claim, phase.complete warns via warnings[] and releases the claim when the claimed phase completes. Conflicts warn (stderr + typed milestone_conflict JSON field) instead of blocking, per the decision's blocking/warning latitude; TTL 4h with heartbeat liveness expires abandoned claims. milestone.lock is registered in the canonical artifact registry so validate.health W019 recognizes it. * chore(#3311): point changeset fragment at pr 3455 --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -140,6 +140,8 @@ export default tseslint.config(
|
||||
'gsd-core/bin/lib/pattern.cjs',
|
||||
'gsd-core/bin/lib/text-lines.cjs',
|
||||
'gsd-core/bin/lib/token-scanner.cjs',
|
||||
// #3311: tsc-generated runtime artifact — lint src/milestone-lock.cts, not this.
|
||||
'gsd-core/bin/lib/milestone-lock.cjs',
|
||||
'gsd-core/bin/lib/health-diagnostic-types.cjs',
|
||||
'gsd-core/bin/lib/health-diagnostic.cjs',
|
||||
'gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs',
|
||||
|
||||
Reference in New Issue
Block a user