aimship 0.1.0-preview.12 → 0.1.0-preview.13

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/README.md CHANGED
@@ -43,7 +43,7 @@ Confirm npm's package installation prompt. `@preview` selects the published prev
43
43
  To install an exact published version, for example:
44
44
 
45
45
  ```sh
46
- npx aimship@0.1.0-preview.7 install --host codex
46
+ npx aimship@0.1.0-preview.13 install --host codex
47
47
  ```
48
48
 
49
49
  If you already have an Aimship `.tgz` package, replace `VERSION` with its actual version and run from the directory containing it:
package/README.zh-CN.md CHANGED
@@ -43,7 +43,7 @@ npx aimship@preview install --host codex --host claude-code
43
43
  安装指定的已发布版本,例如:
44
44
 
45
45
  ```sh
46
- npx aimship@0.1.0-preview.7 install --host codex
46
+ npx aimship@0.1.0-preview.13 install --host codex
47
47
  ```
48
48
 
49
49
  如果已有 Aimship 的 `.tgz` 安装包,将 `VERSION` 替换为实际版本号,在包所在目录执行:
package/lib/documents.mjs CHANGED
@@ -60,7 +60,10 @@ export const numberedIds = text => [...new Set(markdownText(text).match(new RegE
60
60
  // create a second local definition or a namespace/index.
61
61
  function qualifiedCitations(text) {
62
62
  const references=[];
63
- const local=markdownText(text).replace(/\[([^\]\n]*)\]\(([^()\s]+\.md)(?:#([^()\s]+))?\)/gi,(match,label,file,fragment)=>{
63
+ // A displayed link-syntax example is not a link. Keep ordinary `REQ-001`
64
+ // references visible to the number check.
65
+ const prose=markdownText(text).replace(/(`+)([^\n]*?)\1/g,(span,ticks,body)=>/\[[^\]]*\]\(/.test(body)?' '.repeat(span.length):span);
66
+ const local=prose.replace(/\[([^\]\n]*)\]\(([^()\s]+\.md)(?:#([^()\s]+))?\)/gi,(match,label,file,fragment)=>{
64
67
  const locator=fragment??label.trim(),target=`${file}#${locator}`;
65
68
  if (!new RegExp('^'+ID+'$').test(locator)) return match;
66
69
  references.push({target,locator});
@@ -68,10 +71,20 @@ function qualifiedCitations(text) {
68
71
  });
69
72
  return {references,local};
70
73
  }
71
- export function definitions(text, file) {
72
- const lines=markdownText(text).split('\n'), result=[];
74
+ const definitionSections={REQ:['requirements','adoption'],AC:['acceptance'],B:['batches'],TASK:['tasks'],TC:['cases']};
75
+ const referenceHeading=title=>/\b(?:coverage|summary|references|conclusion|notes)\b|覆盖|总结|汇总|引用|结论|备注/i.test(title);
76
+ export function definitions(text, file, spec) {
77
+ const lines=markdownText(text).split('\n'), result=[], context=[];
78
+ const areas=spec?sections(text,spec):[];
79
+ let offset=0;
73
80
  for(let i=0;i<lines.length;i++) {
74
- const line=lines[i], structured=/^\s*(?:\||#{1,6}\s+|[-*+]\s+)/.test(line);
81
+ const line=lines[i], start=offset; offset+=line.length+1;
82
+ const heading=/^ {0,3}(#{1,6})[ \t]+(.+)$/.exec(line);
83
+ if(heading) {
84
+ while(context.length && context.at(-1).level>=heading[1].length)context.pop();
85
+ context.push({level:heading[1].length,title:heading[2]});
86
+ }
87
+ const structured=/^\s*(?:\||#{1,6}\s+|[-*+]\s+)/.test(line);
75
88
  if(!structured && !new RegExp('^'+ID+'[::]').test(line)) continue;
76
89
  const candidate=line.trim().replace(/^\|\s*/, '').replace(/^(?:#{1,6}\s+|[-*+]\s+)/,'').replace(/^[*`]+/,'');
77
90
  const match=new RegExp('^('+ID+')(?![A-Za-z0-9_-])(?:[*`]*)(?:\\s*[|::—–-]\\s*|\\s+|$)(.*)$').exec(candidate);
@@ -84,9 +97,16 @@ export function definitions(text, file) {
84
97
  body+='\n'+lines[j];
85
98
  }
86
99
  }
87
- result.push({id:match[1],file,body,refs:numberedIds(body).filter(id=>id!==match[1])});
100
+ const primary=areas.some(area=>definitionSections[match[1].split('-')[0]]?.includes(area.id) && start>=area.start && start<area.end);
101
+ result.push({id:match[1],file,body,refs:numberedIds(body).filter(id=>id!==match[1]),primary,reference:context.some(h=>referenceHeading(h.title))});
88
102
  }
89
- return result;
103
+ // Definitions remain unique in their existing owning sections. Repeating an
104
+ // established number in a summary, coverage table or execution log cites it.
105
+ // Unstructured sources use their ordinary summary/coverage headings; two
106
+ // substantive definitions elsewhere are still a conflict, never first-wins.
107
+ return result.filter(d=>!result.some(other=>other.id===d.id && other!==d &&
108
+ ((!d.primary && other.primary) || (d.primary===other.primary && d.reference && !other.reference))))
109
+ .map(({primary,reference,...record})=>record);
90
110
  }
91
111
  export function meaningful(text) {
92
112
  const body=markdownText(text).replace(new RegExp(ID,'g'),'').replace(/[\s|:*`_#.—–-]/g,'');
@@ -96,7 +116,7 @@ export function meaningful(text) {
96
116
  // A fragment is a search locator, not a renderer-dependent hyperlink anchor.
97
117
  export function hasLocator(text, locator, spec) {
98
118
  if(spec && spec.sections.includes(locator)) return sections(text,spec).find(s=>s.id===locator)?.count===1;
99
- if(new RegExp('^'+ID+'$').test(locator)) return definitions(text,'').filter(d=>d.id===locator).length===1;
119
+ if(new RegExp('^'+ID+'$').test(locator)) return definitions(text,'',spec).filter(d=>d.id===locator).length===1;
100
120
  return headings(text).filter(h=>h.title===locator || h.key===normalizeHeading(locator)).length===1;
101
121
  }
102
122
  export function unknownConditions(policy) {
@@ -153,7 +173,7 @@ export async function inspectDocuments(directory, state) {
153
173
  if(record.count===1 && !record.body) issues.push(`${doc.path}: empty section ${record.id}.`);
154
174
  }
155
175
  const owned={prd:['REQ','AC','PAGE'],scope:['REQ','AC','PAGE'],plan:['B','TASK'],testing:['TC','RUN'],review:['REV'],'change-log':['CHG']}[doc.kind]??[];
156
- defs.push(...definitions(text, doc.path).filter(d=>owned.includes(d.id.split('-')[0]) || d.id.startsWith('Q-')));
176
+ defs.push(...definitions(text, doc.path, spec).filter(d=>owned.includes(d.id.split('-')[0]) || d.id.startsWith('Q-')));
157
177
  }
158
178
  }
159
179
  const runs = state.stageRuns;
@@ -214,7 +234,8 @@ export async function inspectDocuments(directory, state) {
214
234
  for(const {target,locator} of citations.references) {
215
235
  try {
216
236
  const source=await safeRead(directory,state,decodeURI(target));
217
- const records=source===null?[]:definitions(source,target.split('#')[0]).filter(d=>d.id===locator);
237
+ const sourcePath=decodeURI(target).split('#')[0], registered=docs.find(d=>d.path===sourcePath && d.mode==='new');
238
+ const records=source===null?[]:definitions(source,sourcePath,map.documents[registered?.kind]).filter(d=>d.id===locator);
218
239
  if(records.length!==1 || !meaningful(records[0].body)) issues.push(`${doc.path}: missing, ambiguous or empty source locator ${target}.`);
219
240
  } catch { issues.push(`${doc.path}: unreadable source citation ${target}.`); }
220
241
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aimship",
3
- "version": "0.1.0-preview.12",
3
+ "version": "0.1.0-preview.13",
4
4
  "description": "Explicit, goal-driven delivery workflow for coding agents",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,7 +22,7 @@ Use `tech-design.md`. HTTP changes use `openapi.yaml` or the registered engineer
22
22
 
23
23
  Use readable IDs for different entities: REQ for requirements, AC for acceptance, TASK/B for implementation, TC for cases, REV/RUN for review/execution records, and CHG/Q/PAGE where useful. Start each kind at 001. Keep the same obligation's ID across documents; do not give different entities the same ID. Users should be able to search an ID in ordinary Markdown. Do not require hyperlinks or any reader's HTML support.
24
24
 
25
- Define each ID once in its owning document, in a table's first column, a heading or a bullet, with substantive content: REQ/AC and optional PAGE mappings in PRD or Scope, TASK/B in plan, TC/RUN in testing, REV in review, CHG in change log. Other documents may cite those numbers in prose or tables; these citations do not redefine them. Q records may be defined where the question is resolved. For example:
25
+ Define each ID once in its owning document, in a table's first column, a heading or a bullet, with substantive content: REQ/AC and optional PAGE mappings in PRD or Scope, TASK/B in plan, TC/RUN in testing, REV in review, CHG in change log. Put requirements, acceptance, batches, tasks and cases in their existing corresponding sections. The same document's coverage, summaries and execution records, as well as other documents, may cite those numbers in prose or tables without redefining them. Q records may be defined where the question is resolved. For example:
26
26
 
27
27
  ```markdown
28
28
  | ID | Requirement | Acceptance |
@@ -22,4 +22,4 @@ Use [the shared core](../core.md) for state, evidence and continuation rules. Re
22
22
 
23
23
  Use plan.md. Preserve the ordinary template headings and section order. Follow [document patterns](../document-patterns.md) and the single [artifact map](../artifact-map.json). Keep this run independent even when its document is shared. New runs need a precise result location; adopted work is not a newly executed stage.
24
24
 
25
- Update TASK/B status and actual execution in the existing plan.md, preserving planned versus actual and code versions. Do not generate implementation.md.
25
+ Update TASK/B status and actual execution in plan.md's execution section, citing the existing task/batch numbers. Keep approved task definitions unchanged unless the plan itself changes; preserve planned versus actual and code versions. Do not generate implementation.md.
@@ -12,7 +12,7 @@ B ID, goal, dependencies and integration arrangement. Replace guidance with actu
12
12
 
13
13
  ## Tasks and completion criteria
14
14
 
15
- TASK, batch, REQ/AC or risk, repository ID, file/module, planned change, completion criteria, status, artifact ref. Replace guidance with actual content; explain inapplicability, never prefill a result.
15
+ TASK, batch, REQ/AC or risk, repository ID, file/module, planned change and completion criteria. Replace guidance with actual content; explain inapplicability, never prefill a result.
16
16
 
17
17
  ## Review and independent verification arrangement
18
18
 
@@ -20,7 +20,7 @@ Each batch review, overall review then independent verification; no per-batch fu
20
20
 
21
21
  ## Task status and execution records
22
22
 
23
- Actual changes and object versions by TASK/B; preserve original plan and distinguish pre-existing changes. Replace guidance with actual content; explain inapplicability, never prefill a result.
23
+ Current status, actual changes, artifact references and object versions by existing TASK/B; preserve the approved tasks above and distinguish pre-existing changes. Record progress here, for example a table of Task | Status | Actual result. Replace guidance with actual content; explain inapplicability, never prefill a result.
24
24
 
25
25
  ## Deviations, blockers and remaining work
26
26