specrails-core 6.7.0 → 6.7.1

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.
@@ -34,7 +34,7 @@ export function buildCliInvocation(provider, request, options = {}) {
34
34
  }
35
35
  const readOnly = requestPolicy(request).access === 'read';
36
36
  // Pin the product alias; explicit IDs remain reproducible across releases.
37
- const claudeModelIds = { opus: 'claude-opus-5-5', sonnet: 'claude-sonnet-5-5', haiku: 'claude-haiku-5-5' };
37
+ const claudeModelIds = { opus: 'claude-opus-5-5', sonnet: 'claude-sonnet-5-5', haiku: 'claude-haiku-5-5', fable: 'claude-fable-5-1' };
38
38
  const modelId = provider === 'claude' && request.model ? claudeModelIds[request.model] ?? request.model : request.model;
39
39
  const model = modelId ? ['--model', modelId] : [];
40
40
  const extraRoots = request.allowedRoots.filter(root => root !== request.cwd);
@@ -42,7 +42,7 @@ export declare const DERIVE_FEEDBACK_LIMIT = 8000;
42
42
  /** The deriver's task for one visit: change set, bases, summary, and the re-derivation and repair sections when they apply. */
43
43
  export declare function deriverTask(change: string, changeSetLines: string[], bases: Record<string, string>, summary: string, repair: string | undefined, feedback?: string): string;
44
44
  /**
45
- * Writes the OpenSpec change for a diff that already exists (Flow mode): the
45
+ * Writes the OpenSpec change for a diff that already exists (Intent mode, formerly Flow): the
46
46
  * `deriver` authors the artifacts, then Core measures coverage, completed tasks,
47
47
  * strict validation and the archive preflight itself. Coverage gaps never fail
48
48
  * the node; they reach the reviewer through derivation.json as issues.
@@ -130,7 +130,7 @@ function verificationProposals(structured) {
130
130
  return Array.isArray(structured?.verification) ? structured.verification.slice(0, VERIFICATION_PROPOSALS_LIMIT) : [];
131
131
  }
132
132
  /**
133
- * Writes the OpenSpec change for a diff that already exists (Flow mode): the
133
+ * Writes the OpenSpec change for a diff that already exists (Intent mode, formerly Flow): the
134
134
  * `deriver` authors the artifacts, then Core measures coverage, completed tasks,
135
135
  * strict validation and the archive preflight itself. Coverage gaps never fail
136
136
  * the node; they reach the reviewer through derivation.json as issues.
@@ -5,7 +5,7 @@ import type { DeveloperRecord } from './graph/state.js';
5
5
  import { type ClarificationPolicy } from './graph/clarifications.js';
6
6
  import type { ProjectRulesContext } from './project-rules.js';
7
7
  /** Bump whenever the wording changes: the version is part of the frozen run identity. */
