mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Merge branch 'feat/subagent-report-semantics' into feat/subagent-settlement-delivery
# Conflicts: # examples/acp-agent/tests/snapshots/advanced-toolchain/session.1.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl # examples/headless-agent/tests/snapshots/compaction-recovery/session.jsonl # examples/headless-agent/tests/snapshots/pty-tools/session.jsonl
This commit is contained in:
@@ -63,6 +63,7 @@ export const SERVICE_PAGE: Record<string, string> = {
|
||||
httpServer: 'http-server.md',
|
||||
invariants: 'invariants.md',
|
||||
llm: 'llm-streaming.md',
|
||||
messageFeedback: 'feedback.md',
|
||||
permission: 'permission.md',
|
||||
planMode: 'plan.md',
|
||||
pty: 'pty.md',
|
||||
@@ -229,6 +230,25 @@ export const LINK_MAP: Readonly<Record<string, string>> = {
|
||||
ResolvedRetryPolicy: 'llm-streaming.md',
|
||||
Message: 'llm-streaming.md',
|
||||
MessageSource: 'llm-streaming.md',
|
||||
MessageFeedbackDeleteRequest: 'feedback.md',
|
||||
MessageFeedbackDeleteResult: 'feedback.md',
|
||||
MessageFeedbackDeleteValue: 'feedback.md',
|
||||
MessageFeedbackFailure: 'feedback.md',
|
||||
MessageFeedbackItem: 'feedback.md',
|
||||
MessageFeedbackListRequest: 'feedback.md',
|
||||
MessageFeedbackListResult: 'feedback.md',
|
||||
MessageFeedbackListValue: 'feedback.md',
|
||||
MessageFeedbackNoteBlank: 'feedback.md',
|
||||
MessageFeedbackNoteTooLarge: 'feedback.md',
|
||||
MessageFeedbackPutRequest: 'feedback.md',
|
||||
MessageFeedbackPutResult: 'feedback.md',
|
||||
MessageFeedbackRating: 'feedback.md',
|
||||
MessageFeedbackRejected: 'feedback.md',
|
||||
MessageFeedbackSessionNotFound: 'feedback.md',
|
||||
MessageFeedbackSuccess: 'feedback.md',
|
||||
MessageFeedbackTargetNotFound: 'feedback.md',
|
||||
MessageFeedbackVersion: 'feedback.md',
|
||||
MessageFeedbackVersionConflict: 'feedback.md',
|
||||
UserMessage: 'session.md',
|
||||
PreStepDecision: 'core.md',
|
||||
PreStepContext: 'core.md',
|
||||
|
||||
@@ -135,7 +135,7 @@ const SERVICE_ROLES: ServiceRole[] = [
|
||||
pkg: 'session',
|
||||
title: 'In-memory session store',
|
||||
mode: 'core',
|
||||
consumers: ['agent-loop', 'agent', 'session-persistence', 'session-query', 'session-query-sqlite', 'subagent-inprocess', 'invariants'],
|
||||
consumers: ['agent-loop', 'agent', 'session-persistence', 'session-query', 'session-query-sqlite', 'subagent-inprocess', 'invariants', 'message-feedback'],
|
||||
note: 'Owns append-only Session instances and emits the durable session event feed.',
|
||||
},
|
||||
{
|
||||
@@ -167,7 +167,7 @@ const SERVICE_ROLES: ServiceRole[] = [
|
||||
title: 'Durable session persistence seam',
|
||||
mode: 'seam',
|
||||
implementations: ['session-persistence-jsonl', 'session-persistence-sqlite'],
|
||||
consumers: ['agent-loop', 'tool-bash', 'hooks-claude', 'hooks-codex', 'session-query', 'session-query-sqlite'],
|
||||
consumers: ['agent-loop', 'tool-bash', 'hooks-claude', 'hooks-codex', 'session-query', 'session-query-sqlite', 'message-feedback'],
|
||||
note: 'Backends persist the same SessionEvent vocabulary; apps choose a backend at composition time.',
|
||||
},
|
||||
{
|
||||
@@ -211,9 +211,16 @@ const SERVICE_ROLES: ServiceRole[] = [
|
||||
pkg: 'storage-domain',
|
||||
title: 'Domain data facility',
|
||||
mode: 'core',
|
||||
consumers: ['workspace'],
|
||||
consumers: ['workspace', 'message-feedback'],
|
||||
note: 'Waits for every configured backend, then publishes the domain form as one lifecycle-bound service for typed durable state.',
|
||||
},
|
||||
{
|
||||
key: 'messageFeedback',
|
||||
pkg: 'message-feedback',
|
||||
title: 'Lifecycle-bound message feedback',
|
||||
mode: 'core',
|
||||
note: 'Owns local per-assistant-message feedback, lifecycle and target validation, per-item compare-and-set, and the Host unary Remote contract without entering Session history or telemetry.',
|
||||
},
|
||||
{
|
||||
key: 'workspace',
|
||||
pkg: 'workspace',
|
||||
|
||||
@@ -104,7 +104,7 @@ describe('rewriteMarkdown', () => {
|
||||
repositoryRef: 'abc123',
|
||||
})).toBe(
|
||||
'[B](./reference/b.md#part) '
|
||||
+ '[source](https://github.com/deepseek-ai/deepseek-harness-sdk/blob/abc123/packages/tool.ts#L2) '
|
||||
+ '[source](https://github.com/deepseek-ai/deepseek-harness/blob/abc123/packages/tool.ts#L2) '
|
||||
+ '[web](https://example.com)\n',
|
||||
)
|
||||
})
|
||||
@@ -130,7 +130,7 @@ describe('rewriteMarkdown', () => {
|
||||
pages,
|
||||
repoRoot: root,
|
||||
repositoryRef: 'abc123',
|
||||
})).toBe('\n')
|
||||
})).toBe('\n')
|
||||
})
|
||||
|
||||
it('hands an image to the placer and uses the URL it returns', () => {
|
||||
@@ -209,7 +209,7 @@ describe('rewriteMarkdown', () => {
|
||||
repositoryRef: 'abc123',
|
||||
})).toBe(
|
||||
'[title](./reference/b.md "b.md") '
|
||||
+ '[escaped](https://github.com/deepseek-ai/deepseek-harness-sdk/blob/abc123/docs/x(y).md)\n',
|
||||
+ '[escaped](https://github.com/deepseek-ai/deepseek-harness/blob/abc123/docs/x(y).md)\n',
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { gfm } from 'micromark-extension-gfm'
|
||||
import type { Nodes } from 'mdast'
|
||||
import { docsPages, type DocsLocale, type DocsPage } from '../website/docs.ts'
|
||||
|
||||
const REPOSITORY_URL = 'https://github.com/deepseek-ai/deepseek-harness-sdk'
|
||||
const REPOSITORY_URL = 'https://github.com/deepseek-ai/deepseek-harness'
|
||||
const root = resolve(import.meta.dirname, '..')
|
||||
const generatedRoot = resolve(root, 'website/.generated')
|
||||
|
||||
@@ -209,7 +209,7 @@ function githubTarget(
|
||||
image: boolean,
|
||||
): string {
|
||||
const path = repoPath(absPath, repoRoot)
|
||||
if (image) return `https://raw.githubusercontent.com/deepseek-ai/deepseek-harness-sdk/${repositoryRef}/${path}${suffix}`
|
||||
if (image) return `https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/${repositoryRef}/${path}${suffix}`
|
||||
const kind = lstatSync(absPath).isDirectory() ? 'tree' : 'blob'
|
||||
const lineSuffix = line === undefined ? suffix : `#L${line}`
|
||||
return `${REPOSITORY_URL}/${kind}/${repositoryRef}/${path}${lineSuffix}`
|
||||
|
||||
@@ -1744,6 +1744,101 @@
|
||||
"doc": "docs/subsystems/core.md",
|
||||
"symbol": "AgentOptions",
|
||||
"source": "packages/core/agent/src/runtime-types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackVersion",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackRating",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackItem",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackListRequest",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackListValue",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackPutRequest",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackDeleteRequest",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackDeleteValue",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackSessionNotFound",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackTargetNotFound",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackVersionConflict",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackNoteBlank",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackNoteTooLarge",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackFailure",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackSuccess",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackRejected",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackListResult",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackPutResult",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/subsystems/feedback.md",
|
||||
"symbol": "MessageFeedbackDeleteResult",
|
||||
"source": "packages/feedback/message-feedback/src/types.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,60 +1,45 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { findInternalRepositoryReferences } from './verify-public-repository-links.ts'
|
||||
import { findUnavailableRepositoryReferences } from './verify-public-repository-links.ts'
|
||||
|
||||
describe('public repository link policy', () => {
|
||||
it('rejects encoded and case-varied internal identities without blocking public repositories', () => {
|
||||
const internalOwner = ['deepseek', 'harness'].join('-')
|
||||
const internalRepository = [internalOwner, internalOwner].join('/')
|
||||
const encodedRepository = internalRepository.replaceAll('-', '%2D').replace('/', '%2F')
|
||||
const htmlEncodedRepository = internalRepository.replace('/', '/')
|
||||
const jsonEscapedRepository = internalRepository.replace('/', '\\/')
|
||||
const unicodeEscapedRepository = internalRepository.replace('/', String.raw`\u002f`)
|
||||
describe('repository link policy', () => {
|
||||
it('rejects encoded and case-varied references to the unavailable repository', () => {
|
||||
const unavailableOwner = ['deepseek', 'ai'].join('-')
|
||||
const unavailableName = ['deepseek', 'harness', 'sdk'].join('-')
|
||||
const unavailableRepository = `${unavailableOwner}/${unavailableName}`
|
||||
const encodedRepository = unavailableRepository.replaceAll('-', '%2D').replace('/', '%2F')
|
||||
const htmlEncodedRepository = unavailableRepository.replace('/', '/')
|
||||
const jsonEscapedRepository = unavailableRepository.replace('/', '\\/')
|
||||
const unicodeEscapedRepository = unavailableRepository.replace('/', String.raw`\u002f`)
|
||||
const source = [
|
||||
'https://github.com/deepseek-ai/deepseek-harness-sdk',
|
||||
`https://github.com/${internalOwner}/cordis`,
|
||||
`https://github.com/${internalRepository.toUpperCase()}/issues/1`,
|
||||
'https://github.com/deepseek-ai/deepseek-harness',
|
||||
`https://github.com/${unavailableRepository.toUpperCase()}/issues/1`,
|
||||
`https://github.com/${encodedRepository}/issues/2`,
|
||||
`https://github.com/${htmlEncodedRepository}/issues/3`,
|
||||
`"https:\\/\\/github.com\\/${jsonEscapedRepository}\\/issues\\/4"`,
|
||||
`"https:\\/\\/github.com\\/${unicodeEscapedRepository}\\/issues\\/5"`,
|
||||
`${internalOwner.toUpperCase()}#6`,
|
||||
`https://github.com/${unavailableOwner}/cordis`,
|
||||
`https://github.com/example/${unavailableName}`,
|
||||
].join('\n')
|
||||
|
||||
expect(findInternalRepositoryReferences('subject.md', source)).toEqual([
|
||||
expect(findUnavailableRepositoryReferences('subject.md', source)).toEqual([
|
||||
{ file: 'subject.md', line: 2 },
|
||||
{ file: 'subject.md', line: 3 },
|
||||
{ file: 'subject.md', line: 4 },
|
||||
{ file: 'subject.md', line: 5 },
|
||||
{ file: 'subject.md', line: 6 },
|
||||
{ file: 'subject.md', line: 7 },
|
||||
{ file: 'subject.md', line: 8 },
|
||||
])
|
||||
})
|
||||
|
||||
it('allows only the exact audited trusted-publishing repository declarations', () => {
|
||||
const internalOwner = ['deepseek', 'harness'].join('-')
|
||||
const internalRepository = [internalOwner, internalOwner].join('/')
|
||||
const repositoryUrl = `git+https://github.com/${internalRepository}.git`
|
||||
const manifestLine = ` "url": "${repositoryUrl}",`
|
||||
const constraintLine = `const repositoryUrl = '${repositoryUrl}'`
|
||||
const allowedDeclarations = [
|
||||
['native/landlock-run/packages/entry/package.json', manifestLine],
|
||||
['native/landlock-run/packages/linux-arm64/package.json', manifestLine],
|
||||
['native/landlock-run/packages/linux-x64/package.json', manifestLine],
|
||||
['scripts/check-workspace-constraints.ts', constraintLine],
|
||||
] as const
|
||||
it('preserves frozen archived Agent Notes', () => {
|
||||
const unavailableRepository = ['deepseek-ai', 'deepseek-harness-sdk'].join('/')
|
||||
|
||||
for (const [file, source] of allowedDeclarations) {
|
||||
expect(findInternalRepositoryReferences(file, source)).toEqual([])
|
||||
}
|
||||
|
||||
const wrongFile = 'native/landlock-run/package.json'
|
||||
expect(findInternalRepositoryReferences(wrongFile, manifestLine)).toEqual([{ file: wrongFile, line: 1 }])
|
||||
|
||||
const manifestFile = 'native/landlock-run/packages/entry/package.json'
|
||||
const wrongField = ` "homepage": "${repositoryUrl}",`
|
||||
expect(findInternalRepositoryReferences(manifestFile, wrongField)).toEqual([{ file: manifestFile, line: 1 }])
|
||||
|
||||
const encodedLine = manifestLine.replace('github.com/', 'github.com\\/')
|
||||
expect(findInternalRepositoryReferences(manifestFile, encodedLine)).toEqual([{ file: manifestFile, line: 1 }])
|
||||
expect(findUnavailableRepositoryReferences(
|
||||
'.agents/notes/archived/process/historical-record.md',
|
||||
`https://github.com/${unavailableRepository}`,
|
||||
)).toEqual([])
|
||||
expect(findUnavailableRepositoryReferences(
|
||||
'.agents/notes/implemented/process/active-record.md',
|
||||
`https://github.com/${unavailableRepository}`,
|
||||
)).toEqual([{ file: '.agents/notes/implemented/process/active-record.md', line: 1 }])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** Reject tracked files that expose the internal repository identity outside audited publishing declarations. */
|
||||
/** Reject tracked files that reference an unavailable legacy repository. */
|
||||
|
||||
import { execFileSync } from 'node:child_process'
|
||||
import { existsSync, lstatSync, readFileSync, readlinkSync } from 'node:fs'
|
||||
@@ -6,22 +6,13 @@ import { resolve } from 'node:path'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
|
||||
const root = resolve(import.meta.dirname, '..')
|
||||
const internalOwner = ['deepseek', 'harness'].join('-')
|
||||
const internalRepository = [internalOwner, internalOwner].join('/')
|
||||
const internalIssueShorthand = `${internalOwner}#`
|
||||
const trustedPublishingRepositoryUrl = `git+https://github.com/${internalRepository}.git`
|
||||
|
||||
/** Exact declarations that intentionally expose the source repository for trusted publishing. */
|
||||
const allowedInternalRepositoryLineByFile: Readonly<Record<string, string>> = {
|
||||
'native/landlock-run/packages/entry/package.json': `"url": "${trustedPublishingRepositoryUrl}",`,
|
||||
'native/landlock-run/packages/linux-arm64/package.json': `"url": "${trustedPublishingRepositoryUrl}",`,
|
||||
'native/landlock-run/packages/linux-x64/package.json': `"url": "${trustedPublishingRepositoryUrl}",`,
|
||||
'scripts/check-workspace-constraints.ts': `const repositoryUrl = '${trustedPublishingRepositoryUrl}'`,
|
||||
}
|
||||
const unavailableOwner = ['deepseek', 'ai'].join('-')
|
||||
const unavailableRepositoryName = ['deepseek', 'harness', 'sdk'].join('-')
|
||||
const unavailableRepository = `${unavailableOwner}/${unavailableRepositoryName}`
|
||||
const archivedAgentNotePrefix = '.agents/notes/archived/'
|
||||
|
||||
const namedReferenceCharacters: Readonly<Record<string, string>> = {
|
||||
hyphen: '-',
|
||||
num: '#',
|
||||
sol: '/',
|
||||
}
|
||||
|
||||
@@ -40,8 +31,8 @@ function canonicalReferenceText(source: string): string {
|
||||
.toLowerCase()
|
||||
}
|
||||
|
||||
/** One tracked reference to the internal repository. */
|
||||
export interface InternalRepositoryReference {
|
||||
/** One tracked reference to the unavailable repository. */
|
||||
export interface UnavailableRepositoryReference {
|
||||
/** Repository-relative file path. */
|
||||
file: string
|
||||
/** One-based source line. */
|
||||
@@ -49,20 +40,18 @@ export interface InternalRepositoryReference {
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate unaudited internal-repository references in one text file.
|
||||
* Locate unavailable-repository references in one active text file.
|
||||
* @param file - Repository-relative path used in diagnostics.
|
||||
* @param source - Text to inspect.
|
||||
* @returns every matching source line.
|
||||
* @returns every matching source line, excluding frozen archived Agent Notes.
|
||||
*/
|
||||
export function findInternalRepositoryReferences(file: string, source: string): InternalRepositoryReference[] {
|
||||
const references: InternalRepositoryReference[] = []
|
||||
export function findUnavailableRepositoryReferences(file: string, source: string): UnavailableRepositoryReference[] {
|
||||
if (file.startsWith(archivedAgentNotePrefix)) return []
|
||||
|
||||
const references: UnavailableRepositoryReference[] = []
|
||||
for (const [index, line] of source.split('\n').entries()) {
|
||||
const canonicalLine = canonicalReferenceText(line)
|
||||
const isAllowedPublishingDeclaration = line.trim() === allowedInternalRepositoryLineByFile[file]
|
||||
if (!isAllowedPublishingDeclaration
|
||||
&& (canonicalLine.includes(internalRepository) || canonicalLine.includes(internalIssueShorthand))) {
|
||||
references.push({ file, line: index + 1 })
|
||||
}
|
||||
if (canonicalLine.includes(unavailableRepository)) references.push({ file, line: index + 1 })
|
||||
}
|
||||
return references
|
||||
}
|
||||
@@ -73,8 +62,8 @@ function trackedFiles(repoRoot: string): string[] {
|
||||
.filter(file => file !== '')
|
||||
}
|
||||
|
||||
function scanRepository(repoRoot: string): InternalRepositoryReference[] {
|
||||
const references: InternalRepositoryReference[] = []
|
||||
function scanRepository(repoRoot: string): UnavailableRepositoryReference[] {
|
||||
const references: UnavailableRepositoryReference[] = []
|
||||
for (const file of trackedFiles(repoRoot)) {
|
||||
const path = resolve(repoRoot, file)
|
||||
if (!existsSync(path)) continue
|
||||
@@ -82,7 +71,7 @@ function scanRepository(repoRoot: string): InternalRepositoryReference[] {
|
||||
if (!stat.isFile() && !stat.isSymbolicLink()) continue
|
||||
const source = stat.isSymbolicLink() ? readlinkSync(path) : readFileSync(path, 'utf8')
|
||||
if (source.includes('\0')) continue
|
||||
references.push(...findInternalRepositoryReferences(file, source))
|
||||
references.push(...findUnavailableRepositoryReferences(file, source))
|
||||
}
|
||||
return references
|
||||
}
|
||||
@@ -92,9 +81,9 @@ const isMain = invokedPath !== undefined && import.meta.url === pathToFileURL(re
|
||||
if (isMain) {
|
||||
const references = scanRepository(root)
|
||||
if (references.length === 0) {
|
||||
console.log('verify-public-repository-links: tracked files expose no unexpected internal repository identity.')
|
||||
console.log('verify-public-repository-links: tracked files reference no unavailable repository.')
|
||||
} else {
|
||||
console.error('verify-public-repository-links: unexpected internal repository references found:')
|
||||
console.error('verify-public-repository-links: unavailable repository references found:')
|
||||
for (const reference of references) console.error(` ${reference.file}:${String(reference.line)}`)
|
||||
process.exitCode = 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user