test(agents): what a consumer's AGENTS.md gets, and what stays put
The merge on its own: the section is appended after one blank line,
merging again changes nothing, a moved section is rewritten where it
stands, and removing it gives the file its own bytes back. Markers
inside a fenced block, one quoting a fenced block of its own, are not
the section's. Unbalanced markers, a document that ends inside a code
block and notes that would break the section are refused, naming the
line.
End to end, through LoadProject on a staged fixture: app names lib
and has tool as host tooling; lib builds against base and has libtool
as its own. Transitive gives tool, lib and base in that order, and
neither app's own notes nor libtool's. A second update writes nothing,
mtime included. Direct drops base, edited notes replace the old ones
in the one section, and None restores the original bytes. A project
without an AGENTS.md does not get one, and a symlinked AGENTS.md is
written through the link, which stays a link. Through Run in process,
lint and run leave the file alone, while `test --list` and a build
that fails at the link both refresh it.
The fixture's AGENTS.md is checked in as AGENTS.md.in: an AGENTS.md in
this tree would read as instructions for the agents working on it.
Moving the CLI hook above the run and lint branches, or letting Direct
walk past the first loaded project, fails four of the checks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 03:18:21 +01:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
|
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
|
|
|
|
|
|
|
|
|
import std;
|
|
|
|
|
import Crafter.Build;
|
|
|
|
|
#pragma crafter dependency "../tool"
|
|
|
|
|
using namespace Crafter;
|
|
|
|
|
|
|
|
|
|
// The consumer whose AGENTS.md the test watches. It names lib itself, reaches
|
|
|
|
|
// base only through lib, and uses tool as host tooling. Its own
|
|
|
|
|
// AGENTS.consumer.md is for its consumers and must never land in its own
|
test(agents): the cases the review found
Each fixed finding gets a check that fails without its fix: inline code
and a list item's fence, a section removed from between two paragraphs,
a section before an unclosed fence, a CRLF file, no error when there is
nothing to write, a hard-linked and a read-only AGENTS.md, a dependency
whose project file sits in the consumer's own directory, a test's
dependency, and `test --list`. The read-only case needs an ordinary
user, since root writes through the permission bits, and is skipped
under root.
The merge cases go through a helper that counts a throw as a failure,
so one regression no longer ends the run before the cases after it. A
passing run removes its staged copy, whose builds leave a std PCM per
configuration in a tmpfs.
Reverting the inline-code rule, the own-notes exclusion, the skipping
of tests, the `test --list` guard or the paragraph-preserving removal
each fails its check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 05:02:36 +01:00
|
|
|
// AGENTS.md, not even through helper, a dependency whose project file sits
|
|
|
|
|
// beside this one. testonly is only a test's dependency.
|
test(agents): what a consumer's AGENTS.md gets, and what stays put
The merge on its own: the section is appended after one blank line,
merging again changes nothing, a moved section is rewritten where it
stands, and removing it gives the file its own bytes back. Markers
inside a fenced block, one quoting a fenced block of its own, are not
the section's. Unbalanced markers, a document that ends inside a code
block and notes that would break the section are refused, naming the
line.
End to end, through LoadProject on a staged fixture: app names lib
and has tool as host tooling; lib builds against base and has libtool
as its own. Transitive gives tool, lib and base in that order, and
neither app's own notes nor libtool's. A second update writes nothing,
mtime included. Direct drops base, edited notes replace the old ones
in the one section, and None restores the original bytes. A project
without an AGENTS.md does not get one, and a symlinked AGENTS.md is
written through the link, which stays a link. Through Run in process,
lint and run leave the file alone, while `test --list` and a build
that fails at the link both refresh it.
The fixture's AGENTS.md is checked in as AGENTS.md.in: an AGENTS.md in
this tree would read as instructions for the agents working on it.
Moving the CLI hook above the run and lint branches, or letting Direct
walk past the first loaded project, fails four of the checks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 03:18:21 +01:00
|
|
|
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view>) {
|
|
|
|
|
Configuration cfg;
|
|
|
|
|
cfg.path = "./";
|
|
|
|
|
cfg.name = "app";
|
|
|
|
|
cfg.outputName = "app";
|
|
|
|
|
cfg.type = ConfigurationType::Executable;
|
|
|
|
|
// Against the working directory, as with `cd app && crafter-build`.
|
test(agents): the cases the review found
Each fixed finding gets a check that fails without its fix: inline code
and a list item's fence, a section removed from between two paragraphs,
a section before an unclosed fence, a CRLF file, no error when there is
nothing to write, a hard-linked and a read-only AGENTS.md, a dependency
whose project file sits in the consumer's own directory, a test's
dependency, and `test --list`. The read-only case needs an ordinary
user, since root writes through the permission bits, and is skipped
under root.
The merge cases go through a helper that counts a throw as a failure,
so one regression no longer ends the run before the cases after it. A
passing run removes its staged copy, whose builds leave a std PCM per
configuration in a tmpfs.
Reverting the inline-code rule, the own-notes exclusion, the skipping
of tests, the `test --list` guard or the paragraph-preserving removal
each fails its check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 05:02:36 +01:00
|
|
|
cfg.dependencies = {
|
|
|
|
|
LocalProject({ .projectFile = "../lib/project.cpp" }),
|
|
|
|
|
LocalProject({ .projectFile = "helper.cpp" }),
|
|
|
|
|
};
|
|
|
|
|
cfg.AddTest("t").Dependencies({ LocalProject({ .projectFile = "../testonly/project.cpp" }) });
|
test(agents): what a consumer's AGENTS.md gets, and what stays put
The merge on its own: the section is appended after one blank line,
merging again changes nothing, a moved section is rewritten where it
stands, and removing it gives the file its own bytes back. Markers
inside a fenced block, one quoting a fenced block of its own, are not
the section's. Unbalanced markers, a document that ends inside a code
block and notes that would break the section are refused, naming the
line.
End to end, through LoadProject on a staged fixture: app names lib
and has tool as host tooling; lib builds against base and has libtool
as its own. Transitive gives tool, lib and base in that order, and
neither app's own notes nor libtool's. A second update writes nothing,
mtime included. Direct drops base, edited notes replace the old ones
in the one section, and None restores the original bytes. A project
without an AGENTS.md does not get one, and a symlinked AGENTS.md is
written through the link, which stays a link. Through Run in process,
lint and run leave the file alone, while `test --list` and a build
that fails at the link both refresh it.
The fixture's AGENTS.md is checked in as AGENTS.md.in: an AGENTS.md in
this tree would read as instructions for the agents working on it.
Moving the CLI hook above the run and lint branches, or letting Direct
walk past the first loaded project, fails four of the checks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 03:18:21 +01:00
|
|
|
return cfg;
|
|
|
|
|
}
|