@codyswann/lisa 3.3.0 → 3.4.1
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/all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh +31 -0
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +24 -2
- package/dist/codex/scripts/block-no-verify.sh +53 -4
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +33 -12
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-implement/SKILL.md +4 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-quality-review/SKILL.md +7 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-review-local/SKILL.md +27 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-tdd-implementation/SKILL.md +1 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-track/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
- package/plugins/lisa/hooks/block-no-verify.agy.sh +53 -4
- package/plugins/lisa/hooks/block-no-verify.sh +31 -0
- package/plugins/lisa/rules/eager/design-source-of-truth.md +38 -0
- package/plugins/lisa/rules/eager/tracked-work.md +1 -1
- package/plugins/lisa/rules/reference/design-source-of-truth.md +195 -0
- package/plugins/lisa/rules/reference/tracked-work.md +4 -2
- package/plugins/lisa/scripts/design-source-gate.mjs +530 -0
- package/plugins/lisa/skills/lisa-implement/SKILL.md +4 -2
- package/plugins/lisa/skills/lisa-quality-review/SKILL.md +7 -0
- package/plugins/lisa/skills/lisa-review-local/SKILL.md +27 -0
- package/plugins/lisa/skills/lisa-tdd-implementation/SKILL.md +1 -0
- package/plugins/lisa/skills/lisa-track/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
- package/plugins/lisa-agy/hooks/block-no-verify.agy.sh +53 -4
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/scripts/design-source-gate.mjs +530 -0
- package/plugins/lisa-agy/skills/lisa-implement/SKILL.md +4 -2
- package/plugins/lisa-agy/skills/lisa-quality-review/SKILL.md +7 -0
- package/plugins/lisa-agy/skills/lisa-review-local/SKILL.md +27 -0
- package/plugins/lisa-agy/skills/lisa-tdd-implementation/SKILL.md +1 -0
- package/plugins/lisa-agy/skills/lisa-track/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/hooks/block-no-verify.sh +31 -0
- package/plugins/lisa-copilot/rules/eager/design-source-of-truth.md +38 -0
- package/plugins/lisa-copilot/rules/eager/tracked-work.md +1 -1
- package/plugins/lisa-copilot/rules/reference/design-source-of-truth.md +195 -0
- package/plugins/lisa-copilot/rules/reference/tracked-work.md +4 -2
- package/plugins/lisa-copilot/scripts/design-source-gate.mjs +530 -0
- package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +4 -2
- package/plugins/lisa-copilot/skills/lisa-quality-review/SKILL.md +7 -0
- package/plugins/lisa-copilot/skills/lisa-review-local/SKILL.md +27 -0
- package/plugins/lisa-copilot/skills/lisa-tdd-implementation/SKILL.md +1 -0
- package/plugins/lisa-copilot/skills/lisa-track/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/block-no-verify.sh +31 -0
- package/plugins/lisa-cursor/rules/design-source-of-truth-reference.mdc +200 -0
- package/plugins/lisa-cursor/rules/design-source-of-truth.mdc +43 -0
- package/plugins/lisa-cursor/rules/tracked-work-reference.mdc +4 -2
- package/plugins/lisa-cursor/rules/tracked-work.mdc +1 -1
- package/plugins/lisa-cursor/scripts/design-source-gate.mjs +530 -0
- package/plugins/lisa-cursor/skills/lisa-implement/SKILL.md +4 -2
- package/plugins/lisa-cursor/skills/lisa-quality-review/SKILL.md +7 -0
- package/plugins/lisa-cursor/skills/lisa-review-local/SKILL.md +27 -0
- package/plugins/lisa-cursor/skills/lisa-tdd-implementation/SKILL.md +1 -0
- package/plugins/lisa-cursor/skills/lisa-track/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/hooks/block-no-verify.agy.sh +53 -4
- package/plugins/src/base/hooks/block-no-verify.sh +31 -0
- package/plugins/src/base/rules/eager/design-source-of-truth.md +38 -0
- package/plugins/src/base/rules/eager/tracked-work.md +1 -1
- package/plugins/src/base/rules/reference/design-source-of-truth.md +195 -0
- package/plugins/src/base/rules/reference/tracked-work.md +4 -2
- package/plugins/src/base/scripts/design-source-gate.mjs +530 -0
- package/plugins/src/base/skills/lisa-implement/SKILL.md +4 -2
- package/plugins/src/base/skills/lisa-quality-review/SKILL.md +7 -0
- package/plugins/src/base/skills/lisa-review-local/SKILL.md +27 -0
- package/plugins/src/base/skills/lisa-tdd-implementation/SKILL.md +1 -0
- package/plugins/src/base/skills/lisa-track/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -102,16 +102,65 @@ def disables_verification(token):
|
|
|
102
102
|
and NO_VERIFY.startswith(token)
|
|
103
103
|
)
|
|
104
104
|
|
|
105
|
+
# The only relocations that keep a repo's own hooks in play. Anything else —
|
|
106
|
+
# including "" and /dev/null, which are simply the two most obvious members of
|
|
107
|
+
# the blocked set rather than special cases — is refused.
|
|
108
|
+
PERMITTED_HOOKS_PATHS = {".husky", ".githooks"}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def is_permitted_hooks_path(value):
|
|
112
|
+
"""Whether a core.hooksPath value relocates hooks rather than disabling them.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
value: The raw core.hooksPath value as it appeared on the command line.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
True if the path is an established in-repo hooks directory.
|
|
119
|
+
"""
|
|
120
|
+
cleaned = value.strip().strip("'\"")
|
|
121
|
+
if cleaned.startswith("./"):
|
|
122
|
+
cleaned = cleaned[2:]
|
|
123
|
+
return cleaned.rstrip("/") in PERMITTED_HOOKS_PATHS
|
|
124
|
+
|
|
125
|
+
|
|
105
126
|
for i, token in enumerate(normalized_tokens):
|
|
106
127
|
if disables_verification(token):
|
|
107
128
|
sys.exit(1)
|
|
108
129
|
if token == "HUSKY=0" or token.startswith("HUSKY_SKIP_HOOKS="):
|
|
109
130
|
sys.exit(1)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
131
|
+
# Allowlist the destinations, do not denylist the disabling ones: hooks are
|
|
132
|
+
# disabled just as completely by any directory that happens to contain none
|
|
133
|
+
# (`-c core.hooksPath=/tmp/empty`), so the set that DISABLES hooks is
|
|
134
|
+
# unbounded while the set that legitimately relocates them is tiny. Matched
|
|
135
|
+
# case-insensitively because git config names are.
|
|
136
|
+
lowered = token.lower()
|
|
137
|
+
if lowered.startswith("core.hookspath="):
|
|
138
|
+
if not is_permitted_hooks_path(token.split("=", 1)[1]):
|
|
139
|
+
sys.exit(1)
|
|
140
|
+
if lowered == "core.hookspath" and i + 1 < len(normalized_tokens):
|
|
141
|
+
if not is_permitted_hooks_path(normalized_tokens[i + 1]):
|
|
142
|
+
sys.exit(1)
|
|
143
|
+
# `--config-env=core.hooksPath=SOMEVAR` reads the path out of the named env
|
|
144
|
+
# var, so it is not in the command at all and cannot be allowlisted.
|
|
145
|
+
if lowered.startswith("--config-env="):
|
|
146
|
+
spec = token.split("=", 1)[1]
|
|
147
|
+
if spec.split("=", 1)[0].strip().lower() == "core.hookspath":
|
|
148
|
+
sys.exit(1)
|
|
149
|
+
# git also accepts `--config-env <name>=<envvar>` as two tokens. Guarding
|
|
150
|
+
# only the `=` spelling let the trailing `core.hooksPath=.husky` fall
|
|
151
|
+
# through to the allowlist above, which reads `.husky` as a path — but here
|
|
152
|
+
# it names an ENVIRONMENT VARIABLE, which can hold /dev/null. Checked at the
|
|
153
|
+
# `--config-env` token, which the loop reaches first.
|
|
154
|
+
if lowered == "--config-env" and i + 1 < len(normalized_tokens):
|
|
155
|
+
spec = normalized_tokens[i + 1]
|
|
156
|
+
if spec.split("=", 1)[0].strip().strip("'\"").lower() == "core.hookspath":
|
|
113
157
|
sys.exit(1)
|
|
114
|
-
|
|
158
|
+
# `GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=core.hooksPath
|
|
159
|
+
# GIT_CONFIG_VALUE_0=/dev/null git ...` sets the same command-scope config
|
|
160
|
+
# via env-var-style assignments. The index is arbitrary below
|
|
161
|
+
# GIT_CONFIG_COUNT, so it is matched as `\d+` rather than pinned to 0.
|
|
162
|
+
key_match = re.match(r"git_config_key_\d+=(.*)$", lowered, re.DOTALL)
|
|
163
|
+
if key_match and key_match.group(1).strip().strip("'\"") == "core.hookspath":
|
|
115
164
|
sys.exit(1)
|
|
116
165
|
|
|
117
166
|
sys.exit(0)
|
|
@@ -186,6 +186,37 @@ for i, token in enumerate(normalized_tokens):
|
|
|
186
186
|
spec = token.split("=", 1)[1]
|
|
187
187
|
if spec.split("=", 1)[0].strip().lower() == "core.hookspath":
|
|
188
188
|
sys.exit(1)
|
|
189
|
+
# git accepts `--config-env <name>=<envvar>` as TWO tokens as well as one,
|
|
190
|
+
# and guarding only the `=` spelling was worse than missing the separate
|
|
191
|
+
# form outright: the trailing `core.hooksPath=.husky` then fell through to
|
|
192
|
+
# the allowlist above, which reads `.husky` as a PATH and permits it. But
|
|
193
|
+
# here it is an ENVIRONMENT VARIABLE NAME, and `env '.husky=/dev/null' git
|
|
194
|
+
# --config-env core.hooksPath=.husky` really does resolve hooksPath to
|
|
195
|
+
# /dev/null. The allowlist was being used as the bypass.
|
|
196
|
+
#
|
|
197
|
+
# Checked at the `--config-env` token, which the loop reaches first, so the
|
|
198
|
+
# refusal happens before the value token can be mistaken for a path.
|
|
199
|
+
if lowered == "--config-env" and i + 1 < len(normalized_tokens):
|
|
200
|
+
spec = normalized_tokens[i + 1]
|
|
201
|
+
if spec.split("=", 1)[0].strip().strip("'\"").lower() == "core.hookspath":
|
|
202
|
+
sys.exit(1)
|
|
203
|
+
# `GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=core.hooksPath
|
|
204
|
+
# GIT_CONFIG_VALUE_0=/dev/null git commit` sets command-scope config the
|
|
205
|
+
# same way `-c core.hooksPath=...` does — env-var-style assignments ahead of
|
|
206
|
+
# the invocation instead of a flag — so it disables every hook just as
|
|
207
|
+
# completely while matching none of the token shapes above. Upstream missed
|
|
208
|
+
# this until a downstream fork hardened its own copy against it, which is
|
|
209
|
+
# the one direction a guard must never be caught in.
|
|
210
|
+
#
|
|
211
|
+
# The index is matched as `\d+` rather than pinned to 0: git accepts any
|
|
212
|
+
# index below GIT_CONFIG_COUNT, so a single-index check is evaded by typing
|
|
213
|
+
# a 1. Refused outright, like --config-env=, because the path lives in a
|
|
214
|
+
# separate GIT_CONFIG_VALUE_<n> token that can be exported earlier,
|
|
215
|
+
# reordered, or left out entirely — there is nothing here to allowlist
|
|
216
|
+
# against.
|
|
217
|
+
key_match = re.match(r"git_config_key_\d+=(.*)$", lowered, re.DOTALL)
|
|
218
|
+
if key_match and key_match.group(1).strip().strip("'\"") == "core.hookspath":
|
|
219
|
+
sys.exit(1)
|
|
189
220
|
|
|
190
221
|
sys.exit(0)
|
|
191
222
|
PY
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Design Source of Truth (load-bearing)
|
|
2
|
+
|
|
3
|
+
**Figma is the design source of truth, and every UI surface a change touches declares where its design came from.** A changed UI surface that neither cites a Figma node nor carries the designated marker is a contract violation — and so is a surface whose declaration the gate cannot resolve.
|
|
4
|
+
|
|
5
|
+
**One vendor-neutral contract, cited by** `lisa-implement`, `lisa-tdd-implementation`, `lisa-review-local`, `lisa-quality-review`, and `lisa-tracker-source-artifacts` (the `leaf-only-lifecycle` / `repo-scope-split` precedent: one shared slug, never divergent per-skill prose).
|
|
6
|
+
|
|
7
|
+
## Membership
|
|
8
|
+
|
|
9
|
+
Membership is **surface, not repo name or file extension**: a file is in scope the moment a change makes it render something user-observable — a screen, component, layout, style token, visual state, or markup a user reads. Barrels, pure-logic modules, tests, stories, generated output, and vendored code are out. Projects narrow or widen the default detection through `designSource.include` / `designSource.exclude` in `.lisa.config.json`; they never turn the obligation off.
|
|
10
|
+
|
|
11
|
+
## The two declarations
|
|
12
|
+
|
|
13
|
+
Exactly one of these, written as an ordinary comment in whatever syntax the file uses:
|
|
14
|
+
|
|
15
|
+
| Form | Means |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `DESIGN-SOURCE: <figma-url>` | The surface is backed by a Figma node — it already existed there, or it was synced back. |
|
|
18
|
+
| `DESIGN-SOURCE: none — not in Figma` | The surface is deliberately not captured at the design source. |
|
|
19
|
+
|
|
20
|
+
The marker's spelling is fixed and load-bearing; a drifted spelling silently disarms the gate. An optional trailing ` — <reason>` records why. Only a `figma.com` URL seals a surface: a link to a screenshot, a Slack thread, or any other mock is **malformed**, not proof.
|
|
21
|
+
|
|
22
|
+
## Sync-back is the default; the marker is the exception, not the default
|
|
23
|
+
|
|
24
|
+
When the flow has proven Figma access (the `tool-access-gate` probe), reflecting the surface in Figma and citing the node is the expected outcome. Reach for the marker only when the surface genuinely does not belong in the design source — a debug affordance, a dev-only playground, a throwaway internal tool. The gate reports every marked exception so review can challenge it, and reports a reasonless exception separately when Figma access was available.
|
|
25
|
+
|
|
26
|
+
## Host design-system rules stay authoritative
|
|
27
|
+
|
|
28
|
+
Projects that carry their own design-system rules (`figma-design-system`, `design-system`, `use-the-design-library`, or an equivalent) keep them. This contract never restates component hierarchy, token vocabulary, or reuse policy, and never overrides them. It asks one orthogonal question the host rules do not: is the design source declared?
|
|
29
|
+
|
|
30
|
+
## The gate fails closed
|
|
31
|
+
|
|
32
|
+
`scripts/design-source-gate.mjs` decides the change deterministically. It fails on an undeclared surface, a malformed annotation, a file that both cites Figma and denies having a source, a changed file it could not read, and a diff it could not compute. **A design-source violation is a blocking review finding, never a warning** — it is not demoted to "optional", "if cheap", or a follow-up. A gate that passes on what it could not read proves nothing, so it never does.
|
|
33
|
+
|
|
34
|
+
## Bootstrap and degradation
|
|
35
|
+
|
|
36
|
+
Adoption never demands a retroactive backfill: the gate judges **only the surfaces this change touched**. Pre-existing unannotated UI is burndown, recorded and worked down, not this work item's blocker. If a project has no Figma at all, that is not an exemption — every changed surface carries the marker, and the resulting exception list is the honest record of how much of the product lives outside its design source. Behavior obligations for the same surfaces are unchanged and still governed by `bdd-e2e-coverage`.
|
|
37
|
+
|
|
38
|
+
Full contract (marker grammar, gate semantics, host-rule precedence, bootstrap procedure): [reference/design-source-of-truth.md](../reference/design-source-of-truth.md).
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
Before the first durable project mutation (code, tests, config, docs, committed research/plans/findings, commits, or PRs), establish exactly one live tracker leaf through `lisa-track`. Read-only discussion and orientation are exempt only while they produce no durable artifact.
|
|
4
4
|
|
|
5
|
-
The mandatory order is: live-validate an explicit ref, or conservatively search and create exactly one valid leaf through `lisa-tracker-write` when no unique match exists; idempotently claim it through `lisa-tracker-claim`; then persist and verify the worktree-local binding with `node scripts/lisa-work-item.mjs
|
|
5
|
+
The mandatory order is: live-validate an explicit ref, or conservatively search and create exactly one valid leaf through `lisa-tracker-write` when no unique match exists; idempotently claim it through `lisa-tracker-claim`; then persist and verify the worktree-local binding with `node scripts/lisa-work-item.mjs link <ref>`. A tracker that answers no, and any claim or binding failure, blocks durable work; a tracker that cannot be reached does not block a commit — the offline checks still run, the skip is loud on stderr, and the required `Work-Item Traceability` check re-runs the live checks with credentials before anything merges.
|
|
6
6
|
|
|
7
7
|
Carry that canonical ref through the branch, every ordinary commit's `Work-Item:` trailer, the PR, usage/evidence, and `lisa-tracker-sync`. Hooks and CI never create tickets. Keep the binding through interruptions or blocked outcomes; run `node scripts/lisa-work-item.mjs clear` only after merge/deploy/verification, two-way linkage/evidence, and the tracker item have all reached true terminal completion.
|