8
- export declare const ROLE_INSTRUCTIONS_VERSION = "17";
8
+ export declare const ROLE_INSTRUCTIONS_VERSION = "18";
9
9
  export interface RoleFeedback {
10
10
  verification?: unknown;
11
11
  review?: unknown;
@@ -3,7 +3,7 @@ import { DEFAULT_REVIEW_POLICY, REVIEW_ASPECTS } from './graph/review-policy.js'
3
3
  import { REVIEW_BRIEF_RISK_LIMIT, REVIEW_BRIEF_SCHEMA, REVIEW_RISK_AREAS } from './graph/review-brief.js';
4
4
  import { CLARIFICATIONS_SCHEMA, CLARIFICATION_LIMIT, DEFAULT_CLARIFICATION_POLICY } from './graph/clarifications.js';
5
5
  /** Bump whenever the wording changes: the version is part of the frozen run identity. */
6
- export const ROLE_INSTRUCTIONS_VERSION = '17';
6
+ export const ROLE_INSTRUCTIONS_VERSION = '18';
7
7
  const OUTPUT_TAIL = 6_000;
8
8
  /** One senior engineer, rendered once per role prompt (never repeated inside it): the identity the implement pipeline's roles share. */
9
9
  const ENGINEER = 'a T-shaped principal engineer with decades of delivery across web, mobile and backend systems: deep in software design and testing, broad across product, UX, data, security, infrastructure and operations; fluent in hexagonal (ports and adapters) architecture, SOLID, design patterns, Clean Code, The Pragmatic Programmer, refactoring, legacy-code seams and AI-assisted development. You work for the user, the operator and the next maintainer, and you treat AI-generated code, including your own, with the scepticism owed to any untrusted contribution.';
@@ -279,6 +279,8 @@ function reviewerSection(policy, criteria, definition, adopted = false) {
279
279
  '8. What tests rarely catch: swallowed or context-free errors, missing cancellation, timeouts or cleanup, races and partial failures, retries without idempotency, empty, huge, malformed or boundary inputs, time zones and Unicode, secrets or personal data in logs, non-additive migrations or persisted-format changes, a removed guard or branch without a stated reason (understand before approving its removal), and artifacts the change made stale: localized strings in every locale the repository ships, documentation, schemas, configuration examples. Missing stale-artifact updates inside the planned blast radius are issues; concerns outside it are findings.',
280
280
  '9. Spec claims: for each capability this change touches (its delta specs under the change, and `openspec/specs/<capability>/spec.md` when it exists), compare what the requirements and scenarios claim with what the code does. A claim the code contradicts is a divergence for the brief (`divergences`), with the requirement and the observed behaviour at `file:line`. It is an issue only when this change introduced the contradiction.',
281
281
  '',
282
+ 'The Intent block a spec may carry (problem, outcome, hypothesis, success signals, open questions) is context, never a requirement: a hypothesis is validated with real users after the change ships, a success signal is measured then, and an open question is a decision the spec records. Never raise an issue because the change does not prove the hypothesis, does not measure a signal or leaves such a question open; mention it in `brief` at most. Issues name defects in the code, tests missing for an ADDED or MODIFIED requirement, or an artifact that contradicts the code. Approve when none remains.',
283
+ '',
282
284
  'Judge BEHAVIOUR against the acceptance criteria, never the shape of the code against the wording of the plan: module layout, file lists, class or function names, naming conventions and implementation techniques named in the ticket, the design or a "contract layer" are suggestions the developer may legitimately improve on. A working implementation that satisfies a criterion by other means is correct; asking to rename, move or rewrite it to match the plan\'s wording is NOT an issue. Only a criterion that is not met, a defect, a missing test or a regression is.',
283
285
  '',
284
286
  'Review THE CHANGE. The change set below lists every file this run changed relative to its base, measured by Core from git. Judge those changes and the behavior they affect; code the change did not touch is not an issue unless the change breaks it. Never ask for improvements to pre-existing code, other packages or workspaces, or configuration outside the change; asking to REVERT an edit this change introduced is always in scope. An environment problem (credentials, registry access, missing tools) is not a code issue: record it under findings, never as an issue for the fixer.',
@@ -281,6 +281,13 @@ declare function inspectReceipt(state: PipelineState, env?: NodeJS.ProcessEnv):
281
281
  reasons: string[];
282
282
  receipt?: VerificationReceipt;
283
283
  };
284
+ /**
285
+ * The requirement a spec without acceptance criteria freezes: its description
286
+ * minus the intent block. A hypothesis is validated with users after the
287
+ * change ships and its success signals are measured then; freezing them would
288
+ * make the reviewer demand evidence no code can give.
289
+ */
290
+ export declare function requirementFromDescription(description: string, title: string): string;
284
291
  /** The frozen requirements an acceptance report must certify, in scope order. */
285
292
  export declare function frozenAcceptanceCriteria(contextInput: unknown): Array<Pick<AcceptanceCriterion, 'specId' | 'criterionIndex' | 'requirement'>>;
286
293
  /** Validates a report against the frozen scope without recording it; throws the same errors `recordAcceptance` would. */
@@ -604,8 +604,26 @@ function taskGate(state) {
604
604
  }
605
605
  /** Stable indices refer to the frozen scope, never to rewritten design text.
606
606
  * When no explicit AC list exists, the frozen description is the requirement. */
607
+ /** Heading of the intent block a host prepends to a spec's description (Desktop
608
+ * `renderIntentForAgents`): why and outcome, never a requirement to certify. */
609
+ const INTENT_BLOCK_HEADING = /^## Intent \(/m;
610
+ /**
611
+ * The requirement a spec without acceptance criteria freezes: its description
612
+ * minus the intent block. A hypothesis is validated with users after the
613
+ * change ships and its success signals are measured then; freezing them would
614
+ * make the reviewer demand evidence no code can give.
615
+ */
616
+ export function requirementFromDescription(description, title) {
617
+ const start = description.search(INTENT_BLOCK_HEADING);
618
+ if (start === -1)
619
+ return description || title;
620
+ const rest = description.slice(start + 1);
621
+ const next = rest.search(/^## /m);
622
+ const stripped = (description.slice(0, start) + (next === -1 ? '' : rest.slice(next))).trim();
623
+ return stripped || title;
624
+ }
607
625
  function frozenCriteria(context) {
608
- return context.specs.flatMap(spec => (spec.acceptanceCriteria?.length ? spec.acceptanceCriteria : [spec.description || spec.title])
626
+ return context.specs.flatMap(spec => (spec.acceptanceCriteria?.length ? spec.acceptanceCriteria : [requirementFromDescription(spec.description, spec.title)])
609
627
  .map((requirement, criterionIndex) => ({ specId: String(spec.id), criterionIndex, requirement })));
610
628
  }
611
629
  /** The frozen requirements an acceptance report must certify, in scope order. */
@@ -1,5 +1,5 @@
1
1
  {
2
- "schemaVersion": "5.9",
2
+ "schemaVersion": "5.10",
3
3
  "providers": {
4
4
  "claude": {
5
5
  "cli": {
@@ -415,7 +415,7 @@
415
415
  "specificationFormat": "Architect specs are OpenSpec delta specs authored through the official fast-forward skill (ADDED/MODIFIED/REMOVED/RENAMED requirements); existing requirements are preserved through delta semantics and merged into main specs by OpenSpec archive. Complete replacement specs are not fabricated.",
416
416
  "compatibility": "Additive to integration schema 4 and execution context schema 1. Legacy workflows and profile v1 remain supported. Hosts must check RUNTIME_API_VERSION, not infer runtime support from Core major version.",
417
417
  "documentation": "docs/agent-runtime.md",
418
- "instructionsVersion": "17",
418
+ "instructionsVersion": "18",
419
419
  "workflowVersion": "7",
420
420
  "engines": [
421
421
  1,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specrails-core",
3
- "version": "6.7.0",
3
+ "version": "6.7.1",
4
4
  "description": "Agent workflow engine for specrails-desktop: provider-independent installer and programmatic agent runtime for Claude Code and Codex",
5
5
  "type": "module",
6
6
  "exports": {