gh-inari 0.8.0 → 0.9.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 +1 -1
- package/README.md +15 -9
- package/dist/artifact.d.ts +29 -2
- package/dist/artifact.js +266 -26
- package/dist/artifact.js.map +1 -1
- package/dist/cli.js +200 -28
- 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 +4 -0
- package/dist/contract/ir.js +17 -1
- package/dist/contract/ir.js.map +1 -1
- package/dist/contract/issue-form.js +2 -2
- package/dist/contract/issue-form.js.map +1 -1
- package/dist/contract/issue-reference.d.ts +58 -0
- package/dist/contract/issue-reference.js +157 -0
- package/dist/contract/issue-reference.js.map +1 -0
- package/dist/contract/schema.d.ts +4 -0
- package/dist/contract/schema.js +42 -1
- package/dist/contract/schema.js.map +1 -1
- package/dist/contract/validation.d.ts +1 -1
- package/dist/contract/validation.js +1 -1
- package/dist/contract/validation.js.map +1 -1
- package/dist/github/adapter.d.ts +2 -0
- package/dist/github/adapter.js +80 -32
- package/dist/github/adapter.js.map +1 -1
- package/dist/github/types.d.ts +7 -0
- package/dist/governance.js +2 -0
- package/dist/governance.js.map +1 -1
- package/dist/reconciliation.d.ts +11 -8
- package/dist/reconciliation.js +170 -30
- package/dist/reconciliation.js.map +1 -1
- package/dist/semantic-template.js +7 -1
- package/dist/semantic-template.js.map +1 -1
- package/dist/skill.js +55 -21
- package/dist/skill.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inari",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Governed GitHub Issue/PR/template workflows via the inari CLI. Prefer inari over raw gh for operations it owns; use inari skill for operational playbooks.",
|
|
5
5
|
"skills": "skills/inari"
|
|
6
6
|
}
|
package/README.md
CHANGED
|
@@ -166,8 +166,8 @@ inari issue get <number> [--template <template>] --json
|
|
|
166
166
|
inari pr get <number> [--template <template>] --json
|
|
167
167
|
inari issue check <number> [--template <template>]
|
|
168
168
|
inari pr check <number> [--template <template>]
|
|
169
|
-
inari issue edit <number> --from patch.json [--dry-run]
|
|
170
|
-
inari pr edit <number> --from patch.json [--dry-run]
|
|
169
|
+
inari issue edit <number> [--from patch.json] [--field name=value] [--title title] [--dry-run]
|
|
170
|
+
inari pr edit <number> [--from patch.json] [--field name=value] [--title title] [--base branch] [--maintainer-can-modify] [--dry-run]
|
|
171
171
|
inari issue normalize <number> [--dry-run]
|
|
172
172
|
inari pr normalize <number> [--dry-run]
|
|
173
173
|
inari issue sync <number> --from desired.json [--dry-run]
|
|
@@ -184,12 +184,14 @@ inari pr sync <number> --from desired.json [--dry-run]
|
|
|
184
184
|
}
|
|
185
185
|
```
|
|
186
186
|
|
|
187
|
-
The `fields` object is the semantic input contract shown by `schema
|
|
187
|
+
The `fields` object is the semantic input contract shown by `schema`; the same schema output exposes the separate required create metadata schema. Issue creation also accepts `assignees`; pull request creation accepts `head`, `base`, `draft`, and `maintainerCanModify`. Caller-supplied `title` metadata is required for both create commands, and `--title`, `--head`, and `--base` override envelope metadata. Existing `edit` commands use the remote artifact as their patch base: `--title` is supported for Issues and pull requests, while pull requests also support `--base` and `--maintainer-can-modify`; `--draft` is rejected for edit because pull-request PATCH does not accept it. Omitted values are preserved and unsupported or immutable metadata is rejected.
|
|
188
188
|
|
|
189
189
|
`pr sync --from` accepts a complete pull-request desired-state envelope. Use
|
|
190
190
|
`inari pr sync --help` for the top-level contract, or
|
|
191
191
|
`inari pr schema <template> --json` for its machine-readable `syncInput.schema`
|
|
192
192
|
and a valid `syncInput.minimalExample`.
|
|
193
|
+
`issue sync --from` overlays supplied semantic fields and metadata onto the
|
|
194
|
+
current artifact, preserving values omitted from the input.
|
|
193
195
|
|
|
194
196
|
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`.
|
|
195
197
|
|
|
@@ -211,18 +213,22 @@ boilerplate and raw Markdown are intentionally absent from successful output.
|
|
|
211
213
|
Existing artifact remediation uses one semantic pipeline for both Issues and
|
|
212
214
|
pull requests. `check` is read-only and classifies an artifact as
|
|
213
215
|
`valid-current`, `non-canonical`, `semantically-invalid`, `unsupported`, or
|
|
214
|
-
`ambiguous`. `edit` applies
|
|
215
|
-
accepts raw Markdown as the mutation contract. `normalize` re-renders a
|
|
216
|
+
`ambiguous`. `edit` applies an explicit semantic/metadata patch from JSON or
|
|
217
|
+
direct CLI options; it never accepts raw Markdown as the mutation contract. `normalize` re-renders a
|
|
216
218
|
parseable, semantically valid artifact and fails closed when preservation is
|
|
217
|
-
not proven. `sync`
|
|
218
|
-
|
|
219
|
+
not proven. `issue sync` overlays its input onto the current canonical state,
|
|
220
|
+
while `pr sync` treats its input as the complete desired semantic state; both
|
|
221
|
+
reconcile the canonical projection deterministically. A successful no-op is
|
|
219
222
|
reported explicitly, and `--dry-run` returns a bounded semantic/rendered diff
|
|
220
|
-
|
|
223
|
+
plus the validated resulting fields, metadata, and canonical body without
|
|
224
|
+
calling a GitHub mutation.
|
|
221
225
|
|
|
222
226
|
## Source of truth and supported semantics
|
|
223
227
|
|
|
224
228
|
`.github/ISSUE_TEMPLATE/**` remains the Issue source of truth. For pull requests, Inari discovers GitHub's supported repository locations: `pull_request_template` files under the repository root, `docs/`, or `.github/`, plus `PULL_REQUEST_TEMPLATE/` directories under each location. Native PR template filenames and the `.md`/`.txt` extensions supported by Inari are matched case-insensitively. Other PR-template extension surfaces are intentionally unsupported in v1 and fail closed. Inari discovers and compiles those files; it does not replace them with a proprietary body schema. Supported Issue Form nodes are `input`, `textarea` (including native `render` code fences), single- and multi-select `dropdown`, `checkboxes`, and `markdown`. Browser-only or ambiguous behavior, such as uploads or unsupported textarea rendering modes, fails closed. Markdown nodes are retained for contract/schema explainability but never emitted into an Issue body.
|
|
225
229
|
|
|
230
|
+
Issue dependencies are a separate, template-independent semantic object. Structured Issue envelopes may provide `dependencies.blockedBy` and `dependencies.blocks`; each reference is the canonical `{ "repositoryHost": "github.com", "repositoryId": "<decimal REST repository database id>", "repository": "owner/name", "number": N }` identity. `repositoryHost` plus `repositoryId` is authoritative: the host/install boundary prevents IDs from different GH_HOST/GHES installations colliding. Within one host, rename/transfer preserves the repository identity tuple and changes only the optional locator; cross-host migration is a different identity. The GitHub adapter obtains this decimal ID from the REST repository endpoint through `gh api`, including for repository overrides through a read-only identity lookup; a context that cannot obtain it does not synthesize one from owner/name. Inari sorts and validates these references (including duplicate, self, malformed, and contradictory declarations) before rendering. Non-empty dependencies are preserved in a bounded reserved body marker and projected back as normalized JSON; ordinary Markdown and GitHub-native dependency metadata are never inferred as semantic input. GitHub-native dependency state is not currently mutated by Inari, so there is no competing authority or implicit drift reconciliation.
|
|
231
|
+
|
|
226
232
|
Native PR Markdown expresses structure but not policy. A small versioned overlay may add constraints unavailable in Markdown without changing section order or content. The supported v1 form is:
|
|
227
233
|
|
|
228
234
|
```yaml
|
|
@@ -254,7 +260,7 @@ templates:
|
|
|
254
260
|
|
|
255
261
|
Template and section bindings are deterministic. Stale, unknown, or ambiguous template/section references fail closed. `linkedIssue: true` means that the field contains a GitHub closing reference: `close`, `closes`, `closed`, `fix`, `fixes`, `fixed`, `resolve`, `resolves`, or `resolved`, followed by `#ISSUE-NUMBER` or `OWNER/REPOSITORY#ISSUE-NUMBER`, with an optional colon and case-insensitive keyword. This validates syntax only; GitHub applies automatic linking/closure only under its own contextual rules, including the target default branch.
|
|
256
262
|
|
|
257
|
-
Issue Form top-level `title` is
|
|
263
|
+
Issue Form top-level `title` is a fixed native prefix for create validation, but it does not satisfy the caller's required title metadata by itself. An explicit caller title is used as supplied without inferred prefix concatenation or automatic generation. Top-level `labels` are repository-governed defaults and are always retained; caller-supplied labels are appended in order with duplicates removed. Top-level `assignees`, `projects`, and `type`, and upload fields remain unsupported and fail closed rather than being approximated.
|
|
258
264
|
|
|
259
265
|
## Scope
|
|
260
266
|
|
package/dist/artifact.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type PartialSemanticValidationResult, type PartialSemanticRepairResult, type SemanticValidationResult, type SemanticViolation } from "./contract/validation.js";
|
|
2
2
|
import { type ArtifactDiagnostic, type ArtifactDiagnosticReport } from "./diagnostics.js";
|
|
3
3
|
import { type ArtifactKind, type CanonicalContract } from "./contract/ir.js";
|
|
4
|
+
import { type IssueDependencies, type IssueReference } from "./contract/issue-reference.js";
|
|
4
5
|
import { type ValidatedRenderedIssueArtifact, type ValidatedRenderedPullRequestArtifact } from "./github/types.js";
|
|
5
6
|
export interface ArtifactInputMetadata {
|
|
6
7
|
readonly title?: string;
|
|
@@ -14,6 +15,8 @@ export interface ArtifactInputMetadata {
|
|
|
14
15
|
export interface ArtifactInputDocument {
|
|
15
16
|
readonly fields: Readonly<Record<string, unknown>>;
|
|
16
17
|
readonly metadata: ArtifactInputMetadata;
|
|
18
|
+
/** Generic Issue relationships, independent of template-specific fields. */
|
|
19
|
+
readonly dependencies?: IssueDependencies;
|
|
17
20
|
}
|
|
18
21
|
/**
|
|
19
22
|
* A representation-independent candidate entering the canonical contract.
|
|
@@ -26,6 +29,7 @@ export interface ArtifactCandidate {
|
|
|
26
29
|
readonly fields: unknown;
|
|
27
30
|
readonly metadata: ArtifactInputMetadata;
|
|
28
31
|
readonly source: ArtifactCandidateSource;
|
|
32
|
+
readonly dependencies?: IssueDependencies;
|
|
29
33
|
}
|
|
30
34
|
export interface ArtifactCandidateAdapterResult {
|
|
31
35
|
readonly parsed: boolean;
|
|
@@ -48,13 +52,14 @@ export interface CanonicalArtifactLoadResult {
|
|
|
48
52
|
readonly invalidFields: PartialSemanticValidationResult["invalidFields"];
|
|
49
53
|
readonly diagnostics: ArtifactDiagnosticReport;
|
|
50
54
|
readonly violations: readonly SemanticViolation[];
|
|
55
|
+
readonly dependencies?: IssueDependencies;
|
|
51
56
|
}
|
|
52
57
|
export interface ArtifactMetadataViolation {
|
|
53
58
|
readonly code: "INPUT_METADATA_INVALID";
|
|
54
59
|
readonly path: string;
|
|
55
60
|
readonly message: string;
|
|
56
61
|
}
|
|
57
|
-
export type ArtifactInputErrorCode = "INPUT_DOCUMENT_INVALID" | "INPUT_METADATA_INVALID";
|
|
62
|
+
export type ArtifactInputErrorCode = "INPUT_DOCUMENT_INVALID" | "INPUT_METADATA_INVALID" | "INPUT_DEPENDENCIES_INVALID";
|
|
58
63
|
export declare class ArtifactInputError extends Error {
|
|
59
64
|
readonly code: ArtifactInputErrorCode;
|
|
60
65
|
readonly path: string;
|
|
@@ -92,6 +97,9 @@ export interface ExistingArtifactDiagnostic {
|
|
|
92
97
|
export interface ExistingArtifactParseResult {
|
|
93
98
|
readonly parsed: boolean;
|
|
94
99
|
readonly values: Readonly<Record<string, unknown>>;
|
|
100
|
+
readonly dependencies?: IssueDependencies;
|
|
101
|
+
/** Raw dependency declaration retained for the semantic validation boundary. */
|
|
102
|
+
readonly dependencyInput?: unknown;
|
|
95
103
|
readonly diagnostics: readonly ExistingArtifactDiagnostic[];
|
|
96
104
|
}
|
|
97
105
|
/**
|
|
@@ -101,6 +109,7 @@ export interface ExistingArtifactParseResult {
|
|
|
101
109
|
*/
|
|
102
110
|
export interface RecoverableArtifactValues {
|
|
103
111
|
readonly values: Readonly<Record<string, unknown>>;
|
|
112
|
+
readonly dependencies?: IssueDependencies;
|
|
104
113
|
readonly diagnostics: readonly ExistingArtifactDiagnostic[];
|
|
105
114
|
}
|
|
106
115
|
export interface ExistingArtifactValidationResult {
|
|
@@ -115,6 +124,8 @@ export interface ExistingIssueReader {
|
|
|
115
124
|
getIssue(issueNumber: number): Promise<{
|
|
116
125
|
readonly body: string | null;
|
|
117
126
|
readonly url: string;
|
|
127
|
+
readonly repositoryId?: string;
|
|
128
|
+
readonly repositoryHost?: string;
|
|
118
129
|
}>;
|
|
119
130
|
}
|
|
120
131
|
export interface ExistingPullRequestReader {
|
|
@@ -132,6 +143,7 @@ export interface ExistingPullRequestReader {
|
|
|
132
143
|
* repository governance/provenance that resolves the actual contract.
|
|
133
144
|
*/
|
|
134
145
|
export declare const TEMPLATE_IDENTITY_MARKER_VERSION: "1";
|
|
146
|
+
export declare const ISSUE_DEPENDENCY_MARKER_VERSION: "1";
|
|
135
147
|
export interface TemplateIdentityMarker {
|
|
136
148
|
readonly version: string;
|
|
137
149
|
readonly kind: ArtifactKind;
|
|
@@ -144,6 +156,18 @@ export interface TemplateIdentityMarkerExtraction {
|
|
|
144
156
|
/** Body with a recognized trailing marker line removed; unchanged when none is present. */
|
|
145
157
|
readonly body: string;
|
|
146
158
|
}
|
|
159
|
+
export type IssueDependencyMarkerStatus = "absent" | "valid" | "malformed" | "unsupported-version";
|
|
160
|
+
export interface IssueDependencyMarkerExtraction {
|
|
161
|
+
readonly status: IssueDependencyMarkerStatus;
|
|
162
|
+
readonly dependencies?: IssueDependencies;
|
|
163
|
+
/** Body with a recognized trailing dependency marker removed. */
|
|
164
|
+
readonly body: string;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Read only the reserved trailing dependency marker emitted by Inari. No
|
|
168
|
+
* ordinary Markdown is interpreted as a relationship declaration.
|
|
169
|
+
*/
|
|
170
|
+
export declare function extractIssueDependencyMarker(body: string): IssueDependencyMarkerExtraction;
|
|
147
171
|
/**
|
|
148
172
|
* Recognize and remove a trailing template identity marker line without
|
|
149
173
|
* applying semantic parsing. Only a line starting with the exact reserved
|
|
@@ -212,7 +236,7 @@ export declare function parseExistingPullRequestArtifact(contractInput: unknown,
|
|
|
212
236
|
* selected repair target.
|
|
213
237
|
*/
|
|
214
238
|
export declare function recoverExistingArtifactValues(contractInput: unknown, body: string | null | undefined): RecoverableArtifactValues;
|
|
215
|
-
export declare function validateExistingIssueArtifact(contractInput: unknown, body: string | null | undefined): ExistingArtifactValidationResult;
|
|
239
|
+
export declare function validateExistingIssueArtifact(contractInput: unknown, body: string | null | undefined, subject?: IssueReference): ExistingArtifactValidationResult;
|
|
216
240
|
export declare function validateExistingPullRequestArtifact(contractInput: unknown, body: string | null | undefined): ExistingArtifactValidationResult;
|
|
217
241
|
export interface ExistingArtifactCandidate {
|
|
218
242
|
readonly contract: CanonicalContract;
|
|
@@ -227,6 +251,7 @@ export interface ExistingArtifactProjection {
|
|
|
227
251
|
readonly projection: "canonical" | "unavailable";
|
|
228
252
|
readonly classification: ExistingArtifactClassification;
|
|
229
253
|
readonly fields?: Readonly<Record<string, unknown>>;
|
|
254
|
+
readonly dependencies?: IssueDependencies;
|
|
230
255
|
readonly diagnostics: readonly ExistingArtifactDiagnostic[];
|
|
231
256
|
readonly violations?: readonly SemanticViolation[];
|
|
232
257
|
readonly attemptedTemplates?: readonly string[];
|
|
@@ -239,6 +264,8 @@ export declare function selectExistingArtifactCandidate(candidates: readonly Exi
|
|
|
239
264
|
export declare function validateRequiredMetadataString(value: unknown, key: string): ArtifactMetadataViolation | undefined;
|
|
240
265
|
export declare function validateExistingIssueFromAdapter(reader: ExistingIssueReader, contract: unknown, issueNumber: number): Promise<FetchedExistingArtifact>;
|
|
241
266
|
export declare function validateExistingPullRequestFromAdapter(reader: ExistingPullRequestReader, contract: unknown, pullRequestNumber: number): Promise<FetchedExistingArtifact>;
|
|
267
|
+
/** @internal Validate the canonical Issue metadata handoff before mutation. */
|
|
268
|
+
export declare function verifyIssueMetadataRoundTrip(expected: Readonly<Record<string, unknown>>, artifact: ValidatedRenderedIssueArtifact): void;
|
|
242
269
|
/** Escape only Markdown constructs that could change the canonical section structure. */
|
|
243
270
|
export declare function escapeMarkdownValue(value: string): string;
|
|
244
271
|
export declare function removeHtmlComments(value: string): string;
|