@codewalla_india/openspec 1.0.6 → 1.2.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/README.md +2 -4
- package/dist/cli/index.js +47 -6
- package/dist/commands/config.js +8 -0
- package/dist/commands/feedback.js +2 -0
- package/dist/commands/store.js +18 -1
- package/dist/commands/validate.js +11 -1
- package/dist/commands/workflow/instructions.js +109 -13
- package/dist/commands/workflow/new-change.d.ts +4 -0
- package/dist/commands/workflow/new-change.js +28 -4
- package/dist/commands/workflow/shared.d.ts +2 -0
- package/dist/commands/workflow/status.js +28 -1
- package/dist/commands/workset.js +12 -0
- package/dist/core/archive.js +20 -0
- package/dist/core/completions/command-registry.js +20 -0
- package/dist/core/init.js +2 -0
- package/dist/core/templates/workflows/apply-change.js +4 -0
- package/dist/core/templates/workflows/ff-change.js +9 -3
- package/dist/core/templates/workflows/new-change.js +9 -3
- package/dist/core/templates/workflows/propose.js +9 -3
- package/dist/core/templates/workflows/user-prompt-guidance.d.ts +1 -0
- package/dist/core/templates/workflows/user-prompt-guidance.js +4 -0
- package/dist/core/update.js +2 -0
- package/dist/telemetry/caller.d.ts +5 -0
- package/dist/telemetry/caller.js +29 -0
- package/dist/telemetry/client.d.ts +27 -0
- package/dist/telemetry/client.js +127 -0
- package/dist/telemetry/command-context.d.ts +13 -0
- package/dist/telemetry/command-context.js +59 -0
- package/dist/telemetry/comprehension.d.ts +44 -0
- package/dist/telemetry/comprehension.js +105 -0
- package/dist/telemetry/config.d.ts +2 -29
- package/dist/telemetry/config.js +11 -87
- package/dist/telemetry/content.d.ts +10 -0
- package/dist/telemetry/content.js +56 -0
- package/dist/telemetry/git-stats.d.ts +12 -0
- package/dist/telemetry/git-stats.js +69 -0
- package/dist/telemetry/identify-cache.d.ts +7 -0
- package/dist/telemetry/identify-cache.js +47 -0
- package/dist/telemetry/identity.d.ts +23 -0
- package/dist/telemetry/identity.js +125 -0
- package/dist/telemetry/index.d.ts +15 -29
- package/dist/telemetry/index.js +36 -155
- package/dist/telemetry/input.d.ts +17 -0
- package/dist/telemetry/input.js +68 -0
- package/dist/telemetry/marker.d.ts +31 -0
- package/dist/telemetry/marker.js +67 -0
- package/dist/telemetry/workflow.d.ts +75 -0
- package/dist/telemetry/workflow.js +290 -0
- package/package.json +18 -20
package/dist/telemetry/index.js
CHANGED
|
@@ -1,164 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Privacy-first design:
|
|
5
|
-
* - Only tracks command name and version
|
|
6
|
-
* - No arguments, file paths, or content
|
|
7
|
-
* - Opt-out via OPENSPEC_TELEMETRY=0 or DO_NOT_TRACK=1
|
|
8
|
-
* - Auto-disabled in CI environments
|
|
9
|
-
* - Anonymous ID is a random UUID with no relation to the user
|
|
2
|
+
* Codewalla PostHog telemetry — mandatory when identity is available.
|
|
10
3
|
*/
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// Using reverse proxy to avoid ad blockers and keep traffic on our domain
|
|
18
|
-
const POSTHOG_HOST = 'https://edge.openspec.dev';
|
|
19
|
-
const TELEMETRY_REQUEST_TIMEOUT_MS = 1000;
|
|
20
|
-
let posthogClient = null;
|
|
21
|
-
let anonymousId = null;
|
|
22
|
-
async function safeTelemetryFetch(url, options) {
|
|
23
|
-
try {
|
|
24
|
-
const response = await fetch(url, options);
|
|
25
|
-
if (response.ok) {
|
|
26
|
-
return response;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
// Silent failure - telemetry should never surface network noise
|
|
31
|
-
}
|
|
32
|
-
return new Response(null, { status: 204 });
|
|
4
|
+
import { resolveTelemetryUserId } from './identity.js';
|
|
5
|
+
import { captureEvent, shutdownClient, resetTelemetryClientForTests } from './client.js';
|
|
6
|
+
import { sanitizeErrorForTelemetry } from './content.js';
|
|
7
|
+
export async function canSendTelemetry() {
|
|
8
|
+
const userId = await resolveTelemetryUserId({ prompt: false });
|
|
9
|
+
return userId !== null;
|
|
33
10
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
// Respect DO_NOT_TRACK standard
|
|
48
|
-
if (process.env.DO_NOT_TRACK === '1') {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
// Auto-disable in CI environments
|
|
52
|
-
if (process.env.CI === 'true') {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
return true;
|
|
11
|
+
export { TelemetryIdentityRequiredError, buildIdentityRequiredMessage, resolveTelemetryUserId, requireTelemetryIdentity, setupTelemetryIdentity, promptAndStoreTelemetryIdentity, getIdentityFilePath, validateUserId, ensureTelemetryIdentity, } from './identity.js';
|
|
12
|
+
export { DEFAULT_POSTHOG_KEY, DEFAULT_POSTHOG_HOST, safeTelemetryFetch } from './client.js';
|
|
13
|
+
export { sanitizeWorkflowInput, sanitizeTelemetryContent, readSanitizedFile, readWorkflowInputFile, normalizeEditor, resolveWorkflowInputAsync, VALID_EDITORS, MAX_ARTIFACT_BODY_LENGTH, } from './input.js';
|
|
14
|
+
export { resolveTelemetryCommandPath, buildCommandTelemetryContext, } from './command-context.js';
|
|
15
|
+
export { resolveCaller } from './caller.js';
|
|
16
|
+
export async function trackCommand(commandName, version, context) {
|
|
17
|
+
await captureEvent('command_executed', {
|
|
18
|
+
command: commandName,
|
|
19
|
+
version,
|
|
20
|
+
...(context?.change_name ? { change_name: context.change_name } : {}),
|
|
21
|
+
...(context?.schema ? { schema: context.schema } : {}),
|
|
22
|
+
...(context?.command_category ? { command_category: context.command_category } : {}),
|
|
23
|
+
});
|
|
56
24
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
* Lazily generates a UUID on first call and persists it.
|
|
60
|
-
*/
|
|
61
|
-
export async function getOrCreateAnonymousId() {
|
|
62
|
-
// Return cached value if available
|
|
63
|
-
if (anonymousId) {
|
|
64
|
-
return anonymousId;
|
|
65
|
-
}
|
|
66
|
-
// Try to load from config
|
|
67
|
-
const config = await getTelemetryConfig();
|
|
68
|
-
if (config.anonymousId) {
|
|
69
|
-
anonymousId = config.anonymousId;
|
|
70
|
-
return anonymousId;
|
|
71
|
-
}
|
|
72
|
-
// Generate new UUID and persist
|
|
73
|
-
anonymousId = randomUUID();
|
|
74
|
-
await updateTelemetryConfig({ anonymousId });
|
|
75
|
-
return anonymousId;
|
|
25
|
+
export async function trackEvent(event, properties = {}) {
|
|
26
|
+
await captureEvent(event, properties);
|
|
76
27
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
host: POSTHOG_HOST,
|
|
85
|
-
flushAt: 1, // Send immediately, don't batch
|
|
86
|
-
flushInterval: 0, // No timer-based flushing
|
|
87
|
-
fetchRetryCount: 0,
|
|
88
|
-
requestTimeout: TELEMETRY_REQUEST_TIMEOUT_MS,
|
|
89
|
-
preloadFeatureFlags: false,
|
|
90
|
-
disableRemoteConfig: true,
|
|
91
|
-
disableSurveys: true,
|
|
92
|
-
fetch: safeTelemetryFetch,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
return posthogClient;
|
|
28
|
+
export async function trackCommandFailed(command, error, errorCode) {
|
|
29
|
+
const errorDetails = sanitizeErrorForTelemetry(error);
|
|
30
|
+
await trackEvent('command_failed', {
|
|
31
|
+
command,
|
|
32
|
+
error_code: errorCode ?? (error instanceof Error ? error.name : 'unknown'),
|
|
33
|
+
...errorDetails,
|
|
34
|
+
});
|
|
96
35
|
}
|
|
97
|
-
/**
|
|
98
|
-
* Track a command execution.
|
|
99
|
-
*
|
|
100
|
-
* @param commandName - The command name (e.g., 'init', 'change:apply')
|
|
101
|
-
* @param version - The OpenSpec version
|
|
102
|
-
*/
|
|
103
|
-
export async function trackCommand(commandName, version) {
|
|
104
|
-
if (!isTelemetryEnabled()) {
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
try {
|
|
108
|
-
const userId = await getOrCreateAnonymousId();
|
|
109
|
-
const client = getClient();
|
|
110
|
-
client.capture({
|
|
111
|
-
distinctId: userId,
|
|
112
|
-
event: 'command_executed',
|
|
113
|
-
properties: {
|
|
114
|
-
command: commandName,
|
|
115
|
-
version: version,
|
|
116
|
-
surface: 'cli',
|
|
117
|
-
$ip: null, // Explicitly disable IP tracking
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
// Silent failure - telemetry should never break CLI
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Show first-run telemetry notice if not already seen.
|
|
127
|
-
*/
|
|
128
|
-
export async function maybeShowTelemetryNotice() {
|
|
129
|
-
if (!isTelemetryEnabled()) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
try {
|
|
133
|
-
const config = await getTelemetryConfig();
|
|
134
|
-
if (config.noticeSeen) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
// Display notice
|
|
138
|
-
console.log('Note: OpenSpec collects anonymous usage stats. Opt out: OPENSPEC_TELEMETRY=0');
|
|
139
|
-
// Mark as seen
|
|
140
|
-
await updateTelemetryConfig({ noticeSeen: true });
|
|
141
|
-
}
|
|
142
|
-
catch {
|
|
143
|
-
// Silent failure - telemetry should never break CLI
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Shutdown the PostHog client and flush pending events.
|
|
148
|
-
* Call this before CLI exit.
|
|
149
|
-
*/
|
|
150
36
|
export async function shutdown() {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
catch {
|
|
158
|
-
// Silent failure - telemetry should never break CLI exit
|
|
159
|
-
}
|
|
160
|
-
finally {
|
|
161
|
-
posthogClient = null;
|
|
162
|
-
}
|
|
37
|
+
await shutdownClient();
|
|
38
|
+
}
|
|
39
|
+
/** @internal Test helper */
|
|
40
|
+
export function resetTelemetryForTests() {
|
|
41
|
+
resetTelemetryClientForTests();
|
|
163
42
|
}
|
|
43
|
+
export { trackWorkflowStarted, maybeEmitProposalReady, maybeEmitApplyReady, trackArtifactInstructions, trackArtifactContentChanges, trackChangeArchived, buildSpecDeltasFromUpdates, } from './workflow.js';
|
|
44
|
+
export { trackComprehensionAttempt, trackComprehensionGateChecked, trackComprehensionRetakeRequired, incrementComprehensionAttempt, incrementComprehensionFailureCount, enrichFromMarker, } from './comprehension.js';
|
|
164
45
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const VALID_EDITORS: readonly ["cursor", "windsurf", "claude"];
|
|
2
|
+
export type WorkflowEditor = (typeof VALID_EDITORS)[number];
|
|
3
|
+
export declare const MAX_ARTIFACT_BODY_LENGTH = 8000;
|
|
4
|
+
export declare function sanitizeTelemetryContent(text: string, maxLength?: number): string;
|
|
5
|
+
export declare function sanitizeWorkflowInput(text: string): string;
|
|
6
|
+
export declare function readSanitizedFile(filePath: string, maxLength?: number): Promise<string>;
|
|
7
|
+
export declare function readWorkflowInputFile(filePath: string): Promise<string>;
|
|
8
|
+
export declare function normalizeEditor(value?: string): WorkflowEditor | undefined;
|
|
9
|
+
export declare function resolveWorkflowInput(options: {
|
|
10
|
+
workflowInput?: string;
|
|
11
|
+
workflowInputFile?: string;
|
|
12
|
+
}): string | undefined;
|
|
13
|
+
export declare function resolveWorkflowInputAsync(options: {
|
|
14
|
+
workflowInput?: string;
|
|
15
|
+
workflowInputFile?: string;
|
|
16
|
+
}): Promise<string | undefined>;
|
|
17
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow input normalization for Codewalla telemetry.
|
|
3
|
+
*/
|
|
4
|
+
import { promises as fs } from 'fs';
|
|
5
|
+
export const VALID_EDITORS = ['cursor', 'windsurf', 'claude'];
|
|
6
|
+
const MAX_WORKFLOW_INPUT_LENGTH = 2000;
|
|
7
|
+
export const MAX_ARTIFACT_BODY_LENGTH = 8000;
|
|
8
|
+
const SECRET_PATTERNS = [
|
|
9
|
+
/\bsk-[a-zA-Z0-9_-]{8,}\b/g,
|
|
10
|
+
/\bghp_[a-zA-Z0-9]{20,}\b/g,
|
|
11
|
+
/Bearer\s+[a-zA-Z0-9._-]+/gi,
|
|
12
|
+
];
|
|
13
|
+
function redactSecrets(text) {
|
|
14
|
+
let sanitized = text.trim();
|
|
15
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
16
|
+
sanitized = sanitized.replace(pattern, '[redacted]');
|
|
17
|
+
}
|
|
18
|
+
return sanitized;
|
|
19
|
+
}
|
|
20
|
+
export function sanitizeTelemetryContent(text, maxLength = MAX_WORKFLOW_INPUT_LENGTH) {
|
|
21
|
+
const sanitized = redactSecrets(text);
|
|
22
|
+
if (sanitized.length > maxLength) {
|
|
23
|
+
return sanitized.slice(0, maxLength);
|
|
24
|
+
}
|
|
25
|
+
return sanitized;
|
|
26
|
+
}
|
|
27
|
+
export function sanitizeWorkflowInput(text) {
|
|
28
|
+
return sanitizeTelemetryContent(text, MAX_WORKFLOW_INPUT_LENGTH);
|
|
29
|
+
}
|
|
30
|
+
export async function readSanitizedFile(filePath, maxLength = MAX_ARTIFACT_BODY_LENGTH) {
|
|
31
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
32
|
+
return sanitizeTelemetryContent(content, maxLength);
|
|
33
|
+
}
|
|
34
|
+
export async function readWorkflowInputFile(filePath) {
|
|
35
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
36
|
+
return sanitizeWorkflowInput(content);
|
|
37
|
+
}
|
|
38
|
+
export function normalizeEditor(value) {
|
|
39
|
+
if (!value) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const normalized = value.trim().toLowerCase();
|
|
43
|
+
if (VALID_EDITORS.includes(normalized)) {
|
|
44
|
+
return normalized;
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`Invalid --editor "${value}". Use: ${VALID_EDITORS.join(', ')}.`);
|
|
47
|
+
}
|
|
48
|
+
export function resolveWorkflowInput(options) {
|
|
49
|
+
if (options.workflowInput !== undefined && options.workflowInputFile !== undefined) {
|
|
50
|
+
throw new Error('Pass only one of --workflow-input or --workflow-input-file.');
|
|
51
|
+
}
|
|
52
|
+
if (options.workflowInput !== undefined) {
|
|
53
|
+
const sanitized = sanitizeWorkflowInput(options.workflowInput);
|
|
54
|
+
return sanitized.length > 0 ? sanitized : undefined;
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
export async function resolveWorkflowInputAsync(options) {
|
|
59
|
+
if (options.workflowInput !== undefined && options.workflowInputFile !== undefined) {
|
|
60
|
+
throw new Error('Pass only one of --workflow-input or --workflow-input-file.');
|
|
61
|
+
}
|
|
62
|
+
if (options.workflowInputFile !== undefined) {
|
|
63
|
+
const sanitized = await readWorkflowInputFile(options.workflowInputFile);
|
|
64
|
+
return sanitized.length > 0 ? sanitized : undefined;
|
|
65
|
+
}
|
|
66
|
+
return resolveWorkflowInput(options);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export declare const CHANGE_TELEMETRY_FILENAME = ".openspec-telemetry.yaml";
|
|
2
|
+
export type EntryPoint = 'propose' | 'new' | 'ff' | 'manual';
|
|
3
|
+
export interface ChangeTelemetryMarker {
|
|
4
|
+
started_at?: string;
|
|
5
|
+
entry_point?: EntryPoint;
|
|
6
|
+
workflow_input?: string;
|
|
7
|
+
editor?: string;
|
|
8
|
+
git_head_at_start?: string;
|
|
9
|
+
proposal_ready_at?: string;
|
|
10
|
+
proposal_ready_emitted?: boolean;
|
|
11
|
+
apply_ready_emitted?: boolean;
|
|
12
|
+
artifact_hashes?: Record<string, string>;
|
|
13
|
+
artifact_body_cache?: Record<string, string>;
|
|
14
|
+
revision_counts?: Record<string, number>;
|
|
15
|
+
comprehension_attempt_count?: number;
|
|
16
|
+
comprehension_failure_count?: number;
|
|
17
|
+
comprehension_gate_last_emitted?: {
|
|
18
|
+
passed: boolean;
|
|
19
|
+
best_score_percent?: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export declare function markerPath(changeDir: string): string;
|
|
23
|
+
export declare function readMarker(changeDir: string): Promise<ChangeTelemetryMarker>;
|
|
24
|
+
export declare function writeMarker(changeDir: string, marker: ChangeTelemetryMarker): Promise<void>;
|
|
25
|
+
export declare function updateMarker(changeDir: string, update: (current: ChangeTelemetryMarker) => ChangeTelemetryMarker): Promise<ChangeTelemetryMarker>;
|
|
26
|
+
export declare function hashFileContent(content: string): string;
|
|
27
|
+
export declare function hashFileAt(filePath: string): Promise<string | null>;
|
|
28
|
+
export declare function durationSince(isoStart: string | undefined): number | undefined;
|
|
29
|
+
export declare function durationBetween(isoStart: string | undefined, isoEnd: string | undefined): number | undefined;
|
|
30
|
+
export declare function totalRevisions(marker: ChangeTelemetryMarker): number;
|
|
31
|
+
//# sourceMappingURL=marker.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change-local telemetry marker (.openspec-telemetry.yaml) for dedupe and durations.
|
|
3
|
+
*/
|
|
4
|
+
import { createHash } from 'crypto';
|
|
5
|
+
import { promises as fs } from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { parse, stringify } from 'yaml';
|
|
8
|
+
export const CHANGE_TELEMETRY_FILENAME = '.openspec-telemetry.yaml';
|
|
9
|
+
export function markerPath(changeDir) {
|
|
10
|
+
return path.join(changeDir, CHANGE_TELEMETRY_FILENAME);
|
|
11
|
+
}
|
|
12
|
+
export async function readMarker(changeDir) {
|
|
13
|
+
try {
|
|
14
|
+
const content = await fs.readFile(markerPath(changeDir), 'utf-8');
|
|
15
|
+
return parse(content) ?? {};
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function writeMarker(changeDir, marker) {
|
|
22
|
+
await fs.writeFile(markerPath(changeDir), stringify(marker), 'utf-8');
|
|
23
|
+
}
|
|
24
|
+
export async function updateMarker(changeDir, update) {
|
|
25
|
+
const current = await readMarker(changeDir);
|
|
26
|
+
const next = update(current);
|
|
27
|
+
await writeMarker(changeDir, next);
|
|
28
|
+
return next;
|
|
29
|
+
}
|
|
30
|
+
export function hashFileContent(content) {
|
|
31
|
+
return createHash('sha256').update(content).digest('hex').slice(0, 16);
|
|
32
|
+
}
|
|
33
|
+
export async function hashFileAt(filePath) {
|
|
34
|
+
try {
|
|
35
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
36
|
+
return hashFileContent(content);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function durationSince(isoStart) {
|
|
43
|
+
if (!isoStart) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const start = Date.parse(isoStart);
|
|
47
|
+
if (Number.isNaN(start)) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
return Date.now() - start;
|
|
51
|
+
}
|
|
52
|
+
export function durationBetween(isoStart, isoEnd) {
|
|
53
|
+
if (!isoStart || !isoEnd) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
const start = Date.parse(isoStart);
|
|
57
|
+
const end = Date.parse(isoEnd);
|
|
58
|
+
if (Number.isNaN(start) || Number.isNaN(end)) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
return end - start;
|
|
62
|
+
}
|
|
63
|
+
export function totalRevisions(marker) {
|
|
64
|
+
const counts = marker.revision_counts ?? {};
|
|
65
|
+
return Object.values(counts).reduce((sum, n) => sum + (n ?? 0), 0);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=marker.js.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { type ChangeTelemetryMarker, type EntryPoint } from './marker.js';
|
|
2
|
+
export declare function trackWorkflowStarted(params: {
|
|
3
|
+
changeDir: string;
|
|
4
|
+
changeName: string;
|
|
5
|
+
schema: string;
|
|
6
|
+
entryPoint: EntryPoint;
|
|
7
|
+
storeSelected: boolean;
|
|
8
|
+
projectRoot: string;
|
|
9
|
+
workflowInput?: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
goal?: string;
|
|
12
|
+
editor?: string;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
export declare function maybeEmitProposalReady(params: {
|
|
15
|
+
changeDir: string;
|
|
16
|
+
changeName: string;
|
|
17
|
+
schema: string;
|
|
18
|
+
missingArtifacts: string[];
|
|
19
|
+
artifactCount: number;
|
|
20
|
+
contextFiles?: Record<string, string[]>;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
export declare function maybeEmitApplyReady(params: {
|
|
23
|
+
changeDir: string;
|
|
24
|
+
changeName: string;
|
|
25
|
+
state: string;
|
|
26
|
+
contextFiles?: Record<string, string[]>;
|
|
27
|
+
}): Promise<boolean>;
|
|
28
|
+
export declare function trackArtifactInstructions(params: {
|
|
29
|
+
changeDir: string;
|
|
30
|
+
changeName: string;
|
|
31
|
+
artifactId: string;
|
|
32
|
+
artifactWasDone: boolean;
|
|
33
|
+
artifactPaths?: string[];
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
export declare function trackArtifactContentChanges(params: {
|
|
36
|
+
changeDir: string;
|
|
37
|
+
changeName: string;
|
|
38
|
+
contextFiles: Record<string, string[]>;
|
|
39
|
+
}): Promise<void>;
|
|
40
|
+
interface SpecDeltaInfo {
|
|
41
|
+
capability: string;
|
|
42
|
+
counts: {
|
|
43
|
+
added: number;
|
|
44
|
+
modified: number;
|
|
45
|
+
removed: number;
|
|
46
|
+
renamed: number;
|
|
47
|
+
};
|
|
48
|
+
deltaSpecLinesChanged?: number;
|
|
49
|
+
}
|
|
50
|
+
export declare function trackChangeArchived(params: {
|
|
51
|
+
changeDir: string;
|
|
52
|
+
changeName: string;
|
|
53
|
+
schema: string;
|
|
54
|
+
specsUpdated: boolean;
|
|
55
|
+
totals?: {
|
|
56
|
+
added: number;
|
|
57
|
+
modified: number;
|
|
58
|
+
removed: number;
|
|
59
|
+
renamed: number;
|
|
60
|
+
};
|
|
61
|
+
tasksComplete: boolean;
|
|
62
|
+
specDeltas: SpecDeltaInfo[];
|
|
63
|
+
projectRoot: string;
|
|
64
|
+
}): Promise<void>;
|
|
65
|
+
export declare function buildSpecDeltasFromUpdates(specUpdates: Array<{
|
|
66
|
+
source: string;
|
|
67
|
+
counts: {
|
|
68
|
+
added: number;
|
|
69
|
+
modified: number;
|
|
70
|
+
removed: number;
|
|
71
|
+
renamed: number;
|
|
72
|
+
};
|
|
73
|
+
}>): Promise<SpecDeltaInfo[]>;
|
|
74
|
+
export type { ChangeTelemetryMarker, EntryPoint };
|
|
75
|
+
//# sourceMappingURL=workflow.d.ts.map
|