@gillcash/necktie 0.2.0 → 0.4.0
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/.opencode/command/necktie-mode.md +7 -0
- package/.opencode/command/necktie.md +2 -2
- package/.opencode/plugins/necktie.mjs +67 -5
- package/.qoder/rules/necktie.md +28 -10
- package/.qoder-plugin/plugin.json +3 -3
- package/AGENTS.md +28 -10
- package/LICENSE +20 -20
- package/NOTICE +2 -2
- package/README.es.md +46 -27
- package/README.ko.md +45 -26
- package/README.md +83 -118
- package/commands/necktie-mode.toml +5 -0
- package/commands/necktie.toml +2 -2
- package/core/necktie-core.md +28 -10
- package/core/necktie-full.md +36 -0
- package/core/necktie-lite.md +28 -0
- package/core/necktie-ultra.md +42 -0
- package/docs/host-support.md +50 -0
- package/docs/process-provenance.md +48 -0
- package/docs/release-notes-0.4.0.md +14 -0
- package/hooks/copilot-hooks.json +8 -0
- package/hooks/hooks.json +13 -2
- package/hooks/necktie-context.js +126 -14
- package/lib/necktie-command.cjs +44 -0
- package/lib/necktie-policy.cjs +177 -0
- package/lib/necktie-session.cjs +87 -0
- package/package.json +9 -5
- package/pi-extension/index.js +71 -13
- package/pi-extension/package.json +1 -1
- package/plugin.json +3 -3
- package/skills/necktie/SKILL.md +11 -81
- package/skills/necktie/agents/openai.yaml +3 -3
- package/skills/necktie/references/full.md +36 -0
- package/skills/necktie/references/lite.md +28 -0
- package/skills/necktie/references/policy.md +46 -0
- package/skills/necktie/references/ultra.md +42 -0
- package/.opencode/command/necktie-critique.md +0 -5
- package/.opencode/command/necktie-reverse.md +0 -5
- package/.opencode/command/necktie-review.md +0 -5
- package/commands/necktie-critique.toml +0 -2
- package/commands/necktie-reverse.toml +0 -2
- package/commands/necktie-review.toml +0 -2
- package/skills/necktie/references/loop-protocol.md +0 -85
- package/skills/necktie/scripts/necktie_loop.py +0 -199
- package/skills/necktie-critique/SKILL.md +0 -48
- package/skills/necktie-critique/agents/openai.yaml +0 -6
- package/skills/necktie-reverse/SKILL.md +0 -41
- package/skills/necktie-reverse/agents/openai.yaml +0 -6
- package/skills/necktie-reverse/references/blueprint-template.md +0 -54
- package/skills/necktie-review/SKILL.md +0 -61
- package/skills/necktie-review/agents/openai.yaml +0 -6
- package/skills/necktie-review/references/reviewer-rubric.md +0 -29
- package/skills/necktie-review/scripts/validate_review.py +0 -110
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: necktie-critique
|
|
3
|
-
description: Critique and expand an inquiry before execution by testing goal alignment, assumptions, omitted perspectives, and evidence needs. Use inside the Necktie loop or when the user asks what they overlooked, wants the strongest unasked expert question, requests a red-team of the framing, or needs material follow-up questions rather than a direct answer.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Necktie Critique
|
|
7
|
-
|
|
8
|
-
Critique the inquiry, not merely the current answer. Broaden the user's view without turning the task into an endless discovery interview.
|
|
9
|
-
|
|
10
|
-
## Inputs
|
|
11
|
-
|
|
12
|
-
Obtain the goal, intended audience, acceptance criteria, source ledger, constraints, and any baseline approach. If one is missing, infer it when safe and label the assumption.
|
|
13
|
-
|
|
14
|
-
## Method
|
|
15
|
-
|
|
16
|
-
1. Restate the actual decision or outcome in one sentence.
|
|
17
|
-
2. Test whether the requested deliverable is a means to that outcome or has become the goal by accident.
|
|
18
|
-
3. Check the baseline for hidden assumptions, missing stakeholders, incentives, failure modes, alternative explanations, data limitations, and implementation constraints.
|
|
19
|
-
4. Identify contradictions between the goal, evidence, requested format, and available authority.
|
|
20
|
-
5. Simulate the most relevant genuine subject-matter expert. Ask what that expert would need to know before trusting or acting on the result.
|
|
21
|
-
6. Select the single strongest unasked question: the question whose answer would most change the plan, conclusion, or risk.
|
|
22
|
-
7. Separate questions into:
|
|
23
|
-
- `material-now`: execution should pause because different answers produce meaningfully different outputs.
|
|
24
|
-
- `assumption-safe`: proceed under a clearly stated default.
|
|
25
|
-
- `optional-later`: useful but outside the current scope.
|
|
26
|
-
8. Reframe the inquiry so it targets the user's outcome, includes the necessary controls, and remains answerable from the permitted sources.
|
|
27
|
-
|
|
28
|
-
Do not invent domain facts, confuse method guidance with evidence, or criticize stylistic preferences that do not affect the goal.
|
|
29
|
-
|
|
30
|
-
## Output
|
|
31
|
-
|
|
32
|
-
Return this compact structure:
|
|
33
|
-
|
|
34
|
-
```text
|
|
35
|
-
Outcome test: ...
|
|
36
|
-
What is missing or misframed:
|
|
37
|
-
- ...
|
|
38
|
-
Assumptions to expose:
|
|
39
|
-
- ...
|
|
40
|
-
Strongest unasked question: ...
|
|
41
|
-
Why it matters: ...
|
|
42
|
-
Material questions for the user:
|
|
43
|
-
- ... (or "None; proceed with the stated assumptions.")
|
|
44
|
-
Reframed inquiry: ...
|
|
45
|
-
Readiness: READY | NEEDS-ANSWER | BLOCKED
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Use `NEEDS-ANSWER` only for a material user choice. Use `BLOCKED` only when required evidence or authority cannot be obtained within scope.
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: necktie-reverse
|
|
3
|
-
description: Reverse-engineer an iterative conversation, critique, and successful refinements into one fresh-session executable brief. Use inside the Necktie loop, when the user asks for prompt reversal, when a sequence of revisions should become a reusable prompt, or when execution must be separated from prior answer leakage.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Necktie Reverse
|
|
7
|
-
|
|
8
|
-
Compile the useful decisions from an iterative exchange into one self-contained brief that could have produced the desired result in a fresh session.
|
|
9
|
-
|
|
10
|
-
## Build the brief
|
|
11
|
-
|
|
12
|
-
1. Read [references/blueprint-template.md](references/blueprint-template.md) completely.
|
|
13
|
-
2. Extract the stable goal, audience, constraints, approved refinements, source hierarchy, required deliverables, acceptance criteria, and verification requirements.
|
|
14
|
-
3. Preserve explicit user choices. Resolve contradictions by favoring the latest explicit instruction, then higher-authority constraints, then the option best aligned with the stated goal.
|
|
15
|
-
4. Incorporate critique findings that materially improve correctness, usefulness, risk control, or verifiability.
|
|
16
|
-
5. Exclude conversational debris, abandoned approaches, praise, hidden reasoning, and claims that appeared only in prior outputs.
|
|
17
|
-
6. Require fresh execution from raw sources. Label prior outputs as hypotheses or style references unless independently supported.
|
|
18
|
-
7. Include a reviewer contract with an exact decision vocabulary and stopping rule.
|
|
19
|
-
8. Make the brief specific enough to execute yet independent of a particular model, tool name, or unavailable session state.
|
|
20
|
-
|
|
21
|
-
## Quality test
|
|
22
|
-
|
|
23
|
-
Before returning the brief, verify that a capable agent in a new session could answer all of these from the brief alone:
|
|
24
|
-
|
|
25
|
-
- What outcome matters, for whom, and why?
|
|
26
|
-
- Which sources can prove claims, and which only guide the method?
|
|
27
|
-
- What is in and out of scope?
|
|
28
|
-
- What must be delivered and in what form?
|
|
29
|
-
- What constitutes acceptance or failure?
|
|
30
|
-
- What should be checked, by whom, and when should the loop stop?
|
|
31
|
-
|
|
32
|
-
If a material answer is missing, ask one focused question or state a safe assumption. Do not smuggle unresolved ambiguity into vague language.
|
|
33
|
-
|
|
34
|
-
## Output
|
|
35
|
-
|
|
36
|
-
Return:
|
|
37
|
-
|
|
38
|
-
1. `Executable brief` in a single copyable block using the template headings.
|
|
39
|
-
2. `Compilation notes` listing only material assumptions, excluded prior-output claims, and unresolved limitations.
|
|
40
|
-
|
|
41
|
-
Do not include a transcript summary or chain-of-thought.
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# Executable brief template
|
|
2
|
-
|
|
3
|
-
Use these headings. Omit a heading only when it is genuinely inapplicable.
|
|
4
|
-
|
|
5
|
-
```text
|
|
6
|
-
ROLE
|
|
7
|
-
Act as [relevant role and perspective].
|
|
8
|
-
|
|
9
|
-
OUTCOME
|
|
10
|
-
Produce [artifact/action] so that [audience] can [real-world outcome].
|
|
11
|
-
|
|
12
|
-
INPUTS AND SOURCE HIERARCHY
|
|
13
|
-
- Evidence: [sources that may support claims]
|
|
14
|
-
- Method guidance: [sources that govern the process only]
|
|
15
|
-
- Constraints: [authority, safety, scope, format]
|
|
16
|
-
- Prior outputs: [hypotheses/style references only]
|
|
17
|
-
Resolve conflicts in this order: [explicit hierarchy].
|
|
18
|
-
|
|
19
|
-
SCOPE
|
|
20
|
-
Include: [...]
|
|
21
|
-
Exclude: [...]
|
|
22
|
-
|
|
23
|
-
MATERIAL ASSUMPTIONS
|
|
24
|
-
- [...]
|
|
25
|
-
|
|
26
|
-
WORKFLOW
|
|
27
|
-
1. Inspect and classify sources.
|
|
28
|
-
2. Establish a baseline and expose assumptions.
|
|
29
|
-
3. Challenge the inquiry and identify the strongest unasked question.
|
|
30
|
-
4. Produce the deliverable from raw evidence.
|
|
31
|
-
5. Review against the acceptance criteria.
|
|
32
|
-
6. Revise within the stated stopping rule.
|
|
33
|
-
7. Verify in the target environment.
|
|
34
|
-
|
|
35
|
-
DELIVERABLES
|
|
36
|
-
- [exact output, format, and location]
|
|
37
|
-
|
|
38
|
-
ACCEPTANCE CRITERIA
|
|
39
|
-
- [observable pass/fail criterion]
|
|
40
|
-
|
|
41
|
-
EVIDENCE AND CITATION RULES
|
|
42
|
-
- [claim support, freshness, provenance, quotation, or uncertainty rules]
|
|
43
|
-
|
|
44
|
-
REVIEW CONTRACT
|
|
45
|
-
Return APPROVE, REVISE, or BLOCK. Report only material findings with exact evidence and the smallest required change. Ask the strongest unasked expert question. Do not rewrite while reviewing.
|
|
46
|
-
|
|
47
|
-
STOPPING RULE
|
|
48
|
-
Stop when all criteria pass, a material blocker requires user input, the same issue survives three reviews, or three revision decisions are recorded.
|
|
49
|
-
|
|
50
|
-
HANDOFF
|
|
51
|
-
Return the artifact, reusable brief, verification record, limitations, overlooked consideration, and strongest unasked question.
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Write instructions that are observable and testable. Replace adjectives such as "excellent" or "comprehensive" with explicit criteria. Do not request hidden chain-of-thought; request concise assumptions, decisions, evidence, and verification instead.
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: necktie-review
|
|
3
|
-
description: Independently gate a candidate deliverable against its exact brief, evidence, acceptance criteria, and verification results. Use inside the Necktie loop, for an Auto-review-style approval decision, or when the user wants a concise APPROVE, REVISE, or BLOCK judgment with actionable material findings and a strongest unasked question.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Necktie Review
|
|
7
|
-
|
|
8
|
-
Judge the proposed result without silently rewriting it or expanding its scope. Review as a separate role from the author, using the smallest evidence packet that permits a reliable decision.
|
|
9
|
-
|
|
10
|
-
## Inputs
|
|
11
|
-
|
|
12
|
-
Require:
|
|
13
|
-
|
|
14
|
-
- the exact executable brief;
|
|
15
|
-
- the candidate artifact or change set;
|
|
16
|
-
- acceptance criteria and constraints;
|
|
17
|
-
- a source ledger plus relevant evidence excerpts, paths, or links;
|
|
18
|
-
- verification results, if already available.
|
|
19
|
-
|
|
20
|
-
If an input is unavailable, decide whether that absence is itself a material finding. Read [references/reviewer-rubric.md](references/reviewer-rubric.md) completely before judging.
|
|
21
|
-
|
|
22
|
-
## Review
|
|
23
|
-
|
|
24
|
-
1. Inspect the candidate read-only. Do not author fixes while acting as reviewer.
|
|
25
|
-
2. Test each acceptance criterion and every material factual claim against the evidence ledger.
|
|
26
|
-
3. Look for omissions, contradictions, fabricated support, stale assumptions, unsafe actions, unusable formatting, and failure to verify in the target environment.
|
|
27
|
-
4. Check whether the deliverable advances the actual goal rather than merely matching its requested shape.
|
|
28
|
-
5. Identify what the author and user may not have considered.
|
|
29
|
-
6. Name the single strongest unasked expert question and its consequence.
|
|
30
|
-
7. Report only material findings. Combine duplicates and point to exact locations when possible.
|
|
31
|
-
|
|
32
|
-
## Decide
|
|
33
|
-
|
|
34
|
-
- `APPROVE`: no critical or major finding remains. Minor optional improvements may be noted but cannot block approval.
|
|
35
|
-
- `REVISE`: one or more fixable critical or major findings remain. State the smallest required change for each.
|
|
36
|
-
- `BLOCK`: a required decision, authority, source, or safe execution path is absent and the author cannot resolve it within scope.
|
|
37
|
-
|
|
38
|
-
Confidence is not a substitute for evidence. Do not approve because the prose sounds plausible.
|
|
39
|
-
|
|
40
|
-
## Output
|
|
41
|
-
|
|
42
|
-
Return only one JSON object matching this shape:
|
|
43
|
-
|
|
44
|
-
```json
|
|
45
|
-
{
|
|
46
|
-
"decision": "APPROVE",
|
|
47
|
-
"summary": "One-sentence basis for the decision.",
|
|
48
|
-
"findings": [],
|
|
49
|
-
"strongest_unasked_question": "The highest-leverage omitted question.",
|
|
50
|
-
"question_consequence": "What changes if its answer differs.",
|
|
51
|
-
"confidence": "high"
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Each finding must contain `id`, `severity` (`critical`, `major`, or `minor`), `criterion`, `location`, `evidence`, and `required_change`. Use an empty findings array only for approval. Validate a saved decision with:
|
|
56
|
-
|
|
57
|
-
```text
|
|
58
|
-
python skills/necktie-review/scripts/validate_review.py review.json
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Do not include markdown around the JSON, private reasoning, or an edited artifact.
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# Necktie reviewer rubric
|
|
2
|
-
|
|
3
|
-
## Order of review
|
|
4
|
-
|
|
5
|
-
1. **Authority and safety**: Is the action permitted, reversible where appropriate, and within the agreed scope?
|
|
6
|
-
2. **Goal fit**: Does the artifact support the user's actual outcome and audience?
|
|
7
|
-
3. **Evidence integrity**: Are material claims traceable to eligible, current sources? Are method context and prior outputs kept out of the evidence chain?
|
|
8
|
-
4. **Correctness and completeness**: Are calculations, logic, content, and required sections accurate and sufficient?
|
|
9
|
-
5. **Usability**: Can the intended audience use the result in its target environment?
|
|
10
|
-
6. **Verification**: Were the relevant tests, renders, checks, or inspections performed, and do their results support completion?
|
|
11
|
-
7. **Economy**: Is the solution no larger or more complex than the goal requires?
|
|
12
|
-
|
|
13
|
-
## Severity
|
|
14
|
-
|
|
15
|
-
- `critical`: could cause unsafe action, material loss, invalid conclusion, unauthorized change, or failure of the central deliverable.
|
|
16
|
-
- `major`: violates an acceptance criterion, leaves a material unsupported claim, omits a necessary component, or prevents intended use.
|
|
17
|
-
- `minor`: real but non-blocking defect that does not change the decision or intended use.
|
|
18
|
-
|
|
19
|
-
Do not inflate preferences into findings. A valid finding states the violated criterion, exact location, concrete evidence, and smallest required change.
|
|
20
|
-
|
|
21
|
-
## Decision examples
|
|
22
|
-
|
|
23
|
-
- Approve a sound artifact with an optional wording improvement; record it only as a minor finding if useful.
|
|
24
|
-
- Revise when a KPI definition lacks a denominator, a cited claim is unsupported, a requested file does not render, or a required test fails.
|
|
25
|
-
- Block when the user must choose between materially different scopes, required private data is unavailable, or execution needs authority the run does not possess.
|
|
26
|
-
|
|
27
|
-
## Independence
|
|
28
|
-
|
|
29
|
-
Review the artifact that exists, not the artifact you imagine the author intended. Do not fix it during the review pass. If revising later, leave reviewer role and return to author role first.
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Validate the JSON decision emitted by the Necktie reviewer skill."""
|
|
3
|
-
|
|
4
|
-
from __future__ import annotations
|
|
5
|
-
|
|
6
|
-
import argparse
|
|
7
|
-
import json
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
import sys
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
TOP_LEVEL_KEYS = {
|
|
13
|
-
"decision",
|
|
14
|
-
"summary",
|
|
15
|
-
"findings",
|
|
16
|
-
"strongest_unasked_question",
|
|
17
|
-
"question_consequence",
|
|
18
|
-
"confidence",
|
|
19
|
-
}
|
|
20
|
-
FINDING_KEYS = {"id", "severity", "criterion", "location", "evidence", "required_change"}
|
|
21
|
-
DECISIONS = {"APPROVE", "REVISE", "BLOCK"}
|
|
22
|
-
SEVERITIES = {"critical", "major", "minor"}
|
|
23
|
-
CONFIDENCE = {"high", "medium", "low"}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def nonempty_string(value: object) -> bool:
|
|
27
|
-
return isinstance(value, str) and bool(value.strip())
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def validate_review(value: object) -> list[str]:
|
|
31
|
-
errors: list[str] = []
|
|
32
|
-
if not isinstance(value, dict):
|
|
33
|
-
return ["review must be a JSON object"]
|
|
34
|
-
|
|
35
|
-
missing = sorted(TOP_LEVEL_KEYS - value.keys())
|
|
36
|
-
extra = sorted(value.keys() - TOP_LEVEL_KEYS)
|
|
37
|
-
if missing:
|
|
38
|
-
errors.append(f"missing top-level keys: {', '.join(missing)}")
|
|
39
|
-
if extra:
|
|
40
|
-
errors.append(f"unexpected top-level keys: {', '.join(extra)}")
|
|
41
|
-
if missing:
|
|
42
|
-
return errors
|
|
43
|
-
|
|
44
|
-
decision = value["decision"]
|
|
45
|
-
if decision not in DECISIONS:
|
|
46
|
-
errors.append(f"decision must be one of: {', '.join(sorted(DECISIONS))}")
|
|
47
|
-
for field in ("summary", "strongest_unasked_question", "question_consequence"):
|
|
48
|
-
if not nonempty_string(value[field]):
|
|
49
|
-
errors.append(f"{field} must be a non-empty string")
|
|
50
|
-
if value["confidence"] not in CONFIDENCE:
|
|
51
|
-
errors.append(f"confidence must be one of: {', '.join(sorted(CONFIDENCE))}")
|
|
52
|
-
|
|
53
|
-
findings = value["findings"]
|
|
54
|
-
if not isinstance(findings, list):
|
|
55
|
-
errors.append("findings must be an array")
|
|
56
|
-
return errors
|
|
57
|
-
|
|
58
|
-
blocking_findings = 0
|
|
59
|
-
seen_ids: set[str] = set()
|
|
60
|
-
for index, finding in enumerate(findings):
|
|
61
|
-
prefix = f"findings[{index}]"
|
|
62
|
-
if not isinstance(finding, dict):
|
|
63
|
-
errors.append(f"{prefix} must be an object")
|
|
64
|
-
continue
|
|
65
|
-
missing_finding = sorted(FINDING_KEYS - finding.keys())
|
|
66
|
-
extra_finding = sorted(finding.keys() - FINDING_KEYS)
|
|
67
|
-
if missing_finding:
|
|
68
|
-
errors.append(f"{prefix} missing keys: {', '.join(missing_finding)}")
|
|
69
|
-
if extra_finding:
|
|
70
|
-
errors.append(f"{prefix} unexpected keys: {', '.join(extra_finding)}")
|
|
71
|
-
if missing_finding:
|
|
72
|
-
continue
|
|
73
|
-
for field in FINDING_KEYS - {"severity"}:
|
|
74
|
-
if not nonempty_string(finding[field]):
|
|
75
|
-
errors.append(f"{prefix}.{field} must be a non-empty string")
|
|
76
|
-
if finding["severity"] not in SEVERITIES:
|
|
77
|
-
errors.append(f"{prefix}.severity must be one of: {', '.join(sorted(SEVERITIES))}")
|
|
78
|
-
elif finding["severity"] in {"critical", "major"}:
|
|
79
|
-
blocking_findings += 1
|
|
80
|
-
if finding["id"] in seen_ids:
|
|
81
|
-
errors.append(f"duplicate finding id: {finding['id']}")
|
|
82
|
-
seen_ids.add(finding["id"])
|
|
83
|
-
|
|
84
|
-
if decision == "APPROVE" and blocking_findings:
|
|
85
|
-
errors.append("APPROVE cannot contain critical or major findings")
|
|
86
|
-
if decision in {"REVISE", "BLOCK"} and blocking_findings == 0:
|
|
87
|
-
errors.append(f"{decision} requires at least one critical or major finding")
|
|
88
|
-
return errors
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def main(argv: list[str] | None = None) -> int:
|
|
92
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
93
|
-
parser.add_argument("review", type=Path)
|
|
94
|
-
args = parser.parse_args(argv)
|
|
95
|
-
try:
|
|
96
|
-
value = json.loads(args.review.read_text(encoding="utf-8"))
|
|
97
|
-
except (OSError, json.JSONDecodeError) as exc:
|
|
98
|
-
print(f"invalid: {exc}", file=sys.stderr)
|
|
99
|
-
return 2
|
|
100
|
-
errors = validate_review(value)
|
|
101
|
-
if errors:
|
|
102
|
-
for error in errors:
|
|
103
|
-
print(f"invalid: {error}", file=sys.stderr)
|
|
104
|
-
return 1
|
|
105
|
-
print("valid Necktie review")
|
|
106
|
-
return 0
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if __name__ == "__main__":
|
|
110
|
-
raise SystemExit(main())
|