gmc-openspec 1.4.1 → 1.4.3

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.
@@ -111,6 +111,7 @@ export function registerJiraCommand(program) {
111
111
  issueDir: intakeResult.issueDir,
112
112
  intakePath: intakeResult.path,
113
113
  status,
114
+ documentLanguage: intakeResult.intake?.documentLanguage,
114
115
  allowedNext: status ? getAllowedNext(status) : [],
115
116
  nextCommands: status ? getNextCommands(status, jiraId.toUpperCase()) : [],
116
117
  blockingStage,
@@ -4,6 +4,8 @@ export declare const JIRA_CONFIG_VERSION = 1;
4
4
  export declare const JIRA_INTAKE_SCHEMA_VERSION = 1;
5
5
  export declare const JIRA_DEFAULT_PROVIDER = "atlassian-rovo";
6
6
  export declare const JIRA_DEFAULT_ENDPOINT = "https://mcp.atlassian.com/v1/mcp/authv2";
7
+ export declare const JIRA_DOCUMENT_LANGUAGES: readonly ["en", "zh-CN"];
8
+ export type JiraDocumentLanguage = (typeof JIRA_DOCUMENT_LANGUAGES)[number];
7
9
  export declare const JIRA_WORKFLOW_IDS: readonly ["jira-import", "jira-refine", "jira-review", "jira-split", "jira-propose", "jira-sync"];
8
10
  export type JiraWorkflowId = (typeof JIRA_WORKFLOW_IDS)[number];
9
11
  export declare const JIRA_WORKFLOW_TO_SKILL_DIR: Record<JiraWorkflowId, string>;
@@ -4,6 +4,7 @@ export const JIRA_CONFIG_VERSION = 1;
4
4
  export const JIRA_INTAKE_SCHEMA_VERSION = 1;
5
5
  export const JIRA_DEFAULT_PROVIDER = 'atlassian-rovo';
6
6
  export const JIRA_DEFAULT_ENDPOINT = 'https://mcp.atlassian.com/v1/mcp/authv2';
7
+ export const JIRA_DOCUMENT_LANGUAGES = ['en', 'zh-CN'];
7
8
  export const JIRA_WORKFLOW_IDS = [
8
9
  'jira-import',
9
10
  'jira-refine',
@@ -13,6 +13,10 @@ export declare const JiraIntakeSchema: z.ZodObject<{
13
13
  proposed: "proposed";
14
14
  synced: "synced";
15
15
  }>>;
16
+ documentLanguage: z.ZodDefault<z.ZodEnum<{
17
+ en: "en";
18
+ "zh-CN": "zh-CN";
19
+ }>>;
16
20
  sourceHashSha256: z.ZodOptional<z.ZodString>;
17
21
  allowedNext: z.ZodOptional<z.ZodArray<z.ZodEnum<{
18
22
  split: "split";
@@ -2,13 +2,14 @@ import { existsSync, readFileSync } from 'fs';
2
2
  import path from 'path';
3
3
  import { parse as parseYaml } from 'yaml';
4
4
  import { z } from 'zod';
5
- import { JIRA_ALLOWED_NEXT, JIRA_INTAKE_SCHEMA_VERSION, JIRA_STATUS_ORDER, } from './constants.js';
5
+ import { JIRA_ALLOWED_NEXT, JIRA_DOCUMENT_LANGUAGES, JIRA_INTAKE_SCHEMA_VERSION, JIRA_STATUS_ORDER, } from './constants.js';
6
6
  import { getJiraIssueDir, normalizeJiraId } from './paths.js';
7
7
  export const JiraIntakeSchema = z
8
8
  .object({
9
9
  schemaVersion: z.number().int().positive().default(JIRA_INTAKE_SCHEMA_VERSION),
10
10
  jira: z.string().min(1),
11
11
  status: z.enum(JIRA_STATUS_ORDER).default('imported'),
12
+ documentLanguage: z.enum(JIRA_DOCUMENT_LANGUAGES).default('en'),
12
13
  sourceHashSha256: z.string().optional(),
13
14
  allowedNext: z.array(z.enum(JIRA_STATUS_ORDER)).optional(),
14
15
  })
@@ -5,6 +5,8 @@ const SHARED_GUARDRAILS = `
5
5
  - Treat Jira as the business input source, not the final engineering specification.
6
6
  - Never create or modify \`openspec/changes/*\` directly from raw Jira description or comments.
7
7
  - Never modify \`source.md\`; it is a read-only Jira snapshot protected by \`sourceHashSha256\` in \`intake.yaml\`.
8
+ - Use \`intake.yaml\` \`documentLanguage\` for generated prose documents: \`en\` means English and \`zh-CN\` means Simplified Chinese.
9
+ - Keep structured YAML fields, status enum values, mapping keys, story IDs, requirement IDs, and traceability keys as stable English/code values regardless of \`documentLanguage\`.
8
10
  - Blocking questions must be answered before requirements can be marked reviewed.
9
11
  - Assumptions must be explicit in \`assumptions.md\` and approved before story split or OpenSpec proposal.
10
12
  - Keep \`mapping.yaml\` current so Jira AC maps to requirements, stories, and OpenSpec changes.
@@ -28,13 +30,16 @@ ${SHARED_GUARDRAILS}
28
30
  - Read summary, description, acceptance criteria, comments, linked issues, labels, components, and attachments metadata where available.
29
31
  - Use \`getJiraIssueRemoteIssueLinks\` and \`searchJiraIssuesUsingJql\` only when linked issues or related ticket lookup is needed.
30
32
  - Do not write to Jira.
31
- 2. Create \`jira/<JIRA-ID>-<slug>/\` using a short slug from the Jira summary.
32
- 3. Write \`source.md\` as an auditable snapshot with field names and source sections.
33
- 4. Compute SHA-256 of \`source.md\` and write \`intake.yaml\`:
34
- \`schemaVersion: 1\`, \`jira\`, \`status: imported\`, \`sourceHashSha256\`.
35
- 5. Write \`requirement-draft.md\` as a concise product requirement draft.
36
- 6. Write initial \`questions.md\`, \`assumptions.md\`, and \`mapping.yaml\` placeholders.
37
- 7. Run \`openspec jira validate <JIRA-ID> --stage source\` and report the result.
33
+ 2. Ask the user which document language to use for subsequent generated documents: English or Simplified Chinese. Default to English when the user has no preference.
34
+ - Record English as \`documentLanguage: en\`.
35
+ - Record Simplified Chinese as \`documentLanguage: zh-CN\`.
36
+ 3. Create \`jira/<JIRA-ID>-<slug>/\` using a short slug from the Jira summary.
37
+ 4. Write \`source.md\` as an auditable snapshot with field names and source sections. Preserve the original Jira text and do not translate \`source.md\`.
38
+ 5. Compute SHA-256 of \`source.md\` and write \`intake.yaml\`:
39
+ \`schemaVersion: 1\`, \`jira\`, \`status: imported\`, \`documentLanguage\`, \`sourceHashSha256\`.
40
+ 6. Write \`requirement-draft.md\` as a concise product requirement draft using \`documentLanguage\`.
41
+ 7. Write initial \`questions.md\` and \`assumptions.md\` using \`documentLanguage\`, plus \`mapping.yaml\` placeholders with stable English/code keys.
42
+ 8. Run \`openspec jira validate <JIRA-ID> --stage source\` and report the result.
38
43
 
39
44
  ## Output
40
45
 
@@ -52,14 +57,14 @@ ${SHARED_GUARDRAILS}
52
57
 
53
58
  ## Steps
54
59
 
55
- 1. Run \`openspec jira status <JIRA-ID> --json\` and read the intake folder.
60
+ 1. Run \`openspec jira status <JIRA-ID> --json\` and read the intake folder, including \`intake.yaml\` \`documentLanguage\`.
56
61
  2. Read \`source.md\`, \`requirement-draft.md\`, \`questions.md\`, \`assumptions.md\`, and \`mapping.yaml\`.
57
62
  3. Identify ambiguity as either:
58
63
  - **Blocking**: affects scope, AC, permissions, data contract, external behavior, or story boundaries.
59
64
  - **Non-Blocking**: can be captured as an explicit assumption.
60
- 4. Ask the user all blocking questions before proceeding. Update \`questions.md\` with statuses.
61
- 5. Record non-blocking assumptions in \`assumptions.md\`; do not hide assumptions in requirement prose.
62
- 6. When blocking questions are resolved, write \`requirement.md\` and set \`intake.yaml\` status to \`ready-for-review\`.
65
+ 4. Ask the user all blocking questions before proceeding. Update \`questions.md\` with statuses using \`documentLanguage\`.
66
+ 5. Record non-blocking assumptions in \`assumptions.md\` using \`documentLanguage\`; do not hide assumptions in requirement prose.
67
+ 6. When blocking questions are resolved, write \`requirement.md\` using \`documentLanguage\` and set \`intake.yaml\` status to \`ready-for-review\`.
63
68
  7. Run \`openspec jira validate <JIRA-ID> --stage requirement\`.
64
69
 
65
70
  ## Output
@@ -78,7 +83,7 @@ ${SHARED_GUARDRAILS}
78
83
 
79
84
  ## Steps
80
85
 
81
- 1. Read \`requirement.md\`, \`questions.md\`, and \`assumptions.md\`.
86
+ 1. Read \`intake.yaml\` to get \`documentLanguage\`, then read \`requirement.md\`, \`questions.md\`, and \`assumptions.md\`.
82
87
  2. Run \`openspec jira validate <JIRA-ID> --stage requirement --json\`.
83
88
  3. If validation fails, explain the blockers and return to \`/opsx:jira-refine\`.
84
89
  4. Ask the user to approve or request edits to the requirement and assumptions.
@@ -105,8 +110,8 @@ Each story must have independent review value, clear AC, scope, non-goals, depen
105
110
  ## Steps
106
111
 
107
112
  1. Run \`openspec jira validate <JIRA-ID> --stage requirement --json\`.
108
- 2. Read \`requirement.md\`, \`mapping.yaml\`, and existing OpenSpec specs if capability choices are unclear.
109
- 3. Write \`stories.md\` with story ids, titles, scope, non-goals, AC, dependencies, risks, and suggested OpenSpec change names.
113
+ 2. Read \`intake.yaml\` to get \`documentLanguage\`, plus \`requirement.md\`, \`mapping.yaml\`, and existing OpenSpec specs if capability choices are unclear.
114
+ 3. Write \`stories.md\` using \`documentLanguage\`, with stable English/code story ids, titles, scope, non-goals, AC, dependencies, risks, and suggested OpenSpec change names.
110
115
  4. Update \`mapping.yaml\` so every Jira AC maps to at least one story.
111
116
  5. Set \`intake.yaml\` status to \`split\` and ask the user to review the story split.
112
117
  6. After explicit user approval, set status to \`stories-reviewed\` and run \`openspec jira validate <JIRA-ID> --stage stories\`.
@@ -128,13 +133,13 @@ ${SHARED_GUARDRAILS}
128
133
  ## Steps
129
134
 
130
135
  1. Run \`openspec jira validate <JIRA-ID> --stage stories --json\`. Stop if it fails.
131
- 2. Read \`stories.md\`, \`mapping.yaml\`, and \`requirement.md\`.
136
+ 2. Read \`intake.yaml\` to get \`documentLanguage\`, plus \`stories.md\`, \`mapping.yaml\`, and \`requirement.md\`.
132
137
  3. For each non-deferred reviewed story, create exactly one OpenSpec change:
133
138
  \`openspec new change <jira-id>-<story-slug>\`.
134
139
  4. Generate artifacts through the existing OpenSpec flow:
135
140
  - Run \`openspec status --change <change> --json\`.
136
141
  - For each ready artifact, run \`openspec instructions <artifact> --change <change> --json\`.
137
- - Create \`proposal.md\`, delta specs, \`design.md\`, and \`tasks.md\` from the reviewed story and requirement, not raw Jira text.
142
+ - Create \`proposal.md\`, delta specs, \`design.md\`, and \`tasks.md\` using \`documentLanguage\` from the reviewed story and requirement, not raw Jira text.
138
143
  5. Update \`mapping.yaml\` so every story records its OpenSpec change and spec files.
139
144
  6. Set \`intake.yaml\` status to \`proposed\` and run \`openspec jira validate <JIRA-ID> --stage propose\`.
140
145
 
@@ -155,7 +160,11 @@ ${SHARED_GUARDRAILS}
155
160
  ## Writeback Rules
156
161
 
157
162
  - This is the only Jira intake workflow allowed to write to Jira.
158
- - Before any Jira comment, child issue creation, link update, or status change, show a concrete diff of the write.
163
+ - Child issue writeback is the default strategy for reviewed stories.
164
+ - For every non-deferred story missing \`stories.<storyId>.jiraIssueKey\` in \`mapping.yaml\`, the writeback plan MUST include a \`createJiraIssue\` operation.
165
+ - Do not create duplicate Jira child issues for stories that already have \`jiraIssueKey\`; plan only needed link, update, or status changes for those stories.
166
+ - Summary comment sync is optional. Do not include a Jira comment by default unless the user explicitly requests one, or there are no child issues to create.
167
+ - Before any child issue creation, link update, status change, field edit, or optional comment, show a concrete diff of the write.
159
168
  - Ask for explicit confirmation before each batch of writes.
160
169
  - If \`openspec/jira.yaml\` has \`writeback.enabled: false\`, ask the user to confirm this one-time sync before writing.
161
170
  - Use only the official Atlassian MCP Jira write tools needed for the confirmed diff: \`addCommentToJiraIssue\`, \`editJiraIssue\`, \`getTransitionsForJiraIssue\`, \`transitionJiraIssue\`, and \`createJiraIssue\`.
@@ -164,10 +173,15 @@ ${SHARED_GUARDRAILS}
164
173
 
165
174
  1. Run \`openspec jira validate <JIRA-ID> --stage propose --json\` when syncing proposed OpenSpec changes.
166
175
  2. Read \`mapping.yaml\`, \`stories.md\`, and current OpenSpec change status.
167
- 3. Prepare a writeback plan: comments, links, child issues, or status moves.
168
- 4. Show the diff and wait for explicit user approval.
169
- 5. Use the named Atlassian MCP write tools only after approval.
170
- 6. Update \`intake.yaml\` status to \`synced\` only after successful writeback.
176
+ 3. Identify all non-deferred reviewed stories and split them into:
177
+ - stories missing \`jiraIssueKey\`, which must be planned as Jira child issues;
178
+ - stories with \`jiraIssueKey\`, which must not be recreated.
179
+ 4. Prepare a child-issue-first writeback plan. For each \`createJiraIssue\`, show the Jira summary, issue type, parent/source issue, description or acceptance criteria, trace links, and corresponding OpenSpec change.
180
+ 5. Include an optional summary comment only when the user requested comment sync, or when there are no child issues to create.
181
+ 6. Show the full diff and wait for explicit user approval.
182
+ 7. Use the named Atlassian MCP write tools only after approval.
183
+ 8. After each successful \`createJiraIssue\`, update the matching \`stories.<storyId>.jiraIssueKey\` in \`mapping.yaml\`.
184
+ 9. Update \`intake.yaml\` status to \`synced\` only after successful writeback and local mapping updates.
171
185
 
172
186
  ## Output
173
187
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gmc-openspec",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "AI-native system for spec-driven development",
5
5
  "keywords": [
6
6
  "openspec",