gh-inari 0.6.1 → 0.8.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/.codex-plugin/plugin.json +6 -0
- package/README.md +37 -1
- package/dist/artifact.d.ts +129 -13
- package/dist/artifact.js +579 -63
- package/dist/artifact.js.map +1 -1
- package/dist/cli.js +366 -57
- package/dist/cli.js.map +1 -1
- package/dist/contract/index.d.ts +1 -0
- package/dist/contract/index.js +1 -0
- package/dist/contract/index.js.map +1 -1
- package/dist/contract/ir.d.ts +11 -0
- package/dist/contract/ir.js +23 -1
- package/dist/contract/ir.js.map +1 -1
- package/dist/contract/issue-form.js +15 -2
- package/dist/contract/issue-form.js.map +1 -1
- package/dist/contract/normalization.d.ts +31 -0
- package/dist/contract/normalization.js +73 -0
- package/dist/contract/normalization.js.map +1 -0
- package/dist/contract/validation.d.ts +120 -2
- package/dist/contract/validation.js +476 -3
- package/dist/contract/validation.js.map +1 -1
- package/dist/diagnostics.d.ts +133 -0
- package/dist/diagnostics.js +421 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/github/capability.js +1 -0
- package/dist/github/capability.js.map +1 -1
- package/dist/governance.d.ts +8 -2
- package/dist/governance.js +54 -4
- package/dist/governance.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/pr-policy.d.ts +9 -0
- package/dist/pr-policy.js +36 -16
- package/dist/pr-policy.js.map +1 -1
- package/dist/pr-sync-input.d.ts +74 -0
- package/dist/pr-sync-input.js +231 -0
- package/dist/pr-sync-input.js.map +1 -0
- package/dist/reconciliation.d.ts +15 -2
- package/dist/reconciliation.js +362 -15
- package/dist/reconciliation.js.map +1 -1
- package/dist/semantic-template.js +25 -4
- package/dist/semantic-template.js.map +1 -1
- package/dist/skill.d.ts +42 -0
- package/dist/skill.js +138 -0
- package/dist/skill.js.map +1 -0
- package/package.json +5 -3
- package/skills/inari/SKILL.md +48 -0
package/README.md
CHANGED
|
@@ -119,6 +119,33 @@ npx --yes --package=./gh-inari-<version>.tgz gh-inari --version --json
|
|
|
119
119
|
|
|
120
120
|
Inari uses the current `gh` authentication and repository context. It does not maintain a second credential store. Use `--repository owner/name` when the target repository is not the current checkout.
|
|
121
121
|
|
|
122
|
+
## Codex Plugin
|
|
123
|
+
|
|
124
|
+
The same published `gh-inari` package is also a valid Codex Plugin — no
|
|
125
|
+
second install artifact is needed. Installing or unpacking `gh-inari` (any
|
|
126
|
+
of the paths above) ships `.codex-plugin/plugin.json` and
|
|
127
|
+
`skills/inari/SKILL.md` alongside the CLI. Codex requires explicit
|
|
128
|
+
marketplace registration and installation via Codex plugin commands to
|
|
129
|
+
activate the skill; standard `npm install` alone does not automatically
|
|
130
|
+
surface the plugin to Codex-aware agents.
|
|
131
|
+
|
|
132
|
+
To discover and install it from this repository's marketplace:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
codex plugin marketplace add .
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
In Codex, run `/plugins`, select the `gh-inari` marketplace, and install
|
|
139
|
+
`inari`. Start a new Codex session after installation so the bundled Skill
|
|
140
|
+
is available.
|
|
141
|
+
|
|
142
|
+
The Skill is deliberately thin: it identifies governed GitHub Issue/PR/
|
|
143
|
+
template workflows as Inari-owned and routes agents to `inari skill` /
|
|
144
|
+
`inari skill <scenario>` for the actual operational playbooks, and to
|
|
145
|
+
`inari <domain> --help` for exact command syntax. It does not duplicate
|
|
146
|
+
scenario content, so it stays correct as `inari skill` evolves. Raw `gh`
|
|
147
|
+
remains available for anything outside Inari's governed surface.
|
|
148
|
+
|
|
122
149
|
## Commands
|
|
123
150
|
|
|
124
151
|
```bash
|
|
@@ -159,6 +186,11 @@ inari pr sync <number> --from desired.json [--dry-run]
|
|
|
159
186
|
|
|
160
187
|
The `fields` object is the semantic input contract shown by `schema`. Issue creation also accepts `assignees`; pull request creation accepts `head`, `base`, `draft`, and `maintainerCanModify`. `--title`, `--head`, and `--base` override envelope metadata.
|
|
161
188
|
|
|
189
|
+
`pr sync --from` accepts a complete pull-request desired-state envelope. Use
|
|
190
|
+
`inari pr sync --help` for the top-level contract, or
|
|
191
|
+
`inari pr schema <template> --json` for its machine-readable `syncInput.schema`
|
|
192
|
+
and a valid `syncInput.minimalExample`.
|
|
193
|
+
|
|
162
194
|
Schema and validation output is JSON. `--json` makes render and create output JSON as well. Validation failures return exit status `2`; usage errors return `1`; GitHub/transport failures return `3`. Error objects contain stable `code`, `path` where applicable, and ordered `violations`.
|
|
163
195
|
|
|
164
196
|
`issue get` and `pr get` are canonical-only v1 reads. They resolve the target
|
|
@@ -168,7 +200,11 @@ parse the existing artifact with the same parser and semantic validator as
|
|
|
168
200
|
metadata. Successful reads report `projection: "canonical"`; wrong-template,
|
|
169
201
|
unparseable, ambiguous, and semantically invalid artifacts report structured
|
|
170
202
|
diagnostics with `projection: "unavailable"` and never return guessed fields.
|
|
171
|
-
When `--template` is omitted,
|
|
203
|
+
When `--template` is omitted, Inari first looks for the bounded invisible
|
|
204
|
+
template identity marker every rendered artifact now carries. A valid marker
|
|
205
|
+
resolves the contract directly; an unknown, stale, or wrong-kind marker fails
|
|
206
|
+
closed with a diagnostic instead of guessing another template. Artifacts
|
|
207
|
+
without a marker fall back to evaluating all supported candidates
|
|
172
208
|
deterministically; multiple structural matches fail closed. Native template
|
|
173
209
|
boilerplate and raw Markdown are intentionally absent from successful output.
|
|
174
210
|
|
package/dist/artifact.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type SemanticValidationResult, type SemanticViolation } from "./contract/validation.js";
|
|
2
|
-
import { type
|
|
1
|
+
import { type PartialSemanticValidationResult, type PartialSemanticRepairResult, type SemanticValidationResult, type SemanticViolation } from "./contract/validation.js";
|
|
2
|
+
import { type ArtifactDiagnostic, type ArtifactDiagnosticReport } from "./diagnostics.js";
|
|
3
|
+
import { type ArtifactKind, type CanonicalContract } from "./contract/ir.js";
|
|
3
4
|
import { type ValidatedRenderedIssueArtifact, type ValidatedRenderedPullRequestArtifact } from "./github/types.js";
|
|
4
5
|
export interface ArtifactInputMetadata {
|
|
5
6
|
readonly title?: string;
|
|
@@ -14,6 +15,40 @@ export interface ArtifactInputDocument {
|
|
|
14
15
|
readonly fields: Readonly<Record<string, unknown>>;
|
|
15
16
|
readonly metadata: ArtifactInputMetadata;
|
|
16
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* A representation-independent candidate entering the canonical contract.
|
|
20
|
+
* Adapters may decode JSON, native Markdown, an existing GitHub body, or
|
|
21
|
+
* internal field input, but they never validate or materialize contract
|
|
22
|
+
* semantics themselves.
|
|
23
|
+
*/
|
|
24
|
+
export type ArtifactCandidateSource = "json" | "markdown" | "existing" | "fields";
|
|
25
|
+
export interface ArtifactCandidate {
|
|
26
|
+
readonly fields: unknown;
|
|
27
|
+
readonly metadata: ArtifactInputMetadata;
|
|
28
|
+
readonly source: ArtifactCandidateSource;
|
|
29
|
+
}
|
|
30
|
+
export interface ArtifactCandidateAdapterResult {
|
|
31
|
+
readonly parsed: boolean;
|
|
32
|
+
readonly candidate?: ArtifactCandidate;
|
|
33
|
+
readonly diagnostics: readonly ExistingArtifactDiagnostic[];
|
|
34
|
+
}
|
|
35
|
+
/** Result of the one candidate -> selected contract -> canonical JSON boundary. */
|
|
36
|
+
export interface CanonicalArtifactLoadResult {
|
|
37
|
+
readonly valid: boolean;
|
|
38
|
+
readonly complete: boolean;
|
|
39
|
+
/** Canonical contract-shaped semantic JSON. Never contains rejected fields. */
|
|
40
|
+
readonly canonical: Readonly<Record<string, unknown>>;
|
|
41
|
+
/** Explicit alias for callers that name the output canonical JSON. */
|
|
42
|
+
readonly canonicalJson: Readonly<Record<string, unknown>>;
|
|
43
|
+
/** Backward-compatible semantic value name used by renderer callers. */
|
|
44
|
+
readonly values: Readonly<Record<string, unknown>>;
|
|
45
|
+
readonly candidate: ArtifactCandidate;
|
|
46
|
+
readonly acceptedFields: readonly string[];
|
|
47
|
+
readonly missingFields: PartialSemanticValidationResult["missingFields"];
|
|
48
|
+
readonly invalidFields: PartialSemanticValidationResult["invalidFields"];
|
|
49
|
+
readonly diagnostics: ArtifactDiagnosticReport;
|
|
50
|
+
readonly violations: readonly SemanticViolation[];
|
|
51
|
+
}
|
|
17
52
|
export interface ArtifactMetadataViolation {
|
|
18
53
|
readonly code: "INPUT_METADATA_INVALID";
|
|
19
54
|
readonly path: string;
|
|
@@ -23,21 +58,18 @@ export type ArtifactInputErrorCode = "INPUT_DOCUMENT_INVALID" | "INPUT_METADATA_
|
|
|
23
58
|
export declare class ArtifactInputError extends Error {
|
|
24
59
|
readonly code: ArtifactInputErrorCode;
|
|
25
60
|
readonly path: string;
|
|
26
|
-
|
|
61
|
+
readonly details?: unknown;
|
|
62
|
+
constructor(code: ArtifactInputErrorCode, message: string, path?: string, details?: unknown);
|
|
27
63
|
}
|
|
28
64
|
export type ArtifactPreparationErrorCode = "ARTIFACT_PROVENANCE_MISSING" | "ARTIFACT_ROUND_TRIP_INVALID";
|
|
29
|
-
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
readonly message: string;
|
|
34
|
-
readonly expected?: unknown;
|
|
35
|
-
readonly actual?: unknown;
|
|
36
|
-
}
|
|
65
|
+
/** @deprecated Round-trip diagnostics use the shared #118 diagnostic contract. */
|
|
66
|
+
export type ArtifactRoundTripDiagnostic = ArtifactDiagnostic;
|
|
67
|
+
/** @deprecated Use ArtifactDiagnosticCode/ArtifactDiagnosticDetailCode. */
|
|
68
|
+
export type ArtifactRoundTripDiagnosticCode = ArtifactDiagnostic["code"];
|
|
37
69
|
/** Stable failures raised before a mutation-capable artifact is created. */
|
|
38
70
|
export declare class ArtifactPreparationError extends Error {
|
|
39
71
|
readonly code: ArtifactPreparationErrorCode;
|
|
40
|
-
readonly diagnostics: readonly
|
|
72
|
+
readonly diagnostics: readonly ArtifactDiagnostic[];
|
|
41
73
|
constructor(code: ArtifactPreparationErrorCode, message: string, diagnostics?: readonly ArtifactRoundTripDiagnostic[]);
|
|
42
74
|
}
|
|
43
75
|
export interface PreparedIssueArtifact {
|
|
@@ -51,7 +83,7 @@ export interface PreparedPullRequestArtifact {
|
|
|
51
83
|
readonly artifact: ValidatedRenderedPullRequestArtifact;
|
|
52
84
|
}
|
|
53
85
|
export type ExistingArtifactClassification = "valid" | "semantic" | "wrong-template" | "unparseable" | "ambiguous";
|
|
54
|
-
export type ExistingArtifactDiagnosticCode = "EXISTING_WRONG_TEMPLATE" | "EXISTING_UNPARSEABLE" | "EXISTING_EXTRA_CONTENT" | "EXISTING_UNKNOWN_CHECKLIST_ITEM" | "EXISTING_AMBIGUOUS_TEMPLATE" | "EXISTING_NON_CANONICAL" | "EXISTING_TEMPLATE_COMPILE_FAILED";
|
|
86
|
+
export type ExistingArtifactDiagnosticCode = "EXISTING_WRONG_TEMPLATE" | "EXISTING_UNPARSEABLE" | "EXISTING_EXTRA_CONTENT" | "EXISTING_UNKNOWN_CHECKLIST_ITEM" | "EXISTING_AMBIGUOUS_TEMPLATE" | "EXISTING_NON_CANONICAL" | "EXISTING_TEMPLATE_COMPILE_FAILED" | "EXISTING_TEMPLATE_MARKER_INVALID";
|
|
55
87
|
export interface ExistingArtifactDiagnostic {
|
|
56
88
|
readonly code: ExistingArtifactDiagnosticCode;
|
|
57
89
|
readonly path: string;
|
|
@@ -62,6 +94,15 @@ export interface ExistingArtifactParseResult {
|
|
|
62
94
|
readonly values: Readonly<Record<string, unknown>>;
|
|
63
95
|
readonly diagnostics: readonly ExistingArtifactDiagnostic[];
|
|
64
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Semantic values recovered from an artifact that did not pass the strict
|
|
99
|
+
* structural parser. Values are extracted only from unambiguous contract
|
|
100
|
+
* sections and are still subject to the canonical semantic loader before use.
|
|
101
|
+
*/
|
|
102
|
+
export interface RecoverableArtifactValues {
|
|
103
|
+
readonly values: Readonly<Record<string, unknown>>;
|
|
104
|
+
readonly diagnostics: readonly ExistingArtifactDiagnostic[];
|
|
105
|
+
}
|
|
65
106
|
export interface ExistingArtifactValidationResult {
|
|
66
107
|
readonly valid: boolean;
|
|
67
108
|
readonly classification: ExistingArtifactClassification;
|
|
@@ -82,6 +123,38 @@ export interface ExistingPullRequestReader {
|
|
|
82
123
|
readonly url: string;
|
|
83
124
|
}>;
|
|
84
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Bounded invisible template identity marker embedded in newly rendered
|
|
128
|
+
* artifacts. It is the primary template-selection signal for governed
|
|
129
|
+
* read/repair/validation; legacy artifacts without a marker (or with one
|
|
130
|
+
* that cannot be trusted) fall back to deterministic structural matching.
|
|
131
|
+
* The marker is metadata only: it never substitutes for the authoritative
|
|
132
|
+
* repository governance/provenance that resolves the actual contract.
|
|
133
|
+
*/
|
|
134
|
+
export declare const TEMPLATE_IDENTITY_MARKER_VERSION: "1";
|
|
135
|
+
export interface TemplateIdentityMarker {
|
|
136
|
+
readonly version: string;
|
|
137
|
+
readonly kind: ArtifactKind;
|
|
138
|
+
readonly path: string;
|
|
139
|
+
}
|
|
140
|
+
export type TemplateIdentityMarkerStatus = "absent" | "valid" | "malformed" | "unsupported-version";
|
|
141
|
+
export interface TemplateIdentityMarkerExtraction {
|
|
142
|
+
readonly status: TemplateIdentityMarkerStatus;
|
|
143
|
+
readonly marker?: TemplateIdentityMarker;
|
|
144
|
+
/** Body with a recognized trailing marker line removed; unchanged when none is present. */
|
|
145
|
+
readonly body: string;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Recognize and remove a trailing template identity marker line without
|
|
149
|
+
* applying semantic parsing. Only a line starting with the exact reserved
|
|
150
|
+
* marker prefix is treated as a marker attempt at all; ordinary trailing
|
|
151
|
+
* HTML comments (e.g. PR template scaffolding) are left untouched here and
|
|
152
|
+
* handled by the existing comment-stripping path. Once the reserved prefix
|
|
153
|
+
* is detected, the line is never silently ignored as "absent" again: an
|
|
154
|
+
* oversized, truncated, or otherwise broken marker attempt fails closed as
|
|
155
|
+
* "malformed" instead of falling through to structural matching.
|
|
156
|
+
*/
|
|
157
|
+
export declare function extractTemplateIdentityMarker(body: string): TemplateIdentityMarkerExtraction;
|
|
85
158
|
export interface FetchedExistingArtifact {
|
|
86
159
|
readonly number: number;
|
|
87
160
|
readonly url: string;
|
|
@@ -89,6 +162,41 @@ export interface FetchedExistingArtifact {
|
|
|
89
162
|
}
|
|
90
163
|
/** Parse the documented JSON input envelope while keeping field semantics adapter-independent. */
|
|
91
164
|
export declare function parseArtifactInputDocument(input: unknown): ArtifactInputDocument;
|
|
165
|
+
/** Adapt a parsed JSON envelope without granting it canonical status. */
|
|
166
|
+
export declare function adaptJsonArtifactCandidate(input: unknown): ArtifactCandidate;
|
|
167
|
+
/** Adapt internal structured fields to the same candidate shape as JSON. */
|
|
168
|
+
export declare function adaptFieldArtifactCandidate(fields: unknown, metadata?: ArtifactInputMetadata): ArtifactCandidate;
|
|
169
|
+
/** Alias used by command adapters that call this input the CLI field path. */
|
|
170
|
+
export declare const adaptCliFieldCandidate: typeof adaptFieldArtifactCandidate;
|
|
171
|
+
/** Generic adapter spelling for callers that already hold structured fields. */
|
|
172
|
+
export declare const adaptArtifactCandidate: typeof adaptFieldArtifactCandidate;
|
|
173
|
+
/** Adapt an existing native artifact body through the repository parser. */
|
|
174
|
+
export declare function adaptMarkdownArtifactCandidate(contractInput: unknown, body: string | null | undefined): ArtifactCandidateAdapterResult;
|
|
175
|
+
/** Existing GitHub bodies use the same native Markdown adapter by design. */
|
|
176
|
+
export declare function adaptExistingArtifactCandidate(contractInput: unknown, body: string | null | undefined): ArtifactCandidateAdapterResult;
|
|
177
|
+
/**
|
|
178
|
+
* Reload a candidate against the selected canonical contract. Complete input
|
|
179
|
+
* takes the normal one-pass validator (and therefore may materialize contract
|
|
180
|
+
* defaults); incomplete/invalid input uses the bounded partial contract and
|
|
181
|
+
* exposes only accepted semantic values.
|
|
182
|
+
*/
|
|
183
|
+
export declare function loadCanonicalArtifact(contractInput: unknown, candidateInput: unknown): CanonicalArtifactLoadResult;
|
|
184
|
+
/** Explicitly named alias for callers that pass a candidate object. */
|
|
185
|
+
export declare const loadCanonicalCandidate: typeof loadCanonicalArtifact;
|
|
186
|
+
/** Load a JSON representation through the canonical contract boundary. */
|
|
187
|
+
export declare function loadCanonicalJsonArtifact(contractInput: unknown, input: unknown): CanonicalArtifactLoadResult;
|
|
188
|
+
/** Load native Markdown through the same parser and canonical contract. */
|
|
189
|
+
export declare function loadCanonicalMarkdownArtifact(contractInput: unknown, body: string | null | undefined): CanonicalArtifactLoadResult;
|
|
190
|
+
/** Existing-body spelling retained so read/repair callers share one boundary. */
|
|
191
|
+
export declare function loadCanonicalExistingArtifact(contractInput: unknown, body: string | null | undefined): CanonicalArtifactLoadResult;
|
|
192
|
+
/** Classify an artifact input envelope without applying semantic defaults. */
|
|
193
|
+
export declare function validatePartialArtifactInput(contractInput: unknown, input: unknown): PartialSemanticValidationResult;
|
|
194
|
+
/** Terminology alias for callers that treat validation as classification. */
|
|
195
|
+
export declare const classifyPartialArtifactInput: typeof validatePartialArtifactInput;
|
|
196
|
+
/** Merge only a targeted field patch into a prior stateless partial result. */
|
|
197
|
+
export declare function repairPartialArtifactInput(contractInput: unknown, previous: unknown, patch?: unknown): PartialSemanticRepairResult;
|
|
198
|
+
/** Terminology alias for callers that describe targeted repair as a merge. */
|
|
199
|
+
export declare const mergePartialArtifactInput: typeof repairPartialArtifactInput;
|
|
92
200
|
export declare function renderIssueArtifact(contractInput: unknown, input: unknown): string;
|
|
93
201
|
export declare function renderPullRequestArtifact(contractInput: unknown, input: unknown): string;
|
|
94
202
|
/** Construct the only values accepted by the GitHub mutation adapter. */
|
|
@@ -96,6 +204,14 @@ export declare function prepareIssueArtifact(contractInput: unknown, input: Arti
|
|
|
96
204
|
export declare function preparePullRequestArtifact(contractInput: unknown, input: ArtifactInputDocument): PreparedPullRequestArtifact;
|
|
97
205
|
export declare function parseExistingIssueArtifact(contractInput: unknown, body: string | null | undefined): ExistingArtifactParseResult;
|
|
98
206
|
export declare function parseExistingPullRequestArtifact(contractInput: unknown, body: string | null | undefined): ExistingArtifactParseResult;
|
|
207
|
+
/**
|
|
208
|
+
* Recover field values from a malformed or wrong-template body without
|
|
209
|
+
* weakening the strict existing-artifact parser. The section boundaries and
|
|
210
|
+
* field decoding are the same parser primitives used by strict parsing; only
|
|
211
|
+
* the order/complete-structure requirement is relaxed for an explicitly
|
|
212
|
+
* selected repair target.
|
|
213
|
+
*/
|
|
214
|
+
export declare function recoverExistingArtifactValues(contractInput: unknown, body: string | null | undefined): RecoverableArtifactValues;
|
|
99
215
|
export declare function validateExistingIssueArtifact(contractInput: unknown, body: string | null | undefined): ExistingArtifactValidationResult;
|
|
100
216
|
export declare function validateExistingPullRequestArtifact(contractInput: unknown, body: string | null | undefined): ExistingArtifactValidationResult;
|
|
101
217
|
export interface ExistingArtifactCandidate {
